diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
commit | c7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch) | |
tree | 3682407a599b8f9f03fc096298134cafba1c9b2f /drivers/video | |
parent | 1d793fade8b063fde3cf275bf1a5c2d381292cd9 (diff) |
o Merge with Linux 2.1.116.
o New Newport console code.
o New G364 console code.
Diffstat (limited to 'drivers/video')
85 files changed, 26327 insertions, 3305 deletions
diff --git a/drivers/video/Config.in b/drivers/video/Config.in index b4766876b..82d77bd12 100644 --- a/drivers/video/Config.in +++ b/drivers/video/Config.in @@ -3,10 +3,10 @@ # if [ "$CONFIG_FB" = "y" ]; then - - mainmenu_option next_comment - comment 'Frame buffer devices' - + define_bool CONFIG_DUMMY_CONSOLE y + if [ "$CONFIG_ARCH_ACORN" = "y" ]; then + bool 'Acorn VIDC support' CONFIG_FB_ACORN + fi if [ "$CONFIG_APOLLO" = "y" ]; then define_bool CONFIG_FB_APOLLO y fi @@ -17,10 +17,13 @@ if [ "$CONFIG_FB" = "y" ]; then bool 'Amiga ECS chipset support' CONFIG_FB_AMIGA_ECS bool 'Amiga AGA chipset support' CONFIG_FB_AMIGA_AGA fi + fi + if [ "$CONFIG_ZORRO" = "y" ]; then 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 + tristate 'Amiga CLgen driver' CONFIG_FB_CLGEN fi fi if [ "$CONFIG_ATARI" = "y" ]; then @@ -29,87 +32,236 @@ if [ "$CONFIG_FB" = "y" ]; then 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 "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 + 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 + if [ "$CONFIG_HP300" = "y" ]; then + define_bool CONFIG_FB_HP300 y + fi + # I used CONFIG_ARM here because the ARCH construct doesn't seem to work + # with xconfig. --pb + if [ "$ARCH" = "i386" -o "$ARCH" = "alpha" -o "$ARCH" = "ppc" -o \ + "$CONFIG_ARM" = "y" ]; then + if [ "$CONFIG_ARM" != "y" -o "$CONFIG_ARCH_ACORN" != "y" ] ; then + tristate 'VGA chipset support (text only)' CONFIG_FB_VGA + fi + fi + if [ "$ARCH" = "alpha" ]; then + tristate 'TGA framebuffer support' CONFIG_FB_TGA + fi + if [ "$ARCH" = "i386" ]; then + bool 'VESA VGA graphics console' CONFIG_FB_VESA + define_bool CONFIG_VIDEO_SELECT y + tristate 'MDA dual-headed support' CONFIG_FB_MDA + fi + if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then + bool 'SBUS and UPA framebuffers' CONFIG_FB_SBUS + if [ "$CONFIG_FB_SBUS" != "n" ]; then + if [ "$ARCH" = "sparc64" ]; then + bool ' Creator/Creator3D support' CONFIG_FB_CREATOR + fi + bool ' CGsix (GX,TurboGX) support' CONFIG_FB_CGSIX + bool ' BWtwo support' CONFIG_FB_BWTWO + bool ' CGthree support' CONFIG_FB_CGTHREE + if [ "$ARCH" = "sparc" ]; then + bool ' TCX (SS4/SS5 only) support' CONFIG_FB_TCX + fi + fi + fi + if [ "$ARCH" = "sparc64" ]; then + if [ "$CONFIG_PCI" != "n" ]; then + bool 'PCI framebuffers' CONFIG_FB_PCI + if [ "$CONFIG_FB_PCI" != "n" ]; then + bool ' ATI Mach64 display support' CONFIG_FB_ATY + fi + fi fi 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 - 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 + tristate 'Monochrome support' CONFIG_FBCON_MFB + tristate '2 bpp packed pixels support' CONFIG_FBCON_CFB2 + tristate '4 bpp packed pixels support' CONFIG_FBCON_CFB4 + tristate '8 bpp packed pixels support' CONFIG_FBCON_CFB8 + tristate '16 bpp packed pixels support' CONFIG_FBCON_CFB16 + tristate '24 bpp packed pixels support' CONFIG_FBCON_CFB24 + tristate '32 bpp packed pixels support' CONFIG_FBCON_CFB32 + tristate 'Amiga bitplanes support' CONFIG_FBCON_AFB + tristate 'Amiga interleaved bitplanes support' CONFIG_FBCON_ILBM + 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 'Atari interleaved bitplanes (16 planes) support' CONFIG_FBCON_IPLAN2P16 + tristate 'Mac variable bpp packed pixels support' CONFIG_FBCON_MAC + tristate 'VGA characters/attributes support' CONFIG_FBCON_VGA else - 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 + # Guess what we need + if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_AMIGA" = "y" -o \ + "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \ + "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_RETINAZ3" = "y" -o \ + "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ + "$CONFIG_FB_BWTWO" = "y" -o "$CONFIG_FB_CLGEN" = "y" ]; then define_bool CONFIG_FBCON_MFB y + else + if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_AMIGA" = "m" -o \ + "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \ + "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_RETINAZ3" = "m" -o \ + "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ + "$CONFIG_FB_BWTWO" = "m" -o "$CONFIG_FB_CLGEN" = "m" ]; then + define_bool CONFIG_FBCON_MFB m + fi fi - if [ "$CONFIG_FB_AMIGA" = "y" -o "$CONFIG_FB_AMIGA" = "m" ]; then - define_bool CONFIG_FBCON_ILBM y + if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ + "$CONFIG_FB_VIRTUAL" = "y" ]; then + define_bool CONFIG_FBCON_CFB2 y + define_bool CONFIG_FBCON_CFB4 y + else + if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_MAC" = "m" -o \ + "$CONFIG_FB_VIRTUAL" = "m" ]; then + define_bool CONFIG_FBCON_CFB2 m + define_bool CONFIG_FBCON_CFB4 m + fi + fi + if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_ATARI" = "y" -o \ + "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ + "$CONFIG_FB_OF" = "y" -o "$CONFIG_FB_TGA" = "y" -o \ + "$CONFIG_FB_VESA" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ + "$CONFIG_FB_TCX" = "y" -o "$CONFIG_FB_CGTHREE" = "y" -o \ + "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" ]; then + define_bool CONFIG_FBCON_CFB8 y + else + if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \ + "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ + "$CONFIG_FB_OF" = "m" -o "$CONFIG_FB_TGA" = "m" -o \ + "$CONFIG_FB_VESA" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ + "$CONFIG_FB_TCX" = "m" -o "$CONFIG_FB_CGTHREE" = "m" -o \ + "$CONFIG_FB_CONTROL" = "m" ]; then + define_bool CONFIG_FBCON_CFB8 m + fi + fi + if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \ + "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_VESA" = "y" -o \ + "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \ + "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" ]; then + define_bool CONFIG_FBCON_CFB16 y + else + if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ + "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_VESA" = "m" -o \ + "$CONFIG_FB_VIRTUAL" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \ + "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" ]; then + define_bool CONFIG_FBCON_CFB16 m + fi + fi + if [ "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ + "$CONFIG_FB_CLGEN" = "y" ]; then + define_bool CONFIG_FBCON_CFB24 y + else + if [ "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ + "$CONFIG_FB_CLGEN" = "m" ]; then + define_bool CONFIG_FBCON_CFB24 m + fi + fi + if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \ + "$CONFIG_FB_VESA" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ + "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" ]; then + define_bool CONFIG_FBCON_CFB32 y + else + if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ + "$CONFIG_FB_VESA" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ + "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" ]; then + define_bool CONFIG_FBCON_CFB32 m + fi + fi + if [ "$CONFIG_FB_AMIGA" = "y" ]; then define_bool CONFIG_FBCON_AFB y + define_bool CONFIG_FBCON_ILBM y + else + if [ "$CONFIG_FB_AMIGA" = "m" ]; then + define_bool CONFIG_FBCON_AFB m + define_bool CONFIG_FBCON_ILBM m + fi fi - if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATARI" = "m" ]; then + if [ "$CONFIG_FB_ATARI" = "y" ]; then define_bool CONFIG_FBCON_IPLAN2P2 y define_bool CONFIG_FBCON_IPLAN2P4 y define_bool CONFIG_FBCON_IPLAN2P8 y +# define_bool CONFIG_FBCON_IPLAN2P16 y + else + if [ "$CONFIG_FB_ATARI" = "m" ]; then + define_bool CONFIG_FBCON_IPLAN2P2 m + define_bool CONFIG_FBCON_IPLAN2P4 m + define_bool CONFIG_FBCON_IPLAN2P8 m +# define_bool CONFIG_FBCON_IPLAN2P16 m + fi fi - if [ "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_MAC" = "m" -o \ - "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then + if [ "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" ]; then define_bool CONFIG_FBCON_MAC y - define_bool CONFIG_FBCON_CFB2 y - define_bool CONFIG_FBCON_CFB4 y + else + if [ "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then + define_bool CONFIG_FBCON_MAC m + fi fi - if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATARI" = "m" -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 + if [ "$CONFIG_FB_MDA" = "y" -o "$CONFIG_FB_VGA" = "y" ]; then + define_bool CONFIG_FBCON_VGA y + else + if [ "$CONFIG_FB_MDA" = "m" -o "$CONFIG_FB_VGA" = "m" ]; then + define_bool CONFIG_FBCON_VGA m + fi 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 + bool 'Support only 8 pixels wide fonts' CONFIG_FBCON_FONTWIDTH8_ONLY + if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then + bool 'Sparc console 8x16 font' CONFIG_FONT_SUN8x16 + if [ "$CONFIG_FBCON_FONTWIDTH8_ONLY" = "n" ]; then + bool 'Sparc console 12x22 font (not supported by all drivers)' CONFIG_FONT_SUN12x22 fi - if [ "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then - define_bool CONFIG_FBCON_CFB24 y + bool 'Select other fonts' CONFIG_FBCON_FONTS + if [ "$CONFIG_FBCON_FONTS" = "y" ]; then + bool ' VGA 8x8 font' CONFIG_FONT_8x8 + bool ' VGA 8x16 font' CONFIG_FONT_8x16 + if [ "$CONFIG_FBCON_FONTWIDTH8_ONLY" = "n" ]; then + bool ' Mac console 6x11 font (not supported by all drivers)' CONFIG_FONT_6x11 + fi + bool ' Pearl (old m68k) console 8x8 font' CONFIG_FONT_PEARL_8x8 + bool ' Acorn console 8x8 font' CONFIG_FONT_ACORN_8x8 fi - 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 + else + bool 'Select compiled-in fonts' CONFIG_FBCON_FONTS + if [ "$CONFIG_FBCON_FONTS" = "y" ]; then + bool ' VGA 8x8 font' CONFIG_FONT_8x8 + bool ' VGA 8x16 font' CONFIG_FONT_8x16 + bool ' Sparc console 8x16 font' CONFIG_FONT_SUN8x16 + if [ "$CONFIG_FBCON_FONTWIDTH8_ONLY" = "n" ]; then + bool ' Sparc console 12x22 font (not supported by all drivers)' CONFIG_FONT_SUN12x22 + bool ' Mac console 6x11 font (not supported by all drivers)' CONFIG_FONT_6x11 + fi + bool ' Pearl (old m68k) console 8x8 font' CONFIG_FONT_PEARL_8x8 + bool ' Acorn console 8x8 font' CONFIG_FONT_ACORN_8x8 + else + define_bool CONFIG_FONT_8x8 y + define_bool CONFIG_FONT_8x16 y + if [ "$CONFIG_MAC" = "y" ]; then + if [ "$CONFIG_FBCON_FONTWIDTH8_ONLY" = "n" ]; then + define_bool CONFIG_FONT_6x11 y + fi + fi + if [ "$CONFIG_AMIGA" = "y" ]; then + define_bool CONFIG_FONT_PEARL_8x8 y + fi + if [ "$CONFIG_ARM" = "y" ]; then + define_bool CONFIG_FONT_ACORN_8x8 y + fi fi fi - - endmenu fi diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 2349e4720..412754020 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -21,13 +21,55 @@ MOD_LIST_NAME := VIDEO_MODULES # Frame Buffer Console +# Nasty trick to make sure all wanted stuff is linked in +O_TARGET = fbdev.o +L_OBJS += fbdev.o + +ifeq ($(CONFIG_DUMMY_CONSOLE),y) + L_OBJS += dummycon.o +endif + +ifeq ($(CONFIG_PROM_CONSOLE),y) + L_OBJS += promcon.o promcon_tbl.o +endif + ifeq ($(CONFIG_FB),y) - L_OBJS += fonts.o font_8x8.o font_8x16.o pearl_8x8.o font_6x11.o - LX_OBJS += fbcon.o fbcmap.o fbgen.o + L_OBJS += fonts.o + OX_OBJS += fbcon.o fbcmap.o +# fbgen is not compiled by default since nobody uses it yet, except clgenfb + ifeq ($(CONFIG_FONT_8x8),y) + L_OBJS += font_8x8.o + endif + ifeq ($(CONFIG_FONT_8x16),y) + L_OBJS += font_8x16.o + endif + ifeq ($(CONFIG_FONT_SUN8x16),y) + L_OBJS += font_sun8x16.o + endif + ifeq ($(CONFIG_FONT_SUN12x22),y) + L_OBJS += font_sun12x22.o + endif + ifeq ($(CONFIG_FONT_6x11),y) + L_OBJS += font_6x11.o + endif + ifeq ($(CONFIG_FONT_ACORN_8x8),y) + L_OBJS += font_acorn_8x8.o + endif + ifeq ($(CONFIG_FONT_PEARL_8x8),y) + L_OBJS += font_pearl_8x8.o + endif endif # Frame Buffer Devices +ifeq ($(CONFIG_FB_ACORN),y) +L_OBJS += acornfb.o +else + ifeq ($(CONFIG_FB_ACORN),m) + M_OBJS += acornfb.o + endif +endif + ifeq ($(CONFIG_FB_AMIGA),y) L_OBJS += amifb.o else @@ -52,6 +94,18 @@ ifeq ($(CONFIG_FB_ATY),y) L_OBJS += atyfb.o endif +ifeq ($(CONFIG_FB_CONTROL),y) +L_OBJS += controlfb.o +endif + +ifeq ($(CONFIG_FB_PLATINUM),y) +L_OBJS += platinumfb.o +endif + +ifeq ($(CONFIG_FB_CT65550),y) +L_OBJS += chipsfb.o +endif + ifeq ($(CONFIG_FB_CYBER),y) L_OBJS += cyberfb.o else @@ -64,8 +118,12 @@ ifeq ($(CONFIG_FB_MAC),y) L_OBJS += macfb.o endif +ifeq ($(CONFIG_FB_HP300),y) +L_OBJS += hpfb.o +endif + ifeq ($(CONFIG_FB_OF),y) -L_OBJS += offb.o +L_OBJS += offb.o macmodes.o endif ifeq ($(CONFIG_FB_RETINAZ3),y) @@ -76,6 +134,16 @@ else endif endif +ifeq ($(CONFIG_FB_CLGEN),y) +L_OBJS += clgenfb.o +OX_OBJS += fbgen.o +else + ifeq ($(CONFIG_FB_CLGEN),m) + M_OBJS += clgenfb.o + OX_OBJS += fbgen.o + endif +endif + ifeq ($(CONFIG_FB_S3TRIO),y) L_OBJS += S3triofb.o else @@ -86,6 +154,30 @@ endif ifeq ($(CONFIG_FB_TGA),y) L_OBJS += tgafb.o +else + ifeq ($(CONFIG_FB_TGA),m) + M_OBJS += tgafb.o + endif +endif + +ifeq ($(CONFIG_FB_VGA),y) +L_OBJS += vgafb.o +else + ifeq ($(CONFIG_FB_VGA),m) + M_OBJS += vgafb.o + endif +endif + +ifeq ($(CONFIG_FB_VESA),y) +L_OBJS += vesafb.o +endif + +ifeq ($(CONFIG_FB_MDA),y) +L_OBJS += mdafb.o +else + ifeq ($(CONFIG_FB_MDA),m) + M_OBJS += mdafb.o + endif endif ifeq ($(CONFIG_FB_VIRGE),y) @@ -96,6 +188,84 @@ else endif endif +ifeq ($(CONFIG_FB_SBUS),y) +L_OBJS += sbusfb.o + ifeq ($(CONFIG_FB_CREATOR),y) + L_OBJS += creatorfb.o + else + ifeq ($(CONFIG_FB_CREATOR),m) + M_OBJS += creatorfb.o + endif + endif + ifeq ($(CONFIG_FB_CGSIX),y) + L_OBJS += cgsixfb.o + else + ifeq ($(CONFIG_FB_CGSIX),m) + M_OBJS += cgsixfb.o + endif + endif + ifeq ($(CONFIG_FB_BWTWO),y) + L_OBJS += bwtwofb.o + else + ifeq ($(CONFIG_FB_BWTWO),m) + M_OBJS += bwtwofb.o + endif + endif + ifeq ($(CONFIG_FB_CGTHREE),y) + L_OBJS += cgthreefb.o + else + ifeq ($(CONFIG_FB_CGTHREE),m) + M_OBJS += cgthreefb.o + endif + endif + ifeq ($(CONFIG_FB_TCX),y) + L_OBJS += tcxfb.o + else + ifeq ($(CONFIG_FB_TCX),m) + M_OBJS += tcxfb.o + endif + endif +else + ifeq ($(CONFIG_FB_SBUS),m) + M_OBJS += sbusfb.o + ifeq ($(CONFIG_FB_CREATOR),y) + M_OBJS += creatorfb.o + else + ifeq ($(CONFIG_FB_CREATOR),m) + M_OBJS += creatorfb.o + endif + endif + ifeq ($(CONFIG_FB_CGSIX),y) + M_OBJS += cgsixfb.o + else + ifeq ($(CONFIG_FB_CGSIX),m) + M_OBJS += cgsixfb.o + endif + endif + ifeq ($(CONFIG_FB_BWTWO),y) + M_OBJS += bwtwofb.o + else + ifeq ($(CONFIG_FB_BWTWO),m) + M_OBJS += bwtwofb.o + endif + endif + ifeq ($(CONFIG_FB_CGTHREE),y) + M_OBJS += cgthreefb.o + else + ifeq ($(CONFIG_FB_CGTHREE),m) + M_OBJS += cgthreefb.o + endif + endif + ifeq ($(CONFIG_FB_TCX),y) + M_OBJS += tcxfb.o + else + ifeq ($(CONFIG_FB_TCX),m) + M_OBJS += tcxfb.o + endif + endif + endif +endif + ifeq ($(CONFIG_FB_VIRTUAL),y) L_OBJS += vfb.o else @@ -106,70 +276,147 @@ endif # Generic Low Level Drivers -ifdef CONFIG_FBCON_AFB -LX_OBJS += fbcon-afb.o +ifeq ($(CONFIG_FBCON_AFB),y) +OX_OBJS += fbcon-afb.o +else + ifeq ($(CONFIG_FBCON_AFB),m) + MX_OBJS += fbcon-afb.o + endif endif -ifdef CONFIG_FBCON_CFB2 -LX_OBJS += fbcon-cfb2.o +ifeq ($(CONFIG_FBCON_CFB2),y) +OX_OBJS += fbcon-cfb2.o +else + ifeq ($(CONFIG_FBCON_CFB2),m) + MX_OBJS += fbcon-cfb2.o + endif endif -ifdef CONFIG_FBCON_CFB4 -LX_OBJS += fbcon-cfb4.o +ifeq ($(CONFIG_FBCON_CFB4),y) +OX_OBJS += fbcon-cfb4.o +else + ifeq ($(CONFIG_FBCON_CFB4),m) + MX_OBJS += fbcon-cfb4.o + endif endif -ifdef CONFIG_FBCON_CFB8 -LX_OBJS += fbcon-cfb8.o +ifeq ($(CONFIG_FBCON_CFB8),y) +OX_OBJS += fbcon-cfb8.o +else + ifeq ($(CONFIG_FBCON_CFB8),m) + MX_OBJS += fbcon-cfb8.o + endif endif -ifdef CONFIG_FBCON_CFB16 -LX_OBJS += fbcon-cfb16.o +ifeq ($(CONFIG_FBCON_CFB16),y) +OX_OBJS += fbcon-cfb16.o +else + ifeq ($(CONFIG_FBCON_CFB16),m) + MX_OBJS += fbcon-cfb16.o + endif endif -ifdef CONFIG_FBCON_CFB24 -LX_OBJS += fbcon-cfb24.o +ifeq ($(CONFIG_FBCON_CFB24),y) +OX_OBJS += fbcon-cfb24.o +else + ifeq ($(CONFIG_FBCON_CFB24),m) + MX_OBJS += fbcon-cfb24.o + endif endif -ifdef CONFIG_FBCON_CFB32 -LX_OBJS += fbcon-cfb32.o +ifeq ($(CONFIG_FBCON_CFB32),y) +OX_OBJS += fbcon-cfb32.o +else + ifeq ($(CONFIG_FBCON_CFB32),m) + MX_OBJS += fbcon-cfb32.o + endif endif -ifdef CONFIG_FBCON_ILBM -LX_OBJS += fbcon-ilbm.o +ifeq ($(CONFIG_FBCON_ILBM),y) +OX_OBJS += fbcon-ilbm.o +else + ifeq ($(CONFIG_FBCON_ILBM),m) + MX_OBJS += fbcon-ilbm.o + endif endif -ifdef CONFIG_FBCON_IPLAN2P2 -LX_OBJS += fbcon-iplan2p2.o +ifeq ($(CONFIG_FBCON_IPLAN2P2),y) +OX_OBJS += fbcon-iplan2p2.o +else + ifeq ($(CONFIG_FBCON_IPLAN2P2),m) + MX_OBJS += fbcon-iplan2p2.o + endif endif -ifdef CONFIG_FBCON_IPLAN2P4 -LX_OBJS += fbcon-iplan2p4.o +ifeq ($(CONFIG_FBCON_IPLAN2P4),y) +OX_OBJS += fbcon-iplan2p4.o +else + ifeq ($(CONFIG_FBCON_IPLAN2P4),m) + MX_OBJS += fbcon-iplan2p4.o + endif +endif + +ifeq ($(CONFIG_FBCON_IPLAN2P8),y) +OX_OBJS += fbcon-iplan2p8.o +else + ifeq ($(CONFIG_FBCON_IPLAN2P8),m) + MX_OBJS += fbcon-iplan2p8.o + endif endif -ifdef CONFIG_FBCON_IPLAN2P8 -LX_OBJS += fbcon-iplan2p8.o +ifeq ($(CONFIG_FBCON_IPLAN2P16),y) +OX_OBJS += fbcon-iplan2p16.o +else + ifeq ($(CONFIG_FBCON_IPLAN2P16),m) + MX_OBJS += fbcon-iplan2p16.o + endif +endif + +ifeq ($(CONFIG_FBCON_MAC),y) +OX_OBJS += fbcon-mac.o +else + ifeq ($(CONFIG_FBCON_MAC),m) + MX_OBJS += fbcon-mac.o + endif endif -ifdef CONFIG_FBCON_MAC -LX_OBJS += fbcon-mac.o +ifeq ($(CONFIG_FBCON_MFB),y) +OX_OBJS += fbcon-mfb.o +else + ifeq ($(CONFIG_FBCON_MFB),m) + MX_OBJS += fbcon-mfb.o + endif endif -ifdef CONFIG_FBCON_MFB -LX_OBJS += fbcon-mfb.o +ifeq ($(CONFIG_FBCON_VGA),y) +OX_OBJS += fbcon-vga.o +else + ifeq ($(CONFIG_FBCON_VGA),m) + MX_OBJS += fbcon-vga.o + endif endif -# GSP Console ifdef CONFIG_AMIGA_GSP -L_OBJS := $(L_OBJS) gspcon.o gspcore.o +L_OBJS += gspcon.o gspcore.o endif # VGA Text Console -ifdef CONFIG_ABSTRACT_CONSOLE ifdef CONFIG_VGA_CONSOLE -L_OBJS := $(L_OBJS) vgacon.o +L_OBJS += vgacon.o endif + +# Newport Text Console + +ifdef CONFIG_SGI +L_OBJS := $(L_OBJS) newport_con.o +endif + +# G364 Console for Mips Magnum 4000 / Olivetti M700-10 + +ifdef CONFIG_VIDEO_G364 +L_OBJS := $(L_OBJS) g364fb.o endif include $(TOPDIR)/Rules.make @@ -177,3 +424,10 @@ include $(TOPDIR)/Rules.make gspcore.c: gspcore.gsp $(GSPA) $< > $*.hex $(GSPH2C) $*.hex > gspcore.c + +promcon_tbl.c: prom.uni + ../char/conmakehash prom.uni | \ + sed -e '/#include <[^>]*>/p' -e 's/types/init/' \ + -e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > promcon_tbl.c + +promcon_tbl.o: promcon_tbl.c $(TOPDIR)/include/linux/types.h diff --git a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c index 16c0b888a..eb94dec73 100644 --- a/drivers/video/S3triofb.c +++ b/drivers/video/S3triofb.c @@ -24,8 +24,8 @@ */ #include <linux/config.h> -#include <linux/module.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/errno.h> #include <linux/string.h> #include <linux/mm.h> @@ -36,11 +36,18 @@ #include <linux/interrupt.h> #include <linux/fb.h> #include <linux/init.h> +#include <linux/selection.h> #include <asm/io.h> #include <asm/prom.h> +#include <asm/pci-bridge.h> #include <linux/pci.h> +#ifdef CONFIG_FB_COMPAT_XPMAC +#include <asm/vc_ioctl.h> +#endif +#include "fbcon.h" #include "fbcon-cfb8.h" +#include "s3blit.h" #define mem_in8(addr) in_8((void *)(addr)) @@ -60,7 +67,7 @@ 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 char *s3trio_base; static struct fb_fix_screeninfo fb_fix; static struct fb_var_screeninfo fb_var = { 0, }; @@ -70,10 +77,8 @@ 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_open(struct fb_info *info, int user); +static int s3trio_release(struct fb_info *info, int user); 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, @@ -89,30 +94,24 @@ static int s3trio_pan_display(struct fb_var_screeninfo *var, int con, 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); +void s3triofb_init(void); 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); +#if 0 static int s3triofbcon_setcmap(struct fb_cmap *cmap, int con); +#endif /* * Text console acceleration */ -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 static struct display_switch fbcon_trio8; #endif @@ -138,12 +137,12 @@ 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 void do_install_cmap(int con, struct fb_info *info); 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 + s3trio_get_cmap, s3trio_set_cmap, s3trio_pan_display, s3trio_ioctl }; @@ -151,7 +150,7 @@ static struct fb_ops s3trio_ops = { * Open/Release the frame buffer device */ -static int s3trio_open(struct fb_info *info) +static int s3trio_open(struct fb_info *info, int user) { /* * Nothing, only a usage count for the moment @@ -161,7 +160,7 @@ static int s3trio_open(struct fb_info *info) return(0); } -static int s3trio_release(struct fb_info *info) +static int s3trio_release(struct fb_info *info, int user) { MOD_DEC_USE_COUNT; return(0); @@ -200,11 +199,16 @@ 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) + var->bits_per_pixel > fb_var.bits_per_pixel ) + /* || var->nonstd || var->vmode != FB_VMODE_NONINTERLACED) */ return -EINVAL; + if (var->xres_virtual > fb_var.xres_virtual) { + outw(IO_OUT16VAL((var->xres_virtual /8) & 0xff, 0x13), 0x3d4); + outw(IO_OUT16VAL(((var->xres_virtual /8 ) & 0x300) >> 3, 0x51), 0x3d4); + fb_var.xres_virtual = var->xres_virtual; + fb_fix.line_length = var->xres_virtual; + } + fb_var.yres_virtual = var->yres_virtual; memcpy(var, &fb_var, sizeof(fb_var)); return 0; } @@ -219,12 +223,25 @@ static int s3trio_set_var(struct fb_var_screeninfo *var, int con, static int s3trio_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info) { - if (var->xoffset || var->yoffset) + unsigned int base; + + if (var->xoffset > (var->xres_virtual - var->xres)) return -EINVAL; - else - return 0; + if (var->yoffset > (var->yres_virtual - var->yres)) + return -EINVAL; + + fb_var.xoffset = var->xoffset; + fb_var.yoffset = var->yoffset; + + base = var->yoffset * fb_fix.line_length + var->xoffset; + + outw(IO_OUT16VAL((base >> 8) & 0xff, 0x0c),0x03D4); + outw(IO_OUT16VAL(base & 0xff, 0x0d),0x03D4); + outw(IO_OUT16VAL((base >> 16) & 0xf, 0x69),0x03D4); + return 0; } + /* * Get the Colormap */ @@ -238,7 +255,7 @@ static int s3trio_get_cmap(struct fb_cmap *cmap, int kspc, int con, 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; } @@ -273,7 +290,17 @@ static int s3trio_ioctl(struct inode *inode, struct file *file, u_int cmd, return -EINVAL; } -__initfunc(int s3trio_resetaccel(void)) { +__initfunc(void s3triofb_init(void)) +{ +#ifdef __powerpc__ + /* We don't want to be called like this. */ + /* We rely on Open Firmware (offb) instead. */ +#else /* !__powerpc__ */ + /* To be merged with cybervision */ +#endif /* !__powerpc__ */ +} + +__initfunc(void s3trio_resetaccel(void)) { #define EC01_ENH_ENB 0x0005 @@ -314,18 +341,15 @@ __initfunc(int s3trio_resetaccel(void)) { 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)) { +__initfunc(int s3trio_init(struct device_node *dp)) { u_char bus, dev; unsigned int t32; unsigned short cmd; - int i; - bus=0; - dev=(3<<3); + pci_device_loc(dp,&bus,&dev); 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); @@ -351,16 +375,16 @@ __initfunc(int s3trio_init(void)) { 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((inb(0x3d5) & ~(0x2 | 0x10 | 0x40)) | + 0x20, 0x33), 0x3d4); - outw(IO_OUT16VAL(0x6,0x8), 0x3c4); + 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); + outb(0x58, 0x3d4); + outw(IO_OUT16VAL(inb(0x3d5) | 3 | 0x10, 0x58), 0x3d4); + outw(IO_OUT16VAL(8, 0x53), 0x3d4); /* switch off I/O accesses */ @@ -368,6 +392,7 @@ __initfunc(int s3trio_init(void)) { pcibios_write_config_word(bus, dev, PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY); #endif + return 1; } return 0; @@ -379,18 +404,12 @@ __initfunc(int s3trio_init(void)) { * We heavily rely on OF for the moment. This needs fixing. */ -__initfunc(unsigned long s3trio_fb_init(unsigned long mem_start)) +__initfunc(void s3triofb_init_of(struct device_node *dp)) { - struct device_node *dp; - int i, err, *pp, len; - unsigned *up, address; + int i, *pp, len; + unsigned long 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); @@ -398,19 +417,19 @@ __initfunc(unsigned long s3trio_fb_init(unsigned long mem_start)) 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; + return; } 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; + return; } 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; + return; } if ((pp = (int *)get_property(dp, "width", &len)) != NULL && len == sizeof(int)) @@ -425,45 +444,51 @@ __initfunc(unsigned long s3trio_fb_init(unsigned long mem_start)) 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); + s3trio_init(dp); + address = 0xc6000000; + s3trio_base = ioremap(address,64*1024*1024); + fb_fix.smem_start = (char *)address; fb_fix.type = FB_TYPE_PACKED_PIXELS; fb_fix.type_aux = 0; + fb_fix.accel = FB_ACCEL_S3_TRIO64; + fb_fix.mmio_start = (char *)address+0x1000000; + fb_fix.mmio_len = 0x1000000; + fb_fix.xpanstep = 1; + fb_fix.ypanstep = 1; 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(0x30, s3trio_base+0x1008000 + 0x03D4); + mem_out8(0x2d, s3trio_base+0x1008000 + 0x03D4); + mem_out8(0x2e, s3trio_base+0x1008000 + 0x03D4); - mem_out8(0x50,fb_fix.smem_start+0x1008000 + 0x03D4); + mem_out8(0x50, s3trio_base+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(0x39, s3trio_base+0x1008000 + 0x03D4); + mem_out8(0xa0, s3trio_base+0x1008000 + 0x03D5); - mem_out8(0x45,fb_fix.smem_start+0x1008000 + 0x03D4); - mem_out8(0,fb_fix.smem_start+0x1008000 + 0x03D5); + mem_out8(0x45, s3trio_base+0x1008000 + 0x03D4); + mem_out8(0, s3trio_base+0x1008000 + 0x03D5); - mem_out8(0x4e,fb_fix.smem_start+0x1008000 + 0x03D4); - mem_out8(0,fb_fix.smem_start+0x1008000 + 0x03D5); + mem_out8(0x4e, s3trio_base+0x1008000 + 0x03D4); + mem_out8(0, s3trio_base+0x1008000 + 0x03D5); - mem_out8(0x4f,fb_fix.smem_start+0x1008000 + 0x03D4); - mem_out8(0,fb_fix.smem_start+0x1008000 + 0x03D5); + mem_out8(0x4f, s3trio_base+0x1008000 + 0x03D4); + mem_out8(0, s3trio_base+0x1008000 + 0x03D5); /* init HW cursor */ - CursorBase=(u_long *)(fb_fix.smem_start + 2*1024*1024 - 0x400); - for (i=0; i < 8; i++) { + CursorBase = (u_long *)(s3trio_base + 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++) { + for (i = 8; i < 64; i++) { *(CursorBase +(i*4)) = 0xffff0000; *(CursorBase+1+(i*4)) = 0xffff0000; *(CursorBase+2+(i*4)) = 0xffff0000; @@ -471,34 +496,43 @@ __initfunc(unsigned long s3trio_fb_init(unsigned long mem_start)) } - mem_out8(0x4c,fb_fix.smem_start+0x1008000 + 0x03D4); - mem_out8(((2*1024 - 1)&0xf00)>>8,fb_fix.smem_start+0x1008000 + 0x03D5); + mem_out8(0x4c, s3trio_base+0x1008000 + 0x03D4); + mem_out8(((2*1024 - 1)&0xf00)>>8, s3trio_base+0x1008000 + 0x03D5); + + mem_out8(0x4d, s3trio_base+0x1008000 + 0x03D4); + mem_out8((2*1024 - 1) & 0xff, s3trio_base+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, s3trio_base+0x1008000 + 0x03D4); + mem_in8(s3trio_base+0x1008000 + 0x03D4); - mem_out8(0x45,fb_fix.smem_start+0x1008000 + 0x03D4); - mem_in8(fb_fix.smem_start+0x1008000 + 0x03D4); + mem_out8(0x4a, s3trio_base+0x1008000 + 0x03D4); + mem_out8(0x80, s3trio_base+0x1008000 + 0x03D5); + mem_out8(0x80, s3trio_base+0x1008000 + 0x03D5); + mem_out8(0x80, s3trio_base+0x1008000 + 0x03D5); - 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, s3trio_base+0x1008000 + 0x03D4); + mem_out8(0x00, s3trio_base+0x1008000 + 0x03D5); + mem_out8(0x00, s3trio_base+0x1008000 + 0x03D5); + mem_out8(0x00, s3trio_base+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, s3trio_base+0x1008000 + 0x03D4); + mem_out8(0, s3trio_base+0x1008000 + 0x03D5); - mem_out8(0x45,fb_fix.smem_start+0x1008000 + 0x03D4); - mem_out8(0,fb_fix.smem_start+0x1008000 + 0x03D5); + /* setup default color table */ + + 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]; + } 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); + memset((char *)s3trio_base, 0, 640*480); #if 0 - Trio_RectFill(0,0,90,90,7,1); + Trio_RectFill(0, 0, 90, 90, 7, 1); #endif fb_fix.visual = FB_VISUAL_PSEUDOCOLOR ; @@ -512,7 +546,8 @@ __initfunc(unsigned long s3trio_fb_init(unsigned long mem_start)) fb_var.nonstd = 0; fb_var.activate = 0; fb_var.height = fb_var.width = -1; - fb_var.accel = 5; + fb_var.accel_flags = FB_ACCELF_TEXT; +#warning FIXME: always obey fb_var.accel_flags fb_var.pixclock = 1; fb_var.left_margin = fb_var.right_margin = 0; fb_var.upper_margin = fb_var.lower_margin = 0; @@ -524,7 +559,7 @@ __initfunc(unsigned long s3trio_fb_init(unsigned long mem_start)) 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.screen_base = s3trio_base; disp.visual = fb_fix.visual; disp.type = fb_fix.type; disp.type_aux = fb_fix.type_aux; @@ -533,11 +568,15 @@ __initfunc(unsigned long s3trio_fb_init(unsigned long mem_start)) disp.line_length = fb_fix.line_length; disp.can_soft_blank = 1; disp.inverse = 0; -#ifdef CONFIG_FBCON_CFB8 - disp.dispsw = &fbcon_trio8; +#ifdef FBCON_HAS_CFB8 + if (fb_var.accel_flags & FB_ACCELF_TEXT) + disp.dispsw = &fbcon_trio8; + else + disp.dispsw = &fbcon_cfb8; #else disp.dispsw = NULL; #endif + disp.scrollmode = fb_var.accel_flags & FB_ACCELF_TEXT ? 0 : SCROLL_YREDRAW; strcpy(fb_info.modename, "Trio64 "); strncat(fb_info.modename, dp->full_name, sizeof(fb_info.modename)); @@ -570,19 +609,14 @@ __initfunc(unsigned long s3trio_fb_init(unsigned long mem_start)) 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; + if (register_framebuffer(&fb_info) < 0) + return; printk("fb%d: S3 Trio frame buffer device on %s\n", GET_FB_IDX(fb_info.node), dp->full_name); - - return mem_start; } @@ -595,7 +629,7 @@ static int s3triofbcon_switch(int con, struct fb_info *info) currcon = con; /* Install new colormap */ - do_install_cmap(con); + do_install_cmap(con,info); return 0; } @@ -615,17 +649,23 @@ static int s3triofbcon_updatevar(int con, struct fb_info *info) static void s3triofbcon_blank(int blank, struct fb_info *info) { - /* Nothing */ + unsigned char x; + + mem_out8(0x1, s3trio_base+0x1008000 + 0x03c4); + x = mem_in8(s3trio_base+0x1008000 + 0x03c5); + mem_out8((x & (~0x20)) | (blank << 5), s3trio_base+0x1008000 + 0x03c5); } /* * Set the colormap */ +#if 0 static int s3triofbcon_setcmap(struct fb_cmap *cmap, int con) { return(s3trio_set_cmap(cmap, 1, con, &fb_info)); } +#endif /* @@ -660,16 +700,16 @@ static int s3trio_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 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); + mem_out8(regno,s3trio_base+0x1008000 + 0x3c8); + mem_out8((red & 0xff) >> 2,s3trio_base+0x1008000 + 0x3c9); + mem_out8((green & 0xff) >> 2,s3trio_base+0x1008000 + 0x3c9); + mem_out8((blue & 0xff) >> 2,s3trio_base+0x1008000 + 0x3c9); return 0; } -static void do_install_cmap(int con) +static void do_install_cmap(int con, struct fb_info *info) { if (con != currcon) return; @@ -681,48 +721,7 @@ static void do_install_cmap(int con) &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) { +void s3triofb_setup(char *options, int *ints) { return; @@ -734,7 +733,7 @@ static void Trio_WaitQueue(u_short fifo) { do { - status = mem_in16(fb_fix.smem_start + 0x1000000 + 0x9AE8); + status = mem_in16(s3trio_base + 0x1000000 + 0x9AE8); } while (!(status & fifo)); } @@ -745,7 +744,7 @@ static void Trio_WaitBlit(void) { do { - status = mem_in16(fb_fix.smem_start + 0x1000000 + 0x9AE8); + status = mem_in16(s3trio_base + 0x1000000 + 0x9AE8); } while (status & 0x200); } @@ -813,18 +812,18 @@ static void Trio_RectFill(u_short x, u_short y, u_short width, u_short height, 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(0x39, s3trio_base + 0x1008000 + 0x3d4); + mem_out8(0xa0, s3trio_base + 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(0x46, s3trio_base + 0x1008000 + 0x3d4); + mem_out8((x & 0x0700) >> 8, s3trio_base + 0x1008000 + 0x3d5); + mem_out8(0x47, s3trio_base + 0x1008000 + 0x3d4); + mem_out8(x & 0x00ff, s3trio_base + 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); + mem_out8(0x48, s3trio_base + 0x1008000 + 0x3d4); + mem_out8((y & 0x0700) >> 8, s3trio_base + 0x1008000 + 0x3d5); + mem_out8(0x49, s3trio_base + 0x1008000 + 0x3d4); + mem_out8(y & 0x00ff, s3trio_base + 0x1008000 + 0x3d5); } @@ -833,7 +832,7 @@ static void Trio_MoveCursor(u_short x, u_short y) { * Text console acceleration */ -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 static void fbcon_trio8_bmove(struct display *p, int sy, int sx, int dy, int dx, int height, int width) { @@ -866,7 +865,7 @@ static void fbcon_trio8_putc(struct vc_data *conp, struct display *p, int c, } static void fbcon_trio8_putcs(struct vc_data *conp, struct display *p, - const char *s, int count, int yy, int xx) + const unsigned short *s, int count, int yy, int xx) { Trio_WaitBlit(); fbcon_cfb8_putcs(conp, p, s, count, yy, xx); @@ -880,6 +879,7 @@ static void fbcon_trio8_revc(struct display *p, int xx, int 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 + fbcon_trio8_putcs, fbcon_trio8_revc, NULL, NULL, fbcon_cfb8_clear_margins, + FONTWIDTH(8) }; #endif diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c new file mode 100644 index 000000000..52fb4487a --- /dev/null +++ b/drivers/video/acornfb.c @@ -0,0 +1,382 @@ +/* + * linux/drivers/video/acorn.c + * + * Copyright (C) 1998 Russell King + * + * Frame buffer code for Acorn platforms + */ +#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/init.h> +#include <linux/fb.h> + +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/uaccess.h> + +#include "fbcon-mfb.h" +#include "fbcon-cfb2.h" +#include "fbcon-cfb4.h" +#include "fbcon-cfb8.h" + +#define MAX_VIDC20_PALETTE 256 +#define MAX_VIDC_PALETTE 16 + +struct acornfb_par { + unsigned long screen_base; + unsigned int xres; + unsigned int yres; + unsigned char bits_per_pixel; + unsigned int palette_size; + + union { + union { + struct { + unsigned long red:8; + unsigned long green:8; + unsigned long blue:8; + unsigned long ext:4; + unsigned long unused:4; + } d; + unsigned long p; + } vidc20[MAX_VIDC20_PALETTE]; + union { + struct { + unsigned long red:4; + unsigned long green:4; + unsigned long blue:4; + unsigned long trans:1; + unsigned long unused:19; + } d; + unsigned long p; + } vidc[MAX_VIDC_PALETTE]; + } palette; +}; + +static int currcon = 0; +static struct display disp; +static struct fb_info fb_info; +static struct acornfb_par current_par; + +static int +acornfb_open(struct fb_info *info, int user) +{ + MOD_INC_USE_COUNT; + return 0; +} + +static int +acornfb_release(struct fb_info *info, int user) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +static void +acornfb_encode_var(struct fb_var_screeninfo *var, struct acornfb_par *par) +{ + 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->bits_per_pixel; + var->grayscale = 0; + var->red.offset = 0; + var->red.length = 8; + var->red.msb_right = 0; + var->green.offset = 0; + var->green.length = 8; + var->green.msb_right = 0; + var->blue.offset = 0; + var->blue.length = 8; + var->blue.msb_right = 0; + var->transp.offset = 0; + var->transp.length = 4; + var->transp.msb_right = 0; + var->nonstd = 0; + var->activate = FB_ACTIVATE_NOW; + var->height = -1; + var->width = -1; + var->vmode = FB_VMODE_NONINTERLACED; + var->pixclock = 1; + 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; +} + +static int +acornfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) +{ + struct acornfb_par *par = ¤t_par; + unsigned int line_length; + + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + strcpy(fix->id, "Acorn"); + + line_length = par->xres * par->bits_per_pixel / 8; + + fix->smem_start = (char *)SCREEN2_BASE; + fix->smem_len = (((line_length * par->yres) - 1) | (PAGE_SIZE - 1)) + 1; + fix->type = FB_TYPE_PACKED_PIXELS; + fix->type_aux = 0; + fix->visual = FB_VISUAL_PSEUDOCOLOR; + fix->xpanstep = 0; + fix->ypanstep = 0; + fix->ywrapstep = 1; + fix->line_length = line_length; + fix->accel = FB_ACCEL_NONE; + + return 0; +} + +static int +acornfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) +{ + if (con == -1) { + acornfb_encode_var(var, ¤t_par); + } else + *var = fb_display[con].var; + return 0; +} + +static int +acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) +{ + return 0; +} + +static void +acornfb_set_disp(int con) +{ + struct fb_fix_screeninfo fix; + struct display *display; + + if (con >= 0) + display = &fb_display[con]; + else + display = &disp; + + current_par.xres = 8 * ORIG_VIDEO_COLS; + current_par.yres = 8 * ORIG_VIDEO_LINES; + current_par.bits_per_pixel = 8; + current_par.palette_size = MAX_VIDC20_PALETTE; + + acornfb_get_fix(&fix, con, 0); + + acornfb_get_var(&display->var, con, 0); + + display->cmap.start = 0; + display->cmap.len = 0; + display->cmap.red = NULL; + display->cmap.green = NULL; + display->cmap.blue = NULL; + display->cmap.transp = NULL; + 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; + display->can_soft_blank = 0; + display->inverse = 0; + + outl(SCREEN_START, VDMA_START); + outl(SCREEN_START + fix.smem_len - VDMA_XFERSIZE, VDMA_END); + outl(SCREEN_START, VDMA_INIT); + + switch (display->var.bits_per_pixel) { +#ifdef FBCON_HAS_MFB + case 1: + display->dispsw = &fbcon_mfb; + break; +#endif +#ifdef FBCON_HAS_CFB2 + case 2: + display->dispsw = &fbcon_cfb2; + break; +#endif +#ifdef FBCON_HAS_CFB4 + case 4: + display->dispsw = &fbcon_cfb4; + break; +#endif +#ifdef FBCON_HAS_CFB8 + case 8: + display->dispsw = &fbcon_cfb8; + break; +#endif + default: + display->dispsw = NULL; + break; + } +} + +static int +acornfb_vidc20_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *trans, struct fb_info *info) +{ + if (regno >= current_par.palette_size) + return 1; + *red = current_par.palette.vidc20[regno].d.red; + *green = current_par.palette.vidc20[regno].d.green; + *blue = current_par.palette.vidc20[regno].d.blue; + *trans = current_par.palette.vidc20[regno].d.ext; + return 0; +} + +static int +acornfb_vidc20_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int trans, struct fb_info *info) +{ + if (regno >= current_par.palette_size) + return 1; + + current_par.palette.vidc20[regno].p = 0; + current_par.palette.vidc20[regno].d.red = red; + current_par.palette.vidc20[regno].d.green = green; + current_par.palette.vidc20[regno].d.blue = blue; + + outl(0x10000000 | regno, VIDC_BASE); + outl(current_par.palette.vidc20[regno].p, VIDC_BASE); + + return 0; +} + +static int +acornfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + int err = 0; + + if (con == currcon) + err = fb_get_cmap(cmap, &fb_display[con].var, + kspc, acornfb_vidc20_getcolreg, info); + else if (fb_display[con].cmap.len) + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); + else + fb_copy_cmap(fb_default_cmap(current_par.palette_size), + cmap, kspc ? 0 : 2); + return err; +} + +static int +acornfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + int err = 0; + + if (!fb_display[con].cmap.len) + err = fb_alloc_cmap(&fb_display[con].cmap, + current_par.palette_size, 0); + if (!err) { + if (con == currcon) + err = fb_set_cmap(cmap, &fb_display[con].var, + kspc, acornfb_vidc20_setcolreg, info); + else + fb_copy_cmap(cmap, &fb_display[con].cmap, + kspc ? 0 : 1); + } + return err; +} + +static int +acornfb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + if (var->xoffset || var->yoffset) + return -EINVAL; + else + return 0; +} + +static int +acornfb_ioctl(struct inode *ino, struct file *file, unsigned int cmd, + unsigned long arg, int con, struct fb_info *info) +{ + return -ENOIOCTLCMD; +} + +static struct fb_ops acornfb_ops = { + acornfb_open, + acornfb_release, + acornfb_get_fix, + acornfb_get_var, + acornfb_set_var, + acornfb_get_cmap, + acornfb_set_cmap, + acornfb_pan_display, + acornfb_ioctl +}; + +void +acornfb_setup(char *options, int *ints) +{ +} + +static int +acornfb_update_var(int con, struct fb_info *info) +{ + if (con == currcon) { + int off = fb_display[con].var.yoffset * + fb_display[con].var.xres_virtual * + fb_display[con].var.bits_per_pixel >> 3; + unsigned long base; + + base = current_par.screen_base = SCREEN_START + off; + + outl (SCREEN_START + base, VDMA_INIT); + } + + return 0; +} + +static int +acornfb_switch(int con, struct fb_info *info) +{ + currcon = con; + acornfb_update_var(con, info); + return 0; +} + +static void +acornfb_blank(int blank, struct fb_info *info) +{ +} + +__initfunc(unsigned long +acornfb_init(unsigned long mem_start)) +{ + strcpy(fb_info.modename, "Acorn"); + fb_info.node = -1; + fb_info.fbops = &acornfb_ops; + fb_info.disp = &disp; + fb_info.monspecs.hfmin = 0; + fb_info.monspecs.hfmax = 0; + fb_info.monspecs.vfmin = 0; + fb_info.monspecs.vfmax = 0; + fb_info.monspecs.dpms = 0; + strcpy(fb_info.fontname, "Acorn8x8"); + fb_info.changevar = NULL; + fb_info.switch_con = acornfb_switch; + fb_info.updatevar = acornfb_update_var; + fb_info.blank = acornfb_blank; + + acornfb_set_disp(-1); + fb_set_cmap(fb_default_cmap(current_par.palette_size), &fb_display[0].var, + 1, acornfb_vidc20_setcolreg, &fb_info); + register_framebuffer(&fb_info); + + return mem_start; +} diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 09ff067df..840d23c03 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -52,6 +52,7 @@ #include <linux/interrupt.h> #include <linux/fb.h> #include <linux/init.h> +#include <linux/console.h> #include <asm/uaccess.h> #include <asm/system.h> @@ -579,8 +580,14 @@ static u_short maxfmode, chipset; #define modx(x,v) ((v) & ((x)-1)) /* if x1 is not a constant, this macro won't make real sense :-) */ +#ifdef __mc68000__ #define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \ "d" (x2), "d" ((long)((x1)/0x100000000ULL)), "0" ((long)(x1))); res;}) +#else +/* We know a bit about the numbers, so we can do it this way */ +#define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \ + ((((long)((unsigned long long)x1 >> 8) % x2) << 8) / x2)) +#endif #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) @@ -1153,8 +1160,8 @@ static u_short sprfetchmode[3] = { 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_open(struct fb_info *info, int user); +static int amifb_release(struct fb_info *info, int user); 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, @@ -1182,7 +1189,7 @@ static int amifb_set_cursorstate(struct fb_cursorstate *state, int con); * Interface to the low level console driver */ -unsigned long amifb_init(unsigned long mem_start); +void amifb_init(void); 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); @@ -1245,7 +1252,7 @@ extern unsigned short ami_intena_vals[]; 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 + amifb_pan_display, amifb_ioctl }; @@ -1370,7 +1377,7 @@ cap_invalid: * Open/Release the frame buffer device */ -static int amifb_open(struct fb_info *info) +static int amifb_open(struct fb_info *info, int user) { /* * Nothing, only a usage count for the moment @@ -1380,7 +1387,7 @@ static int amifb_open(struct fb_info *info) return(0); } -static int amifb_release(struct fb_info *info) +static int amifb_release(struct fb_info *info, int user) { MOD_DEC_USE_COUNT; return(0); @@ -1479,17 +1486,17 @@ static int amifb_set_var(struct fb_var_screeninfo *var, int con, display->can_soft_blank = 1; display->inverse = amifb_inverse; switch (fix.type) { -#ifdef CONFIG_FBCON_ILBM +#ifdef FBCON_HAS_ILBM case FB_TYPE_INTERLEAVED_PLANES: display->dispsw = &fbcon_ilbm; break; #endif -#ifdef CONFIG_FBCON_AFB +#ifdef FBCON_HAS_AFB case FB_TYPE_PLANES: display->dispsw = &fbcon_afb; break; #endif -#ifdef CONFIG_FBCON_MFB +#ifdef FBCON_HAS_MFB case FB_TYPE_PACKED_PIXELS: /* depth == 1 */ display->dispsw = &fbcon_mfb; break; @@ -1706,13 +1713,13 @@ static int amifb_set_cursorstate(struct fb_cursorstate *state, int con) * Initialisation */ -__initfunc(unsigned long amifb_init(unsigned long mem_start)) +__initfunc(void amifb_init(void)) { - int err, tag, i; + int tag, i; u_long chipptr; if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO)) - return mem_start; + return; /* * TODO: where should we put this? The DMI Resolver doesn't have a @@ -1723,7 +1730,7 @@ __initfunc(unsigned long amifb_init(unsigned long mem_start)) if (amifb_resolver){ custom.dmacon = DMAF_MASTER | DMAF_RASTER | DMAF_COPPER | DMAF_BLITTER | DMAF_SPRITE; - return mem_start; + return; } #endif @@ -1794,7 +1801,7 @@ default_chipset: strcat(amifb_name, "Unknown"); goto default_chipset; #else /* CONFIG_FB_AMIGA_OCS */ - return mem_start; + return; #endif /* CONFIG_FB_AMIGA_OCS */ break; } @@ -1803,9 +1810,13 @@ default_chipset: * Calculate the Pixel Clock Values for this Machine */ - pixclock[TAG_SHRES] = DIVUL(25E9, amiga_eclock); /* SHRES: 35 ns / 28 MHz */ - pixclock[TAG_HIRES] = DIVUL(50E9, amiga_eclock); /* HIRES: 70 ns / 14 MHz */ - pixclock[TAG_LORES] = DIVUL(100E9, amiga_eclock); /* LORES: 140 ns / 7 MHz */ + { + u_long tmp = DIVUL(200E9, amiga_eclock); + + pixclock[TAG_SHRES] = (tmp + 4) / 8; /* SHRES: 35 ns / 28 MHz */ + pixclock[TAG_HIRES] = (tmp + 2) / 4; /* HIRES: 70 ns / 14 MHz */ + pixclock[TAG_LORES] = (tmp + 1) / 2; /* LORES: 140 ns / 7 MHz */ + } /* * Replace the Tag Values with the Real Pixel Clock Values @@ -1848,10 +1859,6 @@ default_chipset: fb_info.updatevar = &amifbcon_updatevar; fb_info.blank = &amifbcon_blank; - err = register_framebuffer(&fb_info); - if (err < 0) - return mem_start; - chipptr = chipalloc(videomemorysize+ SPRITEMEMSIZE+ DUMMYSPRITEMEMSIZE+ @@ -1894,14 +1901,15 @@ default_chipset: amifb_set_var(&amifb_default, -1, &fb_info); + if (register_framebuffer(&fb_info) < 0) + return; + 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; - - return mem_start; } static int amifbcon_switch(int con, struct fb_info *info) @@ -2121,7 +2129,7 @@ static int ami_encode_fix(struct fb_fix_screeninfo *fix, fix->smem_start = (char *)videomemory; fix->smem_len = videomemorysize; -#ifdef CONFIG_FBCON_MFB +#ifdef FBCON_HAS_MFB if (par->bpp == 1) { fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; @@ -2543,7 +2551,8 @@ static int ami_encode_var(struct fb_var_screeninfo *var, struct amifb_par *par) { u_short clk_shift, line_shift; - int i; + + memset(var, 0, sizeof(struct fb_var_screeninfo)); clk_shift = par->clk_shift; line_shift = par->line_shift; @@ -2626,9 +2635,6 @@ static int ami_encode_var(struct fb_var_screeninfo *var, if (par->vmode & FB_VMODE_YWRAP) var->vmode |= FB_VMODE_YWRAP; - for (i = 0; i < arraysize(var->reserved); i++) - var->reserved[i] = 0; - return 0; } @@ -2927,20 +2933,20 @@ static void ami_do_blank(void) custom.dmacon = DMAF_RASTER | DMAF_SPRITE; red = green = blue = 0; if (!IS_OCS && do_blank > 1) { - switch (do_blank) { - case 2 : /* suspend vsync */ + switch (do_blank-1) { + case VESA_VSYNC_SUSPEND: custom.hsstrt = hsstrt2hw(par->hsstrt); custom.hsstop = hsstop2hw(par->hsstop); custom.vsstrt = vsstrt2hw(par->vtotal+4); custom.vsstop = vsstop2hw(par->vtotal+4); break; - case 3 : /* suspend hsync */ + case VESA_HSYNC_SUSPEND: custom.hsstrt = hsstrt2hw(par->htotal+16); custom.hsstop = hsstop2hw(par->htotal+16); custom.vsstrt = vsstrt2hw(par->vsstrt); custom.vsstop = vsstrt2hw(par->vsstop); break; - case 4 : /* powerdown */ + case VESA_POWERDOWN: custom.hsstrt = hsstrt2hw(par->htotal+16); custom.hsstop = hsstop2hw(par->htotal+16); custom.vsstrt = vsstrt2hw(par->vtotal+4); @@ -3486,7 +3492,8 @@ static void ami_rebuild_copper(void) #ifdef MODULE int init_module(void) { - return(amifb_init(NULL)); + amifb_init(); + return 0; } void cleanup_module(void) diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index ff7aedfe7..a64eaf1fa 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c @@ -47,7 +47,6 @@ #define ATAFB_EXT #define ATAFB_FALCON -#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -71,24 +70,12 @@ #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 */ @@ -492,6 +479,7 @@ static int tt_encode_fix( struct fb_fix_screeninfo *fix, fix->ypanstep=1; fix->ywrapstep=0; fix->line_length = 0; + fix->accel = FB_ACCEL_ATARIBLITT; return 0; } @@ -580,7 +568,8 @@ static int tt_decode_var( struct fb_var_screeninfo *var, static int tt_encode_var( struct fb_var_screeninfo *var, struct atafb_par *par ) { - int linelen, i; + int linelen; + memset(var, 0, sizeof(struct fb_var_screeninfo)); var->red.offset=0; var->red.length=4; var->red.msb_right=0; @@ -668,8 +657,6 @@ static int tt_encode_var( struct fb_var_screeninfo *var, var->nonstd=0; var->activate=0; var->vmode=FB_VMODE_NONINTERLACED; - for (i=0; i<arraysize(var->reserved); i++) - var->reserved[i]=0; return 0; } @@ -816,6 +803,7 @@ static int falcon_encode_fix( struct fb_fix_screeninfo *fix, fix->xpanstep = 2; } fix->line_length = 0; + fix->accel = FB_ACCEL_ATARIBLITT; return 0; } @@ -1306,11 +1294,12 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, struct atafb_par *par ) { /* !!! only for VGA !!! */ - int linelen, i; + int linelen; int prescale, plen; int hdb_off, hde_off, base_off; struct falcon_hw *hw = &par->hw.falcon; + memset(var, 0, sizeof(struct fb_var_screeninfo)); /* possible frequencies: 25.175 or 32MHz */ var->pixclock = hw->sync & 0x1 ? fext.t : hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t; @@ -1461,8 +1450,6 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, var->yoffset=0; var->nonstd=0; /* what is this for? */ var->activate=0; - for (i=0; i<arraysize(var->reserved); i++) - var->reserved[i]=0; return 0; } @@ -1654,7 +1641,7 @@ static int falcon_setcolreg( unsigned regno, unsigned red, (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) | (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) | ((blue & 0xe) >> 1) | ((blue & 1) << 3); -#ifdef CONFIG_FBCON_CFB16 +#ifdef FBCON_HAS_CFB16 fbcon_cfb16_cmap[regno] = (red << 11) | (green << 5) | blue; #endif } @@ -1773,6 +1760,7 @@ static int stste_encode_fix( struct fb_fix_screeninfo *fix, } fix->ywrapstep = 0; fix->line_length = 0; + fix->accel = FB_ACCEL_ATARIBLITT; return 0; } @@ -1838,7 +1826,8 @@ static int stste_decode_var( struct fb_var_screeninfo *var, static int stste_encode_var( struct fb_var_screeninfo *var, struct atafb_par *par ) { - int linelen, i; + int linelen; + memset(var, 0, sizeof(struct fb_var_screeninfo)); var->red.offset=0; var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3; var->red.msb_right=0; @@ -1908,8 +1897,6 @@ static int stste_encode_var( struct fb_var_screeninfo *var, var->nonstd=0; var->activate=0; var->vmode=FB_VMODE_NONINTERLACED; - for (i=0; i<arraysize(var->reserved); i++) - var->reserved[i]=0; return 0; } @@ -2145,8 +2132,7 @@ static int ext_decode_var( struct fb_var_screeninfo *var, static int ext_encode_var( struct fb_var_screeninfo *var, struct atafb_par *par ) { - int i; - + memset(var, 0, sizeof(struct fb_var_screeninfo)); var->red.offset=0; var->red.length=(external_pmode == -1) ? external_depth/3 : (external_vgaiobase ? external_bitspercol : 0); @@ -2181,8 +2167,6 @@ static int ext_encode_var( struct fb_var_screeninfo *var, var->nonstd=0; var->activate=0; var->vmode=FB_VMODE_NONINTERLACED; - for (i=0; i<arraysize(var->reserved); i++) - var->reserved[i]=0; return 0; } @@ -2412,7 +2396,7 @@ do_install_cmap(int con, struct fb_info *info) * Open/Release the frame buffer device */ -static int atafb_open(struct fb_info *info) +static int atafb_open(struct fb_info *info, int user) { /* * Nothing, only a usage count for the moment @@ -2422,7 +2406,7 @@ static int atafb_open(struct fb_info *info) return(0); } -static int atafb_release(struct fb_info *info) +static int atafb_release(struct fb_info *info, int user) { MOD_DEC_USE_COUNT; return(0); @@ -2470,7 +2454,7 @@ atafb_set_disp(int con, struct fb_info *info) atafb_get_var(&var, con, info); if (con == -1) con=0; - display->screen_base = (u_char *)fix.smem_start; + display->screen_base = fix.smem_start; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; @@ -2487,17 +2471,17 @@ atafb_set_disp(int con, struct fb_info *info) switch (fix.type) { case FB_TYPE_INTERLEAVED_PLANES: switch (var.bits_per_pixel) { -#ifdef CONFIG_FBCON_IPLAN2P2 +#ifdef FBCON_HAS_IPLAN2P2 case 2: display->dispsw = &fbcon_iplan2p2; break; #endif -#ifdef CONFIG_FBCON_IPLAN2P4 +#ifdef FBCON_HAS_IPLAN2P4 case 4: display->dispsw = &fbcon_iplan2p4; break; #endif -#ifdef CONFIG_FBCON_IPLAN2P8 +#ifdef FBCON_HAS_IPLAN2P8 case 8: display->dispsw = &fbcon_iplan2p8; break; @@ -2506,17 +2490,17 @@ atafb_set_disp(int con, struct fb_info *info) break; case FB_TYPE_PACKED_PIXELS: switch (var.bits_per_pixel) { -#ifdef CONFIG_FBCON_MFB +#ifdef FBCON_HAS_MFB case 1: display->dispsw = &fbcon_mfb; break; #endif -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 case 8: display->dispsw = &fbcon_cfb8; break; #endif -#ifdef CONFIG_FBCON_CFB16 +#ifdef FBCON_HAS_CFB16 case 16: display->dispsw = &fbcon_cfb16; break; @@ -2642,7 +2626,7 @@ atafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 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 + atafb_pan_display, atafb_ioctl }; static void @@ -2674,7 +2658,7 @@ check_default_par( int detected_mode ) sprintf(default_name,"default%d",i); default_par=get_video_mode(default_name); if (! default_par) - panic("can't set default video mode\n"); + panic("can't set default video mode"); var=atafb_predefined[default_par-1]; var.activate = FB_ACTIVATE_TEST; if (! do_fb_set_var(&var,1)) @@ -2730,15 +2714,14 @@ atafb_blank(int blank, struct fb_info *info) do_install_cmap(currcon, info); } -__initfunc(unsigned long atafb_init(unsigned long mem_start)) +__initfunc(void atafb_init(void)) { - int err; int pad; int detected_mode; unsigned long mem_req; if (!MACH_IS_ATARI) - return mem_start; + return; do { #ifdef ATAFB_EXT @@ -2772,7 +2755,7 @@ __initfunc(unsigned long atafb_init(unsigned long mem_start)) #else /* ATAFB_STE */ /* no default driver included */ /* Nobody will ever see this message :-) */ - panic("Cannot initialize video hardware\n"); + panic("Cannot initialize video hardware"); #endif } while (0); @@ -2793,8 +2776,10 @@ __initfunc(unsigned long atafb_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, - "atafb"); + screen_base = (unsigned long)atari_stram_alloc(mem_req, NULL, + "atafb"); + if (!screen_base) + panic("Cannot allocate screen memory"); memset((char *) screen_base, 0, mem_req); pad = ((screen_base + PAGE_SIZE-1) & PAGE_MASK) - screen_base; screen_base+=pad; @@ -2814,13 +2799,11 @@ __initfunc(unsigned long atafb_init(unsigned long mem_start)) /* Map the video memory (physical address given) to somewhere * in the kernel address space. */ - mem_start = PAGE_ALIGN(mem_start); external_addr = kernel_map(external_addr, external_len, - KERNELMAP_NO_COPYBACK, &mem_start); + KERNELMAP_NO_COPYBACK, NULL); if (external_vgaiobase) external_vgaiobase = kernel_map(external_vgaiobase, - 0x10000, KERNELMAP_NOCACHE_SER, &mem_start); - mem_start += PAGE_SIZE; + 0x10000, KERNELMAP_NOCACHE_SER, NULL); screen_base = real_screen_base = external_addr; screen_len = external_len & PAGE_MASK; @@ -2839,26 +2822,24 @@ __initfunc(unsigned long atafb_init(unsigned long mem_start)) 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); - atafb_get_var(&disp.var, -1, &fb_info); atafb_set_disp(-1, &fb_info); + do_install_cmap(0, &fb_info); + + if (register_framebuffer(&fb_info) < 0) + return; + 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, &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; - - return mem_start; } /* a strtok which returns empty strings, too */ @@ -3139,7 +3120,8 @@ __initfunc(void atafb_setup( char *options, int *ints )) #ifdef MODULE int init_module(void) { - return(atafb_init(NULL)); + atafb_init(); + return 0; } void cleanup_module(void) diff --git a/drivers/video/aty.h b/drivers/video/aty.h index 7c9b00ad7..517b500c5 100644 --- a/drivers/video/aty.h +++ b/drivers/video/aty.h @@ -223,8 +223,8 @@ #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_WRITE_MASK 0x02C8 /* Dword offset 0_B2 */ +#define DP_CHAIN_MASK 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 */ @@ -238,7 +238,7 @@ #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_MASK 0x0304 /* Dword offset 0_C1 */ #define CLR_CMP_CNTL 0x0308 /* Dword offset 0_C2 */ #define FIFO_STAT 0x0310 /* Dword offset 0_C4 */ @@ -569,7 +569,8 @@ #define PLL_WR_EN 0x02 /* PLL registers */ -#define PLL_MACRO_CNTL 0x01 +#define MPLL_CNTL 0x00 +#define VPLL_CNTL 0x01 #define PLL_REF_DIV 0x02 #define PLL_GEN_CNTL 0x03 #define MCLK_FB_DIV 0x04 @@ -579,7 +580,9 @@ #define VCLK1_FB_DIV 0x08 #define VCLK2_FB_DIV 0x09 #define VCLK3_FB_DIV 0x0A -#define PLL_XCLK_CNTL 0x0B +#define PLL_EXT_CNTL 0x0B +#define DLL_CNTL 0x0C +#define VFC_CNTL 0x0D #define PLL_TEST_CTRL 0x0E #define PLL_TEST_COUNT 0x0F @@ -688,28 +691,66 @@ /* 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 +#define CFG_CHIP_MAJOR 0x07000000 +#define CFG_CHIP_FND_ID 0x38000000 +#define CFG_CHIP_MINOR 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 + +/* mach64GX family */ +#define GX_CHIP_ID 0xD7 /* mach64GX (ATI888GX00) */ +#define CX_CHIP_ID 0x57 /* mach64CX (ATI888CX00) */ + +#define GX_PCI_ID 0x4758 /* mach64GX (ATI888GX00) */ +#define CX_PCI_ID 0x4358 /* mach64CX (ATI888CX00) */ + +/* mach64CT family */ +#define CT_CHIP_ID 0x4354 /* mach64CT (ATI264CT) */ +#define ET_CHIP_ID 0x4554 /* mach64ET (ATI264ET) */ + +/* mach64CT family / mach64VT class */ +#define VT_CHIP_ID 0x5654 /* mach64VT (ATI264VT) */ +#define VU_CHIP_ID 0x5655 /* mach64VTB (ATI264VTB) */ + +/* mach64CT family / mach64GT (3D RAGE) class */ +#define LT_CHIP_ID 0x4c54 /* 3D RAGE LT */ +#define LG_CHIP_ID 0x4c47 /* 3D RAGE LG */ +#define GT_CHIP_ID 0x4754 /* 3D RAGE (GT) */ +#define GU_CHIP_ID 0x4755 /* 3D RAGE II/II+ (GTB) */ +#define GB_CHIP_ID 0x4742 /* RAGE PRO, BGA, AGP 1x and 2x */ +#define GD_CHIP_ID 0x4744 /* RAGE PRO, BGA, AGP 1x only */ +#define GI_CHIP_ID 0x4749 /* RAGE PRO, BGA, PCI33 only */ +#define GP_CHIP_ID 0x4750 /* RAGE PRO, PQFP, PCI33, full 3D */ +#define GQ_CHIP_ID 0x4751 /* RAGE PRO, PQFP, PCI33, limited 3D */ + + +/* Mach64 major ASIC revisions */ +#define MACH64_ASIC_NEC_VT_A3 0x08 +#define MACH64_ASIC_NEC_VT_A4 0x48 +#define MACH64_ASIC_SGS_VT_A4 0x40 +#define MACH64_ASIC_SGS_VT_B1S1 0x01 +#define MACH64_ASIC_SGS_GT_B1S1 0x01 +#define MACH64_ASIC_SGS_GT_B1S2 0x41 +#define MACH64_ASIC_UMC_GT_B2U1 0x1a +#define MACH64_ASIC_UMC_GT_B2U2 0x5a +#define MACH64_ASIC_UMC_VT_B2U3 0x9a +#define MACH64_ASIC_UMC_GT_B2U3 0x9a +#define MACH64_ASIC_UMC_R3B_D_P_A1 0x1b +#define MACH64_ASIC_UMC_R3B_D_P_A2 0x5b +#define MACH64_ASIC_UMC_R3B_D_P_A3 0x1c +#define MACH64_ASIC_UMC_R3B_D_P_A4 0x5c + +/* Mach64 foundries */ +#define MACH64_FND_SGS 0 +#define MACH64_FND_NEC 1 +#define MACH64_FND_UMC 3 /* Mach64 chip types */ #define MACH64_UNKNOWN 0 @@ -900,24 +941,4 @@ #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 index e1f8b3ef4..7d271bc29 100644 --- a/drivers/video/atyfb.c +++ b/drivers/video/atyfb.c @@ -1,7 +1,9 @@ /* - * linux/drivers/video/atyfb.c -- Frame buffer device for ATI/Open Firmware + * linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64 * - * Copyright (C) 1997 Geert Uytterhoeven + * Copyright (C) 1997-1998 Geert Uytterhoeven + * Copyright (C) 1998 Bernd Harries + * Copyright (C) 1998 Eddie C. Dost * * This driver is partly based on the PowerMac console driver: * @@ -20,6 +22,23 @@ * more details. */ +/****************************************************************************** + + TODO: + + (ecd): + + - fix initialization of cursor timer. + + - add code to support cursor on all cards and all ramdacs. + + - make cursor parameters controllable via ioctl()s. + + (Anyone to help with all this?) + +******************************************************************************/ + + #include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> @@ -33,314 +52,245 @@ #include <linux/interrupt.h> #include <linux/fb.h> #include <linux/selection.h> +#include <linux/console.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/nvram.h> -#include <linux/vc_ioctl.h> +#include <linux/kd.h> +#include <linux/vt_kern.h> + +#ifdef CONFIG_FB_COMPAT_XPMAC +#include <asm/vc_ioctl.h> +#endif + #include <asm/io.h> + +#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP) #include <asm/prom.h> #include <asm/pci-bridge.h> +#include "macmodes.h" +#endif +#ifdef __sparc__ +#include <asm/pbm.h> +#endif #include "aty.h" #include "fbcon.h" #include "fbcon-cfb8.h" #include "fbcon-cfb16.h" +#include "fbcon-cfb24.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 */ - +#define GUI_RESERVE 0x00001000 -static int default_video_mode = VMODE_NVRAM; -static int default_color_mode = CMODE_NVRAM; +#define CLASS_GX 1 +#define CLASS_CT 2 +#define CLASS_VT 3 +#define CLASS_GT 4 -static struct atyfb_par default_par; -static struct atyfb_par current_par; +#ifndef __powerpc__ +#define eieio() /* Enforce In-order Execution of I/O */ +#endif -/* - * Addresses in NVRAM where video mode and pixel size are stored. - */ -#define NV_VMODE 0x140f -#define NV_CMODE 0x1410 +/* FIXME: remove the FAIL definition */ +#define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0) -/* - * Horizontal and vertical resolution information. - */ -extern struct vmode_attr { - int hres; - int vres; - int vfreq; - int interlaced; -} vmode_attrs[VMODE_MAX]; + /* + * Elements of the Hardware specific atyfb_par structure + */ -/* - * 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} +struct crtc { + u32 vxres; + u32 vyres; + u32 xoffset; + u32 yoffset; + u32 bpp; + u32 h_tot_disp; + u32 h_sync_strt_wid; + u32 v_tot_disp; + u32 v_sync_strt_wid; + u32 off_pitch; + u32 gen_cntl; + u32 dp_pix_width; /* acceleration */ + u32 dp_chain_mask; /* acceleration */ }; - -/* - * 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 */ +struct pll_gx { + u8 m; + u8 n; }; -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; +struct pll_ct { + u8 pll_ref_div; + u8 pll_gen_cntl; + u8 mclk_fb_div; + u8 pll_vclk_cntl; + u8 vclk_post_div; + u8 vclk_fb_div; + u8 pll_ext_cntl; + u32 dsp_config; /* Mach64 GTB DSP */ + u32 dsp_on_off; /* Mach64 GTB DSP */ }; -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; + /* + * The Hardware parameters for each card + */ - unsigned char clock_val[2]; /* vals for 20 and 21 */ -} aty_regvals; +struct atyfb_par { + struct crtc crtc; + union { + struct pll_gx gx; + struct pll_ct ct; + } pll; + u32 accel_flags; +}; -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; +struct aty_cmap_regs { + u8 windex; + u8 lut; + u8 mask; + u8 rindex; + u8 cntl; }; -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 +struct pci_mmap_map { + unsigned long voff; + unsigned long poff; + unsigned long size; + unsigned long prot_flag; + unsigned long prot_mask; }; -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 +#define DEFAULT_CURSOR_BLINK_RATE (20) + +struct aty_cursor { + int enable; + int on; + int vbl_cnt; + int blink_rate; + u32 offset; + struct { + u16 x, y; + } pos, hot, size; + u32 color[2]; + u8 bits[8][64]; + u8 mask[8][64]; + struct timer_list *timer; }; -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 +struct fb_info_aty { + struct fb_info fb_info; + unsigned long ati_regbase_phys; + unsigned long ati_regbase; + unsigned long frame_buffer_phys; + unsigned long frame_buffer; + struct display disp; + struct display_switch dispsw; + struct pci_mmap_map *mmap_map; + struct aty_cursor *cursor; + struct aty_cmap_regs *aty_cmap_regs; + struct { u8 red, green, blue, pad; } palette[256]; + struct atyfb_par default_par; + struct atyfb_par current_par; + u32 total_vram; + u32 pll_per; + u32 mclk_per; + u16 chip_type; +#define Gx info->chip_type + u8 chip_rev; +#define Rev info->chip_rev + u8 bus_type; + u8 ram_type; + u8 dac_type; + u8 clk_type; + u8 mem_refresh_rate; +#ifdef __sparc__ + u8 open; + u8 mmaped; + int vtconsole; + int consolecnt; +#endif }; + /* - * Interface used by the world + * Frame buffer device API */ -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_open(struct fb_info *info, int user); +static int atyfb_release(struct fb_info *info, int user); static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con, - struct fb_info *info); + struct fb_info *fb); static int atyfb_get_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info); + struct fb_info *fb); static int atyfb_set_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info); + struct fb_info *fb); static int atyfb_pan_display(struct fb_var_screeninfo *var, int con, - struct fb_info *info); + struct fb_info *fb); 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); +#ifdef __sparc__ +static int atyfb_mmap(struct fb_info *info, struct file *file, + struct vm_area_struct *vma); +#endif /* * 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); +static int atyfbcon_switch(int con, struct fb_info *fb); +static int atyfbcon_updatevar(int con, struct fb_info *fb); +static void atyfbcon_blank(int blank, struct fb_info *fb); /* * Text console acceleration */ -#ifdef CONFIG_FBCON_CFB8 +static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width); +static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width); +#ifdef FBCON_HAS_CFB8 static struct display_switch fbcon_aty8; +static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int yy, + int xx); #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); +#ifdef FBCON_HAS_CFB16 +static struct display_switch fbcon_aty16; +static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int yy, + int xx); +#endif +#ifdef FBCON_HAS_CFB24 +static struct display_switch fbcon_aty24; +static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int yy, + int xx); +#endif +#ifdef FBCON_HAS_CFB32 +static struct display_switch fbcon_aty32; +static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int yy, + int xx); #endif @@ -348,521 +298,1446 @@ static int atyfb_console_setmode(struct vc_mode *, int); * Internal routines */ +static int aty_init(struct fb_info_aty *info, const char *name); +#ifdef CONFIG_ATARI +static int store_video_par(char *videopar, unsigned char m64_num); +static char *strtoke(char *s, const char *ct); +#endif + +static void reset_engine(const struct fb_info_aty *info); +static void init_engine(const struct atyfb_par *par, + const struct fb_info_aty *info); +static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info); +static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info); +static void aty_set_crtc(const struct fb_info_aty *info, + const struct crtc *crtc); +static int aty_var_to_crtc(const struct fb_info_aty *info, + const struct fb_var_screeninfo *var, + struct crtc *crtc); +static void aty_set_dac_514(const struct fb_info_aty *info, u32 bpp); +static int aty_crtc_to_var(const struct crtc *crtc, + struct fb_var_screeninfo *var); +static void aty_set_pll_gx(const struct fb_info_aty *info, + const struct pll_gx *pll); +static int aty_var_to_pll_18818(const struct fb_var_screeninfo *var, + struct pll_gx *pll); +static int aty_var_to_pll_514(const struct fb_var_screeninfo *var, + struct pll_gx *pll); +static int aty_pll_gx_to_var(const struct pll_gx *pll, + struct fb_var_screeninfo *var); +static void aty_set_pll_ct(const struct fb_info_aty *info, + const struct pll_ct *pll); +static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div, + u8 mclk_post_div, u8 vclk_fb_div, u8 vclk_post_div, + u8 bpp, struct pll_ct *pll); +static int aty_var_to_pll_ct(const struct fb_info_aty *info, + const struct fb_var_screeninfo *var, + struct pll_ct *pll); +static int aty_pll_ct_to_var(const struct pll_ct *pll, + struct fb_var_screeninfo *var); +static void atyfb_set_par(const struct atyfb_par *par, + struct fb_info_aty *info); +static int atyfb_decode_var(const struct fb_var_screeninfo *var, + struct atyfb_par *par, + const struct fb_info_aty *info); +static int atyfb_encode_var(struct fb_var_screeninfo *var, + const struct atyfb_par *par, + const struct fb_info_aty *info); +static void set_off_pitch(struct atyfb_par *par, + const struct fb_info_aty *info); +static int encode_fix(struct fb_fix_screeninfo *fix, + const struct atyfb_par *par, + const struct fb_info_aty *info); static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp, struct fb_info *info); + u_int *transp, struct fb_info *fb); static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *info); + u_int transp, struct fb_info *fb); static void do_install_cmap(int con, struct fb_info *info); +#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP) +static int read_aty_sense(const struct fb_info_aty *info); +#endif + /* + * Interface used by the world + */ + +void atyfb_init(void); +#ifdef CONFIG_FB_OF +void atyfb_of_init(struct device_node *dp); +#endif +void atyfb_setup(char *options, int *ints); + + +static int currcon = 0; + 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 + atyfb_get_cmap, atyfb_set_cmap, atyfb_pan_display, atyfb_ioctl, +#ifdef __sparc__ + atyfb_mmap +#else + NULL +#endif }; +static char atyfb_name[16] = "ATY Mach64"; +static char fontname[40] __initdata = { 0 }; + +static const u32 ref_clk_per = 1000000000000ULL/14318180; + +#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP) +static int default_vmode = VMODE_NVRAM; +static int default_cmode = CMODE_NVRAM; +#endif + +#ifdef CONFIG_ATARI +static unsigned int mach64_count __initdata = 0; +static unsigned long phys_vmembase[FB_MAX] __initdata = { 0, }; +static unsigned long phys_size[FB_MAX] __initdata = { 0, }; +static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, }; +#endif + + +static struct aty_features { + u16 pci_id; + u16 chip_type; + const char *name; +} aty_features[] __initdata = { + /* mach64GX family */ + { 0x4758, 0x00d7, "mach64GX (ATI888GX00)" }, + { 0x4358, 0x0057, "mach64CX (ATI888CX00)" }, + + /* mach64CT family */ + { 0x4354, 0x4354, "mach64CT (ATI264CT)" }, + { 0x4554, 0x4554, "mach64ET (ATI264ET)" }, + + /* mach64CT family / mach64VT class */ + { 0x5654, 0x5654, "mach64VT (ATI264VT)" }, + { 0x5655, 0x5655, "mach64VTB (ATI264VTB)" }, +/* { 0x5656, 0x5656, "mach64VT4 (ATI264VT4)" }, */ + + /* mach64CT family / mach64GT (3D RAGE) class */ + { 0x4c54, 0x4c54, "3D RAGE LT" }, + { 0x4c47, 0x4c47, "3D RAGE LG" }, + { 0x4754, 0x4754, "3D RAGE (GT)" }, + { 0x4755, 0x4755, "3D RAGE II+ (GTB)" }, +/* { 0x4756, 0x4756, "3D RAGE IIC" }, */ + { 0x4742, 0x4742, "3D RAGE PRO (BGA, AGP)" }, + { 0x4744, 0x4744, "3D RAGE PRO (BGA, AGP, 1x only)" }, + { 0x4749, 0x4749, "3D RAGE PRO (BGA, PCI)" }, + { 0x4750, 0x4750, "3D RAGE PRO (PQFP, PCI)" }, + { 0x4751, 0x4751, "3D RAGE PRO (PQFP, PCI, limited 3D)" }, +}; + + +static inline u32 aty_ld_le32(volatile unsigned int regindex, + const struct fb_info_aty *info) +{ + unsigned long temp; + u32 val; + +#if defined(__powerpc__) + temp = info->ati_regbase; + asm("lwbrx %0,%1,%2" : "=r"(val) : "r" (regindex), "r" (temp)); +#elif defined(__sparc_v9__) + temp = info->ati_regbase + regindex; + asm("lduwa [%1] %2, %0" : "=r" (val) : "r" (temp), "i" (ASI_PL)); +#else + temp = info->ati_regbase+regindex; + val = le32_to_cpu(*((volatile u32 *)(temp))); +#endif + return val; +} -static inline int aty_vram_reqd(const struct atyfb_par *par) +static inline void aty_st_le32(volatile unsigned int regindex, u32 val, + const struct fb_info_aty *info) { - return (par->vxres*par->vyres) << par->cmode; + unsigned long temp; + +#if defined(__powerpc__) + temp = info->ati_regbase; + asm("stwbrx %0,%1,%2" : : "r" (val), "r" (regindex), "r" (temp) : + "memory"); +#elif defined(__sparc_v9__) + temp = info->ati_regbase + regindex; + asm("stwa %0, [%1] %2" : : "r" (val), "r" (temp), "i" (ASI_PL) : "memory"); +#else + temp = info->ati_regbase+regindex; + *((volatile u32 *)(temp)) = cpu_to_le32(val); +#endif } -extern inline unsigned aty_ld_le32(volatile unsigned long addr) +static inline u8 aty_ld_8(volatile unsigned int regindex, + const struct fb_info_aty *info) { - register unsigned long temp = ati_regbase,val; + return *(volatile u8 *)(info->ati_regbase+regindex); +} - asm("lwbrx %0,%1,%2": "=r"(val):"r"(addr), "r"(temp)); - return val; +static inline void aty_st_8(volatile unsigned int regindex, u8 val, + const struct fb_info_aty *info) +{ + *(volatile u8 *)(info->ati_regbase+regindex) = val; } -extern inline void aty_st_le32(volatile unsigned long addr, unsigned val) + + /* + * Generic Mach64 routines + */ + + /* + * All writes to draw engine registers are automatically routed through a + * 32-bit-wide, 16-entry-deep command FIFO ... + * Register writes to registers with DWORD offsets less than 40h are not + * FIFOed. + * (from Chapter 5 of the Mach64 Programmer's Guide) + */ + +static inline void wait_for_fifo(u16 entries, const struct fb_info_aty *info) { - register unsigned long temp = ati_regbase; + while ((aty_ld_le32(FIFO_STAT, info) & 0xffff) > + ((u32)(0x8000 >> entries))); +} - asm("stwbrx %0,%1,%2": : "r"(val), "r"(addr), "r"(temp):"memory"); +static inline void wait_for_idle(const struct fb_info_aty *info) +{ + wait_for_fifo(16, info); + while ((aty_ld_le32(GUI_STAT, info) & 1)!= 0); } -extern inline unsigned char aty_ld_8(volatile unsigned long addr) +static void reset_engine(const struct fb_info_aty *info) { - return *(char *) ((long) addr + (long) ati_regbase); + /* reset engine */ + aty_st_le32(GEN_TEST_CNTL, + aty_ld_le32(GEN_TEST_CNTL, info) & ~GUI_ENGINE_ENABLE, info); + /* enable engine */ + aty_st_le32(GEN_TEST_CNTL, + aty_ld_le32(GEN_TEST_CNTL, info) | GUI_ENGINE_ENABLE, info); + /* ensure engine is not locked up by clearing any FIFO or */ + /* HOST errors */ + aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, info) | BUS_HOST_ERR_ACK | + BUS_FIFO_ERR_ACK, info); } -extern inline void aty_st_8(volatile unsigned long addr, unsigned char val) +static void init_engine(const struct atyfb_par *par, + const struct fb_info_aty *info) { - *(unsigned char *) (addr + (unsigned long) ati_regbase) = val; + u32 pitch_value; + + /* determine modal information from global mode structure */ + pitch_value = par->crtc.vxres; + + if (par->crtc.bpp == 24) { + /* In 24 bpp, the engine is in 8 bpp - this requires that all */ + /* horizontal coordinates and widths must be adjusted */ + pitch_value = pitch_value * 3; + } + + /* Reset engine, enable, and clear any engine errors */ + reset_engine(info); + /* Ensure that vga page pointers are set to zero - the upper */ + /* page pointers are set to 1 to handle overflows in the */ + /* lower page */ + aty_st_le32(MEM_VGA_WP_SEL, 0x00010000, info); + aty_st_le32(MEM_VGA_RP_SEL, 0x00010000, info); + + /* ---- Setup standard engine context ---- */ + + /* All GUI registers here are FIFOed - therefore, wait for */ + /* the appropriate number of empty FIFO entries */ + wait_for_fifo(14, info); + + /* enable all registers to be loaded for context loads */ + aty_st_le32(CONTEXT_MASK, 0xFFFFFFFF, info); + + /* set destination pitch to modal pitch, set offset to zero */ + aty_st_le32(DST_OFF_PITCH, (pitch_value / 8) << 22, info); + + /* zero these registers (set them to a known state) */ + aty_st_le32(DST_Y_X, 0, info); + aty_st_le32(DST_HEIGHT, 0, info); + aty_st_le32(DST_BRES_ERR, 0, info); + aty_st_le32(DST_BRES_INC, 0, info); + aty_st_le32(DST_BRES_DEC, 0, info); + + /* set destination drawing attributes */ + aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM | + DST_X_LEFT_TO_RIGHT, info); + + /* set source pitch to modal pitch, set offset to zero */ + aty_st_le32(SRC_OFF_PITCH, (pitch_value / 8) << 22, info); + + /* set these registers to a known state */ + aty_st_le32(SRC_Y_X, 0, info); + aty_st_le32(SRC_HEIGHT1_WIDTH1, 1, info); + aty_st_le32(SRC_Y_X_START, 0, info); + aty_st_le32(SRC_HEIGHT2_WIDTH2, 1, info); + + /* set source pixel retrieving attributes */ + aty_st_le32(SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT, info); + + /* set host attributes */ + wait_for_fifo(13, info); + aty_st_le32(HOST_CNTL, 0, info); + + /* set pattern attributes */ + aty_st_le32(PAT_REG0, 0, info); + aty_st_le32(PAT_REG1, 0, info); + aty_st_le32(PAT_CNTL, 0, info); + + /* set scissors to modal size */ + aty_st_le32(SC_LEFT, 0, info); + aty_st_le32(SC_TOP, 0, info); + aty_st_le32(SC_BOTTOM, par->crtc.vyres-1, info); + aty_st_le32(SC_RIGHT, pitch_value-1, info); + + /* set background color to minimum value (usually BLACK) */ + aty_st_le32(DP_BKGD_CLR, 0, info); + + /* set foreground color to maximum value (usually WHITE) */ + aty_st_le32(DP_FRGD_CLR, 0xFFFFFFFF, info); + + /* set write mask to effect all pixel bits */ + aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF, info); + + /* set foreground mix to overpaint and background mix to */ + /* no-effect */ + aty_st_le32(DP_MIX, FRGD_MIX_S | BKGD_MIX_D, info); + + /* set primary source pixel channel to foreground color */ + /* register */ + aty_st_le32(DP_SRC, FRGD_SRC_FRGD_CLR, info); + + /* set compare functionality to false (no-effect on */ + /* destination) */ + wait_for_fifo(3, info); + aty_st_le32(CLR_CMP_CLR, 0, info); + aty_st_le32(CLR_CMP_MASK, 0xFFFFFFFF, info); + aty_st_le32(CLR_CMP_CNTL, 0, info); + + /* set pixel depth */ + wait_for_fifo(2, info); + aty_st_le32(DP_PIX_WIDTH, par->crtc.dp_pix_width, info); + aty_st_le32(DP_CHAIN_MASK, par->crtc.dp_chain_mask, info); + + /* insure engine is idle before leaving */ + wait_for_idle(info); } -static void aty_st_514(int offset, char val) +static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info) { - 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 */ + aty_st_8(DAC_CNTL, 1, info); + /* right addr byte */ + aty_st_8(DAC_W_INDEX, offset & 0xff, info); + /* left addr byte */ + aty_st_8(DAC_DATA, (offset >> 8) & 0xff, info); eieio(); - aty_st_8(DAC_MASK, val); + aty_st_8(DAC_MASK, val, info); eieio(); - aty_st_8(DAC_CNTL, 0); + aty_st_8(DAC_CNTL, 0, info); } -static void aty_st_pll(int offset, char val) +static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info) { - aty_WaitQueue(3); - aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN); /* write addr byte */ + /* write addr byte */ + aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN, info); eieio(); - aty_st_8(CLOCK_CNTL + 2, val); /* write the register value */ + /* write the register value */ + aty_st_8(CLOCK_CNTL + 2, val, info); eieio(); - aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN); + aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info); } -static struct aty_regvals *get_aty_struct(int vmode) +#if 0 /* ecd debug */ +static u8 aty_ld_pll(int offset, const struct fb_info_aty *info) { - int v = vmode - 1; + u8 val; - 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; - } + /* write addr byte */ + aty_st_8(CLOCK_CNTL + 1, (offset << 2), info); + eieio(); + /* read the register value */ + val = aty_ld_8(CLOCK_CNTL + 2, info); + eieio(); + return val; } +#endif /* ecd debug */ + +#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP) -static int read_aty_sense(void) + /* + * Apple monitor sense + */ + +static int read_aty_sense(const struct fb_info_aty *info) { int sense, i; - aty_st_le32(GP_IO, 0x31003100); /* drive outputs high */ + aty_st_le32(GP_IO, 0x31003100, info); /* drive outputs high */ __delay(200); - aty_st_le32(GP_IO, 0); /* turn off outputs */ + aty_st_le32(GP_IO, 0, info); /* turn off outputs */ __delay(2000); - i = aty_ld_le32(GP_IO); /* get primary sense value */ + i = aty_ld_le32(GP_IO, info); /* 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 */ + aty_st_le32(GP_IO, 0x20000000, info); /* drive A low */ __delay(2000); - i = aty_ld_le32(GP_IO); + i = aty_ld_le32(GP_IO, info); sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4); - aty_st_le32(GP_IO, 0x20002000); /* drive A high again */ + aty_st_le32(GP_IO, 0x20002000, info); /* drive A high again */ __delay(200); - aty_st_le32(GP_IO, 0x10000000); /* drive B low */ + aty_st_le32(GP_IO, 0x10000000, info); /* drive B low */ __delay(2000); - i = aty_ld_le32(GP_IO); + i = aty_ld_le32(GP_IO, info); sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6); - aty_st_le32(GP_IO, 0x10001000); /* drive B high again */ + aty_st_le32(GP_IO, 0x10001000, info); /* drive B high again */ __delay(200); - aty_st_le32(GP_IO, 0x01000000); /* drive C low */ + aty_st_le32(GP_IO, 0x01000000, info); /* drive C low */ __delay(2000); - sense |= (aty_ld_le32(GP_IO) & 0x3000) >> 12; - aty_st_le32(GP_IO, 0); /* turn off outputs */ + sense |= (aty_ld_le32(GP_IO, info) & 0x3000) >> 12; + aty_st_le32(GP_IO, 0, info); /* turn off outputs */ return sense; } -static void RGB514_Program(int cmode) +#endif /* defined(CONFIG_PMAC) || defined(CONFIG_CHRP) */ + +/* ------------------------------------------------------------------------- */ + + /* + * Hardware Cursor support. + */ + +static u8 cursor_pixel_map[2] = { 0, 15 }; +static u8 cursor_color_map[2] = { 0, 0xff }; + +static u8 cursor_bits_lookup[16] = { - typedef struct { - char pixel_dly; - char misc2_cntl; - char pixel_rep; - char pixel_cntl_index; - char pixel_cntl_v1; - } RGB514_DAC_Table; + 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54, + 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55 +}; - 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; +static u8 cursor_mask_lookup[16] = +{ + 0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02, + 0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00 +}; + +static void +aty_set_cursor_color(struct fb_info_aty *fb, u8 *pixel, + u8 *red, u8 *green, u8 *blue) +{ + struct aty_cursor *c = fb->cursor; + int i; - pDacProgTab = &RGB514DAC_Tab[cmode]; + if (!c) + return; - aty_st_514(0x90, 0x00); - aty_st_514(0x04, pDacProgTab->pixel_dly); - aty_st_514(0x05, 0x00); +#ifdef __sparc__ + if (fb->mmaped && currcon == fb->vtconsole) + return; +#endif - aty_st_514(0x2, 0x1); - aty_st_514(0x71, pDacProgTab->misc2_cntl); - aty_st_514(0x0a, pDacProgTab->pixel_rep); + for (i = 0; i < 2; i++) { + c->color[i] = (u32)red[i] << 24; + c->color[i] |= (u32)green[i] << 16; + c->color[i] |= (u32)blue[i] << 8; + c->color[i] |= (u32)pixel[i]; + } - aty_st_514(pDacProgTab->pixel_cntl_index, pDacProgTab->pixel_cntl_v1); + wait_for_fifo(2, fb); + aty_st_le32(CUR_CLR0, c->color[0], fb); + aty_st_le32(CUR_CLR1, c->color[1], fb); } -static void set_off_pitch(const struct atyfb_par *par) +static void +aty_set_cursor_shape(struct fb_info_aty *fb) { - u32 pitch, offset; + struct aty_cursor *c = fb->cursor; + u8 *ram, m, b; + int x, y; - 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); - } + if (!c) + return; + +#ifdef __sparc__ + if (fb->mmaped && currcon == fb->vtconsole) + return; +#endif + + ram = (u8 *)(fb->frame_buffer + c->offset); + + for (y = 0; y < c->size.y; y++) { + for (x = 0; x < c->size.x >> 2; x++) { + m = c->mask[x][y]; + b = c->bits[x][y]; + *ram++ = cursor_mask_lookup[m >> 4] | + cursor_bits_lookup[(b & m) >> 4]; + *ram++ = cursor_mask_lookup[m & 0x0f] | + cursor_bits_lookup[(b & m) & 0x0f]; + } + for ( ; x < 8; x++) { + *ram++ = 0xaa; + *ram++ = 0xaa; + } + } + memset(ram, 0xaa, (64 - c->size.y) * 16); } -static void atyfb_set_par(struct atyfb_par *par) +static void +aty_set_cursor(struct fb_info_aty *fb) { - int i, hres; - struct aty_regvals *init = get_aty_struct(par->vmode); - int vram_type = aty_ld_le32(CONFIG_STAT0) & 7; + struct aty_cursor *c = fb->cursor; + u16 xoff, yoff; + int x, y; - if (init == 0) /* paranoia, shouldn't get here */ - panic("aty: display mode %d not supported", par->vmode); + if (!c) + return; - current_par = *par; - hres = vmode_attrs[par->vmode-1].hres; +#ifdef __sparc__ + if (fb->mmaped && currcon == fb->vtconsole) + return; +#endif - /* clear FIFO errors */ - aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_HOST_ERR_ACK - | BUS_FIFO_ERR_ACK); + if (c->on) { + x = c->pos.x - c->hot.x; + if (x < 0) { + xoff = -x; + x = 0; + } else { + xoff = 0; + } + + y = c->pos.y - c->hot.y; + if (y < 0) { + yoff = -y; + y = 0; + } else { + yoff = 0; + } + + wait_for_fifo(4, fb); + aty_st_le32(CUR_OFFSET, (c->offset >> 3) + (yoff << 1), fb); + aty_st_le32(CUR_HORZ_VERT_OFF, + ((u32)(64 - c->size.y + yoff) << 16) | xoff, fb); + aty_st_le32(CUR_HORZ_VERT_POSN, ((u32)y << 16) | x, fb); + aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, fb) + | HWCURSOR_ENABLE, fb); + } else { + wait_for_fifo(4, fb); + aty_st_le32(GEN_TEST_CNTL, + aty_ld_le32(GEN_TEST_CNTL, fb) & ~HWCURSOR_ENABLE, + fb); + } +} - /* 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(); +static void +aty_cursor_timer_handler(unsigned long dev_addr) +{ + struct fb_info_aty *fb = (struct fb_info_aty *)dev_addr; - 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 (!fb->cursor) + return; - if ( chip_type == MACH64_GX_ID ) { - i = aty_ld_le32(GEN_TEST_CNTL); - aty_st_le32(GEN_TEST_CNTL, i | GEN_OVR_OUTPUT_EN ); - } + if (!fb->cursor->enable) + goto out; - 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; - } + if (fb->cursor->vbl_cnt && --fb->cursor->vbl_cnt == 0) { + fb->cursor->on ^= 1; + aty_set_cursor(fb); + fb->cursor->vbl_cnt = fb->cursor->blink_rate; + } - aty_ld_8(DAC_REGS); /* clear counter */ - aty_WaitIdleEmpty(); +out: + fb->cursor->timer->expires = jiffies + (HZ / 50); + add_timer(fb->cursor->timer); +} - 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); +static void +atyfb_cursor(struct display *d, int mode, int x, int y) +{ + struct fb_info_aty *fb = (struct fb_info_aty *)d->fb_info; + struct aty_cursor *c = fb->cursor; - aty_st_8(CLOCK_CNTL, 0); - aty_st_8(CLOCK_CNTL, CLOCK_STROBE); + if (!c) + return; - aty_st_le32(CRTC_VLINE_CRNT_VLINE, 0); +#ifdef __sparc__ + if (fb->mmaped && currcon == fb->vtconsole) + return; +#endif - set_off_pitch(par); + x *= d->fontwidth; + y *= d->fontheight; + if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->on) + return; - if (chip_type == MACH64_GT_ID) { - aty_st_le32(BUS_CNTL, 0x7b23a040); + c->enable = 0; + c->pos.x = x; + c->pos.y = y; - /* 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); + switch (mode) { + case CM_ERASE: + c->on = 0; + aty_set_cursor(fb); + break; - 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]); + case CM_DRAW: + case CM_MOVE: + c->on = 1; + aty_set_cursor(fb); - //aty_st_le32(CLOCK_CNTL,8192); - } else { - i |= ((1 * par->cmode) << 26) | 0x300090; - aty_st_le32(DSP_ON_OFF, init->mem_cntl[par->cmode]); + if (!c->timer) { + c->timer = kmalloc(sizeof(*c->timer), GFP_KERNEL); + if (!c->timer) + return; + + c->blink_rate = DEFAULT_CURSOR_BLINK_RATE; + + init_timer(c->timer); + c->timer->expires = jiffies + (HZ / 50); + c->timer->data = (unsigned long)fb; + c->timer->function = aty_cursor_timer_handler; + add_timer(c->timer); + } + + c->vbl_cnt = c->blink_rate; + c->enable = 1; + break; } +} - aty_st_le32(MEM_CNTL, i); - aty_st_le32(EXT_MEM_CNTL, 0x5000001); +static int +atyfb_set_font(struct display *d, int width, int height) +{ + struct fb_info_aty *fb = (struct fb_info_aty *)d->fb_info; + struct aty_cursor *c = fb->cursor; + int i, j; + + if (c) { + if (!width || !height) { + width = 8; + height = 16; + } - /* if (total_vram > 0x400000) - i |= 0x538; this not been verified on > 4Megs!! */ - } else { + c->offset = fb->total_vram - 0x1000; + c->hot.x = 0; + c->hot.y = 0; + c->size.x = width; + c->size.y = height; -/* 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); + memset(c->bits, 0xff, sizeof(c->bits)); + memset(c->mask, 0, sizeof(c->mask)); - 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); + for (i = 0, j = width; j >= 0; j -= 8, i++) { + c->mask[i][height-2] = (j >= 8) ? 0xff : (0xff << (8 - j)); + c->mask[i][height-1] = (j >= 8) ? 0xff : (0xff << (8 - j)); } + + aty_set_cursor_color(fb, cursor_pixel_map, cursor_color_map, + cursor_color_map, cursor_color_map); + aty_set_cursor_shape(fb); + } + return 1; +} + + + + +/* ------------------------------------------------------------------------- */ + + /* + * CRTC programming + */ + +static void aty_set_crtc(const struct fb_info_aty *info, + const struct crtc *crtc) +{ + aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, info); + aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, info); + aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, info); + aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, info); + aty_st_le32(CRTC_VLINE_CRNT_VLINE, 0, info); + aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, info); + aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, info); +} + +static int aty_var_to_crtc(const struct fb_info_aty *info, + const struct fb_var_screeninfo *var, + struct crtc *crtc) +{ + u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp; + u32 left, right, upper, lower, hslen, vslen, sync, vmode; + u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol; + u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol; + u32 pix_width, dp_pix_width, dp_chain_mask; + + /* input */ + xres = var->xres; + yres = var->yres; + vxres = var->xres_virtual; + vyres = var->yres_virtual; + xoffset = var->xoffset; + yoffset = var->yoffset; + bpp = var->bits_per_pixel; + left = var->left_margin; + right = var->right_margin; + upper = var->upper_margin; + lower = var->lower_margin; + hslen = var->hsync_len; + vslen = var->vsync_len; + sync = var->sync; + vmode = var->vmode; + + /* convert (and round up) and validate */ + xres = (xres+7) & ~7; + xoffset = (xoffset+7) & ~7; + vxres = (vxres+7) & ~7; + if (vxres < xres+xoffset) + vxres = xres+xoffset; + h_disp = xres/8-1; + if (h_disp > 0xff) + FAIL("h_disp too large"); + h_sync_strt = h_disp+(right/8); + if (h_sync_strt > 0x1ff) + FAIL("h_sync_start too large"); + h_sync_dly = right & 7; + h_sync_wid = (hslen+7)/8; + if (h_sync_wid > 0x1f) + FAIL("h_sync_wid too large"); + h_total = h_sync_strt+h_sync_wid+(h_sync_dly+left+7)/8; + if (h_total > 0x1ff) + FAIL("h_total too large"); + h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; + + if (vyres < yres+yoffset) + vyres = yres+yoffset; + v_disp = yres-1; + if (v_disp > 0x7ff) + FAIL("v_disp too large"); + v_sync_strt = v_disp+lower; + if (v_sync_strt > 0x7ff) + FAIL("v_sync_strt too large"); + v_sync_wid = vslen; + if (v_sync_wid > 0x1f) + FAIL("v_sync_wid too large"); + v_total = v_sync_strt+v_sync_wid+upper; + if (v_total > 0x7ff) + FAIL("v_total too large"); + v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1; + + if (bpp <= 8) { + bpp = 8; + pix_width = CRTC_PIX_WIDTH_8BPP; + dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB; + dp_chain_mask = 0x8080; + } else if (bpp <= 16) { + bpp = 16; + pix_width = CRTC_PIX_WIDTH_15BPP; + dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP | + BYTE_ORDER_LSB_TO_MSB; + dp_chain_mask = 0x4210; + } else if ((bpp <= 24) && (Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) { + bpp = 24; + pix_width = CRTC_PIX_WIDTH_24BPP; + dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB; + dp_chain_mask = 0x8080; + } else if (bpp <= 32) { + bpp = 32; + pix_width = CRTC_PIX_WIDTH_32BPP; + dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP | + BYTE_ORDER_LSB_TO_MSB; + dp_chain_mask = 0x8080; + } else + FAIL("invalid bpp"); + + if (vxres*vyres*bpp/8 > info->total_vram) + FAIL("not enough video RAM"); + + if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) + FAIL("invalid vmode"); + + /* output */ + crtc->vxres = vxres; + crtc->vyres = vyres; + crtc->xoffset = xoffset; + crtc->yoffset = yoffset; + crtc->bpp = bpp; + crtc->h_tot_disp = h_total | (h_disp<<16); + crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) | + ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) | + (h_sync_pol<<21); + crtc->v_tot_disp = v_total | (v_disp<<16); + crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21); + crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19); + crtc->gen_cntl = pix_width | CRTC_EXT_DISP_EN | CRTC_ENABLE; + if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID) || + ((Gx == VT_CHIP_ID) && !(Rev & 0x03)) || + ((Gx == GT_CHIP_ID) && !(Rev & 0x03))) { + /* Not VTB/GTB */ + /* FIXME: magic FIFO values */ + crtc->gen_cntl |= aty_ld_le32(CRTC_GEN_CNTL, info) & 0x000e0000; } -/* 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; + crtc->dp_pix_width = dp_pix_width; + crtc->dp_chain_mask = dp_chain_mask; + + return 0; +} + +static void aty_set_dac_514(const struct fb_info_aty *info, u32 bpp) +{ + static struct { + u8 pixel_dly; + u8 misc2_cntl; + u8 pixel_rep; + u8 pixel_cntl_index; + u8 pixel_cntl_v1; + } tab[3] = { + { 0, 0x41, 0x03, 0x71, 0x45 }, /* 8 bpp */ + { 0, 0x45, 0x04, 0x0c, 0x01 }, /* 555 */ + { 0, 0x45, 0x06, 0x0e, 0x00 }, /* XRGB */ + }; + int i; + + switch (bpp) { + case 8: + default: + i = 0; break; - case MACH64_VT_ID: - i = 0x87010184; + case 16: + i = 1; break; - default: - i = 0x47012100; + case 32: + i = 2; break; } + aty_st_514(0x90, 0x00, info); /* VRAM Mask Low */ + aty_st_514(0x04, tab[i].pixel_dly, info); /* Horizontal Sync Control */ + aty_st_514(0x05, 0x00, info); /* Power Management */ + aty_st_514(0x02, 0x01, info); /* Misc Clock Control */ + aty_st_514(0x71, tab[i].misc2_cntl, info); /* Misc Control 2 */ + aty_st_514(0x0a, tab[i].pixel_rep, info); /* Pixel Format */ + aty_st_514(tab[i].pixel_cntl_index, tab[i].pixel_cntl_v1, info); + /* Misc Control 2 / 16 BPP Control / 32 BPP Control */ +} - 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: +static int aty_crtc_to_var(const struct crtc *crtc, + struct fb_var_screeninfo *var) +{ + u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync; + u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol; + u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol; + u32 pix_width; + + /* input */ + h_total = crtc->h_tot_disp & 0x1ff; + h_disp = (crtc->h_tot_disp>>16) & 0xff; + h_sync_strt = (crtc->h_sync_strt_wid & 0xff) | + ((crtc->h_sync_strt_wid>>4) & 0x100); + h_sync_dly = (crtc->h_sync_strt_wid>>8) & 0x7; + h_sync_wid = (crtc->h_sync_strt_wid>>16) & 0x1f; + h_sync_pol = (crtc->h_sync_strt_wid>>21) & 0x1; + v_total = crtc->v_tot_disp & 0x7ff; + v_disp = (crtc->v_tot_disp>>16) & 0x7ff; + v_sync_strt = crtc->v_sync_strt_wid & 0x7ff; + v_sync_wid = (crtc->v_sync_strt_wid>>16) & 0x1f; + v_sync_pol = (crtc->v_sync_strt_wid>>21) & 0x1; + pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK; + + /* convert */ + xres = (h_disp+1)*8; + yres = v_disp+1; + left = (h_total-h_sync_strt-h_sync_wid)*8-h_sync_dly; + right = (h_sync_strt-h_disp)*8; + hslen = h_sync_wid*8; + upper = v_total-v_sync_strt-v_sync_wid; + lower = v_sync_strt-v_disp; + vslen = v_sync_wid; + sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) | + (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT); + + switch (pix_width) { +#if 0 + case CRTC_PIX_WIDTH_4BPP: + bpp = 4; + 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; +#endif + case CRTC_PIX_WIDTH_8BPP: + bpp = 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 CRTC_PIX_WIDTH_15BPP: /* RGB 555 */ + bpp = 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; +#if 0 + case CRTC_PIX_WIDTH_16BPP: /* RGB 565 */ + bpp = 16; + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 6; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + var->transp.offset = 0; + var->transp.length = 0; + break; +#endif + case CRTC_PIX_WIDTH_24BPP: /* RGB 888 */ + bpp = 24; + 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 = 0; + var->transp.length = 0; + break; + case CRTC_PIX_WIDTH_32BPP: /* ARGB 8888 */ + bpp = 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; default: - i = CRTC_PIX_WIDTH_8BPP; break; + FAIL("Invalid pixel width"); } - 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); + /* output */ + var->xres = xres; + var->yres = yres; + var->xres_virtual = crtc->vxres; + var->yres_virtual = crtc->vyres; + var->bits_per_pixel = bpp; + var->xoffset = crtc->xoffset; + var->yoffset = crtc->yoffset; + var->left_margin = left; + var->right_margin = right; + var->upper_margin = upper; + var->lower_margin = lower; + var->hsync_len = hslen; + var->vsync_len = vslen; + var->sync = sync; + var->vmode = FB_VMODE_NONINTERLACED; -#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) */ + return 0; } +/* ------------------------------------------------------------------------- */ /* - * Open/Release the frame buffer device + * PLL programming (Mach64 GX family) + * + * FIXME: use function pointer tables instead of switch statements */ -static int atyfb_open(struct fb_info *info) +static void aty_set_pll_gx(const struct fb_info_aty *info, + const struct pll_gx *pll) +{ + switch (info->clk_type) { + case CLK_ATI18818_1: + aty_st_8(CLOCK_CNTL, pll->m, info); + break; + case CLK_IBMRGB514: + aty_st_514(0x06, 0x02, info); /* DAC Operation */ + aty_st_514(0x10, 0x01, info); /* PLL Control 1 */ + aty_st_514(0x70, 0x01, info); /* Misc Control 1 */ + aty_st_514(0x8f, 0x1f, info); /* PLL Ref. Divider Input */ + aty_st_514(0x03, 0x00, info); /* Sync Control */ + aty_st_514(0x05, 0x00, info); /* Power Management */ + aty_st_514(0x20, pll->m, info); /* F0 / M0 */ + aty_st_514(0x21, pll->m, info); /* F1 / N0 */ + break; + } +} +static int aty_var_to_pll_18818(const struct fb_var_screeninfo *var, + struct pll_gx *pll) { /* - * Nothing, only a usage count for the moment + * FIXME: use real calculations instead of using fixed values from the old + * driver */ - - MOD_INC_USE_COUNT; - return(0); + static struct { + u32 ps_lim; /* pixclock period rounding limit (arbitrary) */ + u8 mode; /* (prescsaler << 4) | Select */ + u8 prog; /* ref_div_count */ + } ATI18818_clocks[] = { + { 7500, 0x0B, 1 }, /* 7407.4 ps = 135.00 MHz */ + { 9000, 0x0A, 1 }, /* 7936.5 ps = 126.00 MHz */ + { 11000, 0x09, 1 }, /* 10000.0 ps = 100.00 MHz */ + { 12800, 0x0D, 1 }, /* 12500.0 ps = 80.00 MHz */ + { 13500, 0x0E, 1 }, /* 13333.3 ps = 75.00 MHz */ +/* { 14000, 0x03, 2 },*/ /* 13888.8 ps = 72.00 MHz */ + { 15000, 0x1B, 1 }, /* 14814.8 ps = 67.50 MHz */ + { 15500, 0x0F, 1 }, /* 15384.6 ps = 65.00 MHz */ + { 16000, 0x1A, 1 }, /* 15873.0 ps = 63.00 MHz */ +/* { 16000, 0x02, 2 },*/ /* 15873.0 ps = 63.00 MHz */ +/* { 18000, 0x01, 2 },*/ /* 17655.4 ps = 56.64 MHz */ +/* { 19900, 0x00, 2 },*/ /* 19860.9 ps = 50.35 MHz */ + { 20000, 0x07, 1 }, /* 20000.0 ps = 50.00 MHz */ + { 20300, 0x06, 1 }, /* 20202.0 ps = 49.50 MHz */ + { 22500, 0x05, 1 }, /* 22271.2 ps = 44.90 MHz */ + { 25000, 0x04, 1 }, /* 25000.0 ps = 40.00 MHz */ +/* { 28000, 0x03, 1 },*/ /* 27777.8 ps = 36.00 MHz */ + { 30000, 0x2B, 1 }, /* 29629,6 ps = 33.75 MHz */ + { 31000, 0x1F, 1 }, /* 30769.2 ps = 32.50 MHz */ + { 32000, 0x2A, 1 }, /* 31746.0 ps = 31.50 MHz */ +/* { 32000, 0x02, 1 },*/ /* 31746.0 ps = 31.50 MHz */ +/* { 36000, 0x01, 1 },*/ /* 35310.7 ps = 28.32 MHz */ +/* { 39900, 0x00, 1 },*/ /* 39714.1 ps = 25.18 MHz */ + { 40000, 0x17, 1 }, /* 40000.0 ps = 25.00 MHz */ + { 40600, 0x16, 1 }, /* 40404.0 ps = 24.75 MHz */ + { 45000, 0x15, 1 }, /* 44543.4 ps = 22.45 MHz */ + { 50000, 0x14, 1 }, /* 50000.0 ps = 20.00 MHz */ +/* { 56000, 0x13, 1 },*/ /* 55555.5 ps = 18.00 MHz */ + { 62000, 0x2F, 1 }, /* 61538.8 ps = 16.25 MHz */ +/* { 64000, 0x12, 1 },*/ /* 63492.0 ps = 15.75 MHz */ + }; + int set; + + for (set = 0; set < sizeof(ATI18818_clocks)/sizeof(*ATI18818_clocks); + set++) + if (var->pixclock <= ATI18818_clocks[set].ps_lim) { + pll->m = ATI18818_clocks[set].mode; + pll->n = ATI18818_clocks[set].prog; + return 0; + } + return -EINVAL; } -static int atyfb_release(struct fb_info *info) +static int aty_var_to_pll_514(const struct fb_var_screeninfo *var, + struct pll_gx *pll) { - MOD_DEC_USE_COUNT; - return(0); + /* + * FIXME: use real calculations instead of using fixed values from the old + * driver + */ + static struct { + u32 limit; /* pixlock rounding limit (arbitrary) */ + u8 m; /* (df<<6) | vco_div_count */ + u8 n; /* ref_div_count */ + } RGB514_clocks[7] = { + { 8000, (3<<6) | 20, 9 }, /* 7395 ps / 135.2273 MHz */ + { 10000, (1<<6) | 19, 3 }, /* 9977 ps / 100.2273 MHz */ + { 13000, (1<<6) | 2, 3 }, /* 12509 ps / 79.9432 MHz */ + { 14000, (2<<6) | 8, 7 }, /* 13394 ps / 74.6591 MHz */ + { 16000, (1<<6) | 44, 6 }, /* 15378 ps / 65.0284 MHz */ + { 25000, (1<<6) | 15, 5 }, /* 17460 ps / 57.2727 MHz */ + { 50000, (0<<6) | 53, 7 }, /* 33145 ps / 30.1705 MHz */ + }; + int i; + + for (i = 0; i < sizeof(RGB514_clocks)/sizeof(*RGB514_clocks); i++) + if (var->pixclock <= RGB514_clocks[i].limit) { + pll->m = RGB514_clocks[i].m; + pll->n = RGB514_clocks[i].n; + return 0; + } + return -EINVAL; } + /* FIXME: ATI18818?? */ -static int encode_fix(struct fb_fix_screeninfo *fix, - const struct atyfb_par *par) +static int aty_pll_gx_to_var(const struct pll_gx *pll, + struct fb_var_screeninfo *var) { - struct aty_regvals *init; + u8 df, vco_div_count, ref_div_count; + + df = pll->m >> 6; + vco_div_count = pll->m & 0x3f; + ref_div_count = pll->n; + + var->pixclock = (ref_clk_per*(vco_div_count+65)/ref_div_count)>>(3-df); + + return 0; +} - 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 + * PLL programming (Mach64 CT family) */ - 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; +static void aty_set_pll_ct(const struct fb_info_aty *info, + const struct pll_ct *pll) +{ +#if 0 /* ecd debug */ +printk("PLL_REF_DIV: %02x (%02x)\n", + pll->pll_ref_div, aty_ld_pll(PLL_REF_DIV, info)); +printk("PLL_GEN_CNTL: %02x (%02x)\n", + pll->pll_gen_cntl, aty_ld_pll(PLL_GEN_CNTL, info)); +printk("MCLK_FB_DIV: %02x (%02x)\n", + pll->mclk_fb_div, aty_ld_pll(MCLK_FB_DIV, info)); +printk("PLL_VCLK_CNTL: %02x (%02x)\n", + pll->pll_vclk_cntl, aty_ld_pll(PLL_VCLK_CNTL, info)); +printk("VCLK_POST_DIV: %02x (%02x)\n", + pll->vclk_post_div, aty_ld_pll(VCLK_POST_DIV, info)); +printk("VCLK0_FB_DIV: %02x (%02x)\n", + pll->vclk_fb_div, aty_ld_pll(VCLK0_FB_DIV, info)); +printk("PLL_EXT_CNTL: %02x (%02x)\n", + pll->pll_ext_cntl, aty_ld_pll(PLL_EXT_CNTL, info)); +#endif /* ecd debug */ + aty_st_pll(PLL_REF_DIV, pll->pll_ref_div, info); + aty_st_pll(PLL_GEN_CNTL, pll->pll_gen_cntl, info); + aty_st_pll(MCLK_FB_DIV, pll->mclk_fb_div, info); + aty_st_pll(PLL_VCLK_CNTL, pll->pll_vclk_cntl, info); + aty_st_pll(VCLK_POST_DIV, pll->vclk_post_div, info); + aty_st_pll(VCLK0_FB_DIV, pll->vclk_fb_div, info); + aty_st_pll(PLL_EXT_CNTL, pll->pll_ext_cntl, info); + + if (((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) || + (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) || + (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) || + (Gx == VU_CHIP_ID)) { + if (info->ram_type >= SDRAM) + aty_st_pll(DLL_CNTL, 0xa6, info); + else + aty_st_pll(DLL_CNTL, 0xa0, info); + aty_st_pll(VFC_CNTL, 0x1b, info); + aty_st_le32(DSP_CONFIG, pll->dsp_config, info); + aty_st_le32(DSP_ON_OFF, pll->dsp_on_off, info); + } +} + +static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div, + u8 mclk_post_div, u8 vclk_fb_div, u8 vclk_post_div, + u8 bpp, struct pll_ct *pll) +{ + u32 dsp_xclks_per_row, dsp_loop_latency, dsp_precision, dsp_off, dsp_on; + u32 xclks_per_row, fifo_off, fifo_on, y, fifo_size, page_size; + + /* xclocks_per_row<<11 */ + xclks_per_row = (mclk_fb_div*vclk_post_div*64<<11)/ + (vclk_fb_div*mclk_post_div*bpp); + if (xclks_per_row < (1<<11)) + FAIL("Dotclock to high"); + fifo_size = 24; + dsp_precision = 0; + y = (xclks_per_row*fifo_size)>>11; + while (y) { + y >>= 1; + dsp_precision++; + } + dsp_precision -= 5; + /* fifo_off<<6 */ + fifo_off = ((xclks_per_row*(fifo_size-1))>>5)+(1<<6); + + if (info->total_vram > 1*1024*1024) { + if (info->ram_type >= SDRAM) { + /* >1 MB SDRAM */ + dsp_loop_latency = 8; + page_size = 8; + } else { + /* >1 MB DRAM */ + dsp_loop_latency = 6; + page_size = 9; + } + } else { + if (info->ram_type >= SDRAM) { + /* <2 MB SDRAM */ + dsp_loop_latency = 9; + page_size = 10; + } else { + /* <2 MB DRAM */ + dsp_loop_latency = 8; + page_size = 10; + } + } + /* fifo_on<<6 */ + if (xclks_per_row >= (page_size<<11)) + fifo_on = ((2*page_size+1)<<6)+(xclks_per_row>>5); + else + fifo_on = (3*page_size)<<6; + + dsp_xclks_per_row = xclks_per_row>>dsp_precision; + dsp_on = fifo_on>>dsp_precision; + dsp_off = fifo_off>>dsp_precision; + + pll->dsp_config = (dsp_xclks_per_row & 0x3fff) | + ((dsp_loop_latency & 0xf)<<16) | + ((dsp_precision & 7)<<20); + pll->dsp_on_off = (dsp_on & 0x7ff) | ((dsp_off & 0x7ff)<<16); return 0; } +static int aty_var_to_pll_ct(const struct fb_info_aty *info, + const struct fb_var_screeninfo *var, + struct pll_ct *pll) +{ + u32 vclk_per, q, x; /* x is a workaround for sparc64-linux-gcc */ + u8 pll_ref_div, pll_gen_cntl, pll_ext_cntl; + u8 mclk_fb_div, mclk_post_div, mpostdiv = 0; + u8 vclk_fb_div, vclk_post_div, vpostdiv = 0; + int err; + + x = x; /* x is a workaround for sparc64-linux-gcc */ -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; + pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */ - xres = vmode_attrs[par->vmode-1].hres; - yres = vmode_attrs[par->vmode-1].vres; + vclk_per = var->pixclock; + pll_ref_div = info->pll_per*2*255/ref_clk_per; - if (var->xres_virtual <= xres) - par->vxres = xres; + /* FIXME: use the VTB/GTB /3 post divider if it's better suited */ + q = ref_clk_per*pll_ref_div*4/info->mclk_per; /* actually 8*q */ + if (q < 16*8 || q > 255*8) + FAIL("mclk out of range"); + else if (q < 32*8) + mclk_post_div = 8; + else if (q < 64*8) + mclk_post_div = 4; + else if (q < 128*8) + mclk_post_div = 2; else - par->vxres = (var->xres_virtual+7) & ~7; - if (var->yres_virtual <= yres) - par->vyres = yres; + mclk_post_div = 1; + mclk_fb_div = q*mclk_post_div/8; + + /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */ + q = ref_clk_per*pll_ref_div*4/vclk_per; /* actually 8*q */ + if (q < 16*8 || q > 255*8) + FAIL("vclk out of range"); + else if (q < 32*8) + vclk_post_div = 8; + else if (q < 64*8) + vclk_post_div = 4; + else if (q < 128*8) + vclk_post_div = 2; else - par->vyres = var->yres_virtual; + vclk_post_div = 1; + vclk_fb_div = q*vclk_post_div/8; - par->xoffset = (var->xoffset+7) & ~7; - par->yoffset = var->yoffset; - if (par->xoffset+xres > par->vxres || par->yoffset+yres > par->vyres) - return -EINVAL; + if ((err = aty_dsp_gt(info, mclk_fb_div, mclk_post_div, vclk_fb_div, + vclk_post_div, var->bits_per_pixel, pll))) + return err; - if (bpp <= 8) - par->cmode = CMODE_8; - else if (bpp <= 16) - par->cmode = CMODE_16; - else if (bpp <= 32) - par->cmode = CMODE_32; + if ((((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) || + (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) || + (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) || + (Gx == VU_CHIP_ID)) && (info->ram_type >= SDRAM)) + pll_gen_cntl = 0x04; else - return -EINVAL; + pll_gen_cntl = 0x84; - if (aty_vram_reqd(par) > total_vram) - return -EINVAL; + switch (mclk_post_div) { + case 1: + mpostdiv = 0; + break; + case 2: + mpostdiv = 1; + break; + case 3: + mpostdiv = 4; + break; + case 4: + mpostdiv = 2; + break; + case 8: + mpostdiv = 3; + break; + } + pll_gen_cntl |= mpostdiv<<4; /* mclk */ + + if (Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48)) + pll_ext_cntl = 0; + else + pll_ext_cntl = mpostdiv; /* xclk == mclk */ + + switch (vclk_post_div) { + case 1: + vpostdiv = 0; + break; + case 2: + vpostdiv = 1; + break; + case 3: + vpostdiv = 0; + pll_ext_cntl |= 0x10; + break; + case 4: + vpostdiv = 2; + break; + case 6: + vpostdiv = 2; + pll_ext_cntl |= 0x10; + break; + case 8: + vpostdiv = 3; + break; + case 12: + vpostdiv = 3; + pll_ext_cntl |= 0x10; + break; + } + vclk_post_div = vpostdiv; + + pll->pll_ref_div = pll_ref_div; + pll->pll_gen_cntl = pll_gen_cntl; + pll->mclk_fb_div = mclk_fb_div; + pll->vclk_post_div = vclk_post_div; + pll->vclk_fb_div = vclk_fb_div; + pll->pll_ext_cntl = pll_ext_cntl; + return 0; +} - /* 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)) +static int aty_pll_ct_to_var(const struct pll_ct *pll, + struct fb_var_screeninfo *var) +{ + u8 pll_ref_div = pll->pll_ref_div; + u8 vclk_fb_div = pll->vclk_fb_div; + u8 vclk_post_div = pll->vclk_post_div; + u8 pll_ext_cntl = pll->pll_ext_cntl; + static u8 vclk_post_div_tab[] = { + 1, 2, 4, 8, + 3, 0, 6, 12 + }; + u8 vpostdiv = vclk_post_div_tab[((pll_ext_cntl & 0x10) >> 1) | + (vclk_post_div & 3)]; + if (vpostdiv == 0) return -EINVAL; + var->pixclock = pll_ref_div*vpostdiv*ref_clk_per/vclk_fb_div/2; + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static void atyfb_set_par(const struct atyfb_par *par, + struct fb_info_aty *info) +{ + u32 i; + + info->current_par = *par; + + aty_set_crtc(info, &par->crtc); + aty_st_8(CLOCK_CNTL, 0, info); + aty_st_8(CLOCK_CNTL, CLOCK_STROBE, info); + + if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) { + switch (info->dac_type) { + case DAC_IBMRGB514: + aty_set_dac_514(info, par->crtc.bpp); + break; + case DAC_ATI68860_B: + /* FIXME */ + break; + } + aty_set_pll_gx(info, &par->pll.gx); + aty_st_le32(BUS_CNTL, 0x890e20f1, info); + aty_st_le32(DAC_CNTL, 0x47052100, info); + } else { + aty_set_pll_ct(info, &par->pll.ct); + i = aty_ld_le32(MEM_CNTL, info) & 0xf30fffff; + if (!(Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48))) + i |= info->mem_refresh_rate << 20; + switch (par->crtc.bpp) { + case 8: + case 24: + i |= 0x00000000; + break; + case 16: + i |= 0x04000000; + break; + case 32: + i |= 0x08000000; + break; + } + if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) { + aty_st_le32(DAC_CNTL, 0x87010184, info); + aty_st_le32(BUS_CNTL, 0x680000f9, info); + } else if ((Gx == VT_CHIP_ID) || (Gx == VU_CHIP_ID)) { + aty_st_le32(DAC_CNTL, 0x87010184, info); + aty_st_le32(BUS_CNTL, 0x680000f9, info); + } else { + /* GT */ + aty_st_le32(DAC_CNTL, 0x86010102, info); + aty_st_le32(BUS_CNTL, 0x7b23a040, info); + aty_st_le32(EXT_MEM_CNTL, 0x5000001, info); + } + aty_st_le32(MEM_CNTL, i, info); + } + aty_st_8(DAC_MASK, 0xff, info); + + /* Initialize the graphics engine */ + if (par->accel_flags & FB_ACCELF_TEXT) + init_engine(par, info); + +#ifdef CONFIG_FB_COMPAT_XPMAC + if (console_fb_info == &info->fb_info) { + struct fb_var_screeninfo var; + int vmode, cmode; + display_info.height = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1; + display_info.width = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8; + display_info.depth = par->crtc.bpp; + display_info.pitch = par->crtc.vxres*par->crtc.bpp/8; + atyfb_encode_var(&var, par, info); + if (mac_var_to_vmode(&var, &vmode, &cmode)) + display_info.mode = 0; + else + display_info.mode = vmode; + strcpy(display_info.name, atyfb_name); + display_info.fb_address = info->frame_buffer_phys; + display_info.cmap_adr_address = info->ati_regbase_phys+0xc0; + display_info.cmap_data_address = info->ati_regbase_phys+0xc1; + display_info.disp_reg_address = info->ati_regbase_phys; + } +#endif /* CONFIG_FB_COMPAT_XPMAC */ +} + +static int atyfb_decode_var(const struct fb_var_screeninfo *var, + struct atyfb_par *par, + const struct fb_info_aty *info) +{ + int err; + + if ((err = aty_var_to_crtc(info, var, &par->crtc))) + return err; + if ((Gx == GX_PCI_ID) || (Gx == CX_PCI_ID)) + switch (info->clk_type) { + case CLK_ATI18818_1: + err = aty_var_to_pll_18818(var, &par->pll.gx); + break; + case CLK_IBMRGB514: + err = aty_var_to_pll_514(var, &par->pll.gx); + break; + } + else + err = aty_var_to_pll_ct(info, var, &par->pll.ct); + if (err) + return err; + + if (var->accel_flags & FB_ACCELF_TEXT) + par->accel_flags = FB_ACCELF_TEXT; + else + par->accel_flags = 0; #if 0 if (!fbmon_valid_timings(pixclock, htotal, vtotal, info)) @@ -872,106 +1747,192 @@ static int decode_var(struct fb_var_screeninfo *var, return 0; } -static int encode_var(struct fb_var_screeninfo *var, - const struct atyfb_par *par) +static int atyfb_encode_var(struct fb_var_screeninfo *var, + const struct atyfb_par *par, + const struct fb_info_aty *info) { + int err; + 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; + if ((err = aty_crtc_to_var(&par->crtc, var))) + return err; + if ((Gx == GX_PCI_ID) || (Gx == CX_PCI_ID)) + err = aty_pll_gx_to_var(&par->pll.gx, var); + else + err = aty_pll_ct_to_var(&par->pll.ct, var); + if (err) + return err; + 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; + var->accel_flags = par->accel_flags; return 0; } -static void init_par(struct atyfb_par *par, int vmode, int cmode) + +static void set_off_pitch(struct atyfb_par *par, + const struct fb_info_aty *info) { - 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; + u32 xoffset = par->crtc.xoffset; + u32 yoffset = par->crtc.yoffset; + u32 vxres = par->crtc.vxres; + u32 bpp = par->crtc.bpp; + + par->crtc.off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19); + aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, info); +} + + + /* + * Open/Release the frame buffer device + */ + +static int atyfb_open(struct fb_info *info, int user) + +{ +#ifdef __sparc__ + struct fb_info_aty *fb = (struct fb_info_aty *)info; + + if (user) { + if (fb->open) + return -EBUSY; + fb->mmaped = 0; + fb->open = 1; + fb->vtconsole = -1; + } else { + fb->consolecnt++; + } +#endif + MOD_INC_USE_COUNT; + return(0); +} + +static int atyfb_release(struct fb_info *info, int user) +{ +#ifdef __sparc__ + struct fb_info_aty *fb = (struct fb_info_aty *)info; + + if (user) { + if (fb->vtconsole != -1) + vt_cons[fb->vtconsole]->vc_mode = KD_TEXT; + fb->open = 0; + fb->mmaped = 0; + fb->vtconsole = -1; + } else { + fb->consolecnt--; + } +#endif + MOD_DEC_USE_COUNT; + return(0); } +static int encode_fix(struct fb_fix_screeninfo *fix, + const struct atyfb_par *par, + const struct fb_info_aty *info) +{ + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + + strcpy(fix->id, atyfb_name); + fix->smem_start = (char *)info->frame_buffer_phys; + fix->smem_len = (u32)info->total_vram; + +#ifdef __LITTLE_ENDIAN + /* + * Last page of 8 MB little-endian aperture is MMIO + * FIXME: we should use the auxiliary aperture instead so we can acces the + * full 8 MB of video RAM on 8 MB boards + */ + if (fix->smem_len > 0x800000-GUI_RESERVE) + fix->smem_len = 0x800000-GUI_RESERVE; +#endif + /* + * Reg Block 0 (CT-compatible block) is at ati_regbase_phys + * Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400 + */ + if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) { + fix->mmio_start = (char *)info->ati_regbase_phys; + fix->mmio_len = 0x400; + fix->accel = FB_ACCEL_ATI_MACH64GX; + } else if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) { + fix->mmio_start = (char *)info->ati_regbase_phys; + fix->mmio_len = 0x400; + fix->accel = FB_ACCEL_ATI_MACH64CT; + } else if ((Gx == VT_CHIP_ID) || (Gx == VU_CHIP_ID)) { + fix->mmio_start = (char *)(info->ati_regbase_phys-0x400); + fix->mmio_len = 0x800; + fix->accel = FB_ACCEL_ATI_MACH64VT; + } else { + fix->mmio_start = (char *)(info->ati_regbase_phys-0x400); + fix->mmio_len = 0x800; + fix->accel = FB_ACCEL_ATI_MACH64GT; + } + fix->type = FB_TYPE_PACKED_PIXELS; + fix->type_aux = 0; + fix->line_length = par->crtc.vxres*par->crtc.bpp/8; + fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR + : FB_VISUAL_DIRECTCOLOR; + fix->ywrapstep = 0; + fix->xpanstep = 8; + fix->ypanstep = 1; + + return 0; +} + + +struct fb_var_screeninfo default_var = { + /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ + 640, 480, 640, 480, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2, + 0, FB_VMODE_NONINTERLACED +}; + +#ifdef __sparc__ +struct fb_var_screeninfo default_var_1024x768 __initdata = { + /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */ + 1024, 768, 1024, 768, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, 12699, 176, 16, 28, 1, 96, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED +}; + +struct fb_var_screeninfo default_var_1152x900 __initdata = { + /* 1152x900, 76 Hz, Non-Interlaced (110.0 MHz dotclock) */ + 1152, 900, 1152, 900, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, 9091, 234, 24, 34, 3, 100, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED +}; + +struct fb_var_screeninfo default_var_1280x1024 __initdata = { + /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */ + 1280, 1024, 1280, 1024, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, 7408, 248, 16, 38, 1, 144, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED +}; +#endif + + /* * Get the Fixed Part of the Display */ static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con, - struct fb_info *info) + struct fb_info *fb) { + const struct fb_info_aty *info = (struct fb_info_aty *)fb; struct atyfb_par par; if (con == -1) - par = default_par; + par = info->default_par; else - decode_var(&fb_display[con].var, &par); - encode_fix(fix, &par); + atyfb_decode_var(&fb_display[con].var, &par, info); + encode_fix(fix, &par, info); return 0; } @@ -981,12 +1942,14 @@ static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con, */ static int atyfb_get_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info) + struct fb_info *fb) { + const struct fb_info_aty *info = (struct fb_info_aty *)fb; + if (con == -1) - encode_var(var, &default_par); + atyfb_encode_var(var, &info->default_par, info); else - *var=fb_display[con].var; + *var = fb_display[con].var; return 0; } @@ -996,23 +1959,23 @@ static int atyfb_get_var(struct fb_var_screeninfo *var, int con, */ static int atyfb_set_var(struct fb_var_screeninfo *var, int con, - struct fb_info *info) + struct fb_info *fb) { + struct fb_info_aty *info = (struct fb_info_aty *)fb; struct atyfb_par par; struct display *display; - int oldxres, oldyres, oldvxres, oldvyres, oldbpp; - int err; + int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel, accel, err; int activate = var->activate; if (con >= 0) display = &fb_display[con]; else - display = &fb_disp; /* used during initialization */ + display = fb->disp; /* used during initialization */ - if ((err = decode_var(var, &par))) + if ((err = atyfb_decode_var(var, &par, info))) return err; - encode_var(var, &par); + atyfb_encode_var(var, &par, (struct fb_info_aty *)info); if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { oldxres = display->var.xres; @@ -1020,14 +1983,15 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con, oldvxres = display->var.xres_virtual; oldvyres = display->var.yres_virtual; oldbpp = display->var.bits_per_pixel; + oldaccel = display->var.accel_flags; display->var = *var; if (oldxres != var->xres || oldyres != var->yres || oldvxres != var->xres_virtual || oldvyres != var->yres_virtual || - oldbpp != var->bits_per_pixel) { + oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) { struct fb_fix_screeninfo fix; - encode_fix(&fix, &par); - display->screen_base = (u_char *)fix.smem_start; + encode_fix(&fix, &par, info); + display->screen_base = (char *)info->frame_buffer; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; @@ -1036,33 +2000,46 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con, 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; + accel = var->accel_flags & FB_ACCELF_TEXT; + switch (par.crtc.bpp) { +#ifdef FBCON_HAS_CFB8 + case 8: + *display->dispsw = accel ? fbcon_aty8 : fbcon_cfb8; + break; #endif +#ifdef FBCON_HAS_CFB16 + case 16: + *display->dispsw = accel ? fbcon_aty16 : fbcon_cfb16; break; - case CMODE_16: - display->dispsw = &fbcon_cfb16; +#endif +#ifdef FBCON_HAS_CFB24 + case 24: + *display->dispsw = accel ? fbcon_aty24 : fbcon_cfb24; break; - case CMODE_32: - display->dispsw = &fbcon_cfb32; +#endif +#ifdef FBCON_HAS_CFB32 + case 32: + *display->dispsw = accel ? fbcon_aty32 : fbcon_cfb32; break; +#endif default: display->dispsw = NULL; break; } - if (fb_info.changevar) - (*fb_info.changevar)(con); + display->scrollmode = accel ? 0 : SCROLL_YREDRAW; + if (info->fb_info.changevar) + (*info->fb_info.changevar)(con); + if (info->cursor) { + display->dispsw->cursor = atyfb_cursor; + display->dispsw->set_font = atyfb_set_font; + } } if (con == currcon) - atyfb_set_par(&par); + atyfb_set_par(&par, info); if (oldbpp != var->bits_per_pixel) { if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) return err; - do_install_cmap(con, info); + do_install_cmap(con, &info->fb_info); } } @@ -1077,20 +2054,21 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con, */ static int atyfb_pan_display(struct fb_var_screeninfo *var, int con, - struct fb_info *info) + struct fb_info *fb) { + struct fb_info_aty *info = (struct fb_info_aty *)fb; u32 xres, yres, xoffset, yoffset; - struct atyfb_par *par = ¤t_par; + struct atyfb_par *par = &info->current_par; - xres = vmode_attrs[par->vmode-1].hres; - yres = vmode_attrs[par->vmode-1].vres; + xres = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8; + yres = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1; xoffset = (var->xoffset+7) & ~7; yoffset = var->yoffset; - if (xoffset+xres > par->vxres || yoffset+yres > par->vyres) + if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres) return -EINVAL; - par->xoffset = xoffset; - par->yoffset = yoffset; - set_off_pitch(par); + par->crtc.xoffset = xoffset; + par->crtc.yoffset = yoffset; + set_off_pitch(par, info); return 0; } @@ -1106,9 +2084,10 @@ static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, 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); + else { + int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; + fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2); + } return 0; } @@ -1122,8 +2101,8 @@ static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, 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))) + int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; + if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0))) return err; } if (con == currcon) /* current console? */ @@ -1141,283 +2120,835 @@ static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, return -EINVAL; } +#ifdef __sparc__ +static int atyfb_mmap(struct fb_info *info, struct file *file, + struct vm_area_struct *vma) +{ + struct fb_info_aty *fb = (struct fb_info_aty *)info; + unsigned int size, page, map_size = 0; + unsigned long map_offset = 0; + int i; + + if (!fb->mmap_map) + return -ENXIO; + + size = vma->vm_end - vma->vm_start; + if (vma->vm_offset & ~PAGE_MASK) + return -ENXIO; + + /* To stop the swapper from even considering these pages. */ + vma->vm_flags |= (VM_SHM | VM_LOCKED); + +#ifdef __sparc_v9__ + /* Align it as much as desirable */ + { + int j, max = -1, align; + + map_offset = vma->vm_offset+size; + for (i = 0; fb->mmap_map[i].size; i++) { + if (fb->mmap_map[i].voff < vma->vm_offset) + continue; + if (fb->mmap_map[i].voff >= map_offset) + break; + if (max < 0 || + fb->mmap_map[i].size > fb->mmap_map[max].size) + max = i; + } + if (max >= 0) { + j = fb->mmap_map[max].size; + if (fb->mmap_map[max].voff + j > map_offset) + j = map_offset - fb->mmap_map[max].voff; + for (align = 0x400000; align > PAGE_SIZE; align >>= 3) + if (j >= align && + !(fb->mmap_map[max].poff & (align - 1))) + break; + if (align > PAGE_SIZE) { + j = align; + align = j - ((vma->vm_start + + fb->mmap_map[max].voff + - vma->vm_offset) & (j - 1)); + if (align != j) { + struct vm_area_struct *vmm; + + vmm = find_vma(current->mm, + vma->vm_start); + if (!vmm || vmm->vm_start + >= vma->vm_end + align) { + vma->vm_start += align; + vma->vm_end += align; + } + } + } + } + } +#endif + + /* Each page, see which map applies */ + for (page = 0; page < size; ) { + map_size = 0; + for (i = 0; fb->mmap_map[i].size; i++) { + unsigned long start = fb->mmap_map[i].voff; + unsigned long end = start + fb->mmap_map[i].size; + unsigned long offset = vma->vm_offset + page; + + if (start > offset) + continue; + if (offset > end) + continue; + + map_size = fb->mmap_map[i].size - (offset - start); + map_offset = fb->mmap_map[i].poff + (offset - start); + break; + } + if (!map_size) { + page += PAGE_SIZE; + continue; + } + if (page + map_size > size) + map_size = size - page; + + pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask); + pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag; + + if (remap_page_range(vma->vm_start + page, map_offset, + map_size, vma->vm_page_prot)) + return -EAGAIN; + + page += map_size; + } + + if (!map_size) + return -EINVAL; - /* - * Initialisation - */ + vma->vm_file = file; + file->f_count++; + vma->vm_flags |= VM_IO; -__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__ */ + if (!fb->mmaped) { + int lastconsole = 0; + + if (info->display_fg) + lastconsole = info->display_fg->vc_num; + fb->mmaped = 1; + if (fb->consolecnt && fb_display[lastconsole].fb_info == info) { + fb->vtconsole = lastconsole; + vt_cons[lastconsole]->vc_mode = KD_GRAPHICS; + } + } + return 0; } +#endif /* __sparc__ */ + /* + * Initialisation + */ -unsigned long atyfb_of_init(unsigned long mem_start, struct device_node *dp) +__initfunc(static int aty_init(struct fb_info_aty *info, const char *name)) { - int i, err, sense; + u32 chip_id; + u32 i; + int j, k; 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); + struct display *disp; + const char *chipname = NULL; + int pll, mclk; +#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP) + int sense; +#endif + + info->aty_cmap_regs = (struct aty_cmap_regs *)(info->ati_regbase+0xc0); + chip_id = aty_ld_le32(CONFIG_CHIP_ID, info); + Gx = chip_id & CFG_CHIP_TYPE; + Rev = (chip_id & CFG_CHIP_REV)>>24; + for (j = 0; j < (sizeof(aty_features)/sizeof(*aty_features)); j++) + if (aty_features[j].chip_type == Gx) { + chipname = aty_features[j].name; + break; + } + if (!chipname) { + printk("atyfb: Unknown mach64 0x%04x\n", Gx); + return 0; + } else + printk("atyfb: %s [0x%04x rev 0x%2x] ", chipname, Gx, Rev); + if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) { + info->bus_type = (aty_ld_le32(CONFIG_STAT0, info) >> 0) & 0x07; + info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) >> 3) & 0x07; + /* FIXME: clockchip/RAMDAC probing? */ +#ifdef CONFIG_ATARI + info->dac_type = DAC_ATI68860_B; + info->clk_type = CLK_ATI18818_1; +#else + info->dac_type = DAC_IBMRGB514; + info->clk_type = CLK_IBMRGB514; +#endif + /* FIXME */ + pll = 135; + mclk = 50; + } else { + info->bus_type = PCI; + info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) & 0x07); + info->dac_type = DAC_INTERNAL; + info->clk_type = CLK_INTERNAL; + if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) { + pll = 135; + mclk = 60; + } else { + mclk = info->ram_type >= SDRAM ? 67 : 63; + if ((Gx == VT_CHIP_ID) && (Rev == 0x08)) { + /* VTA3 */ + pll = 170; + } else if (((Gx == VT_CHIP_ID) && ((Rev == 0x40) || + (Rev == 0x48))) || + ((Gx == VT_CHIP_ID) && ((Rev == 0x01) || + (Rev == 0x9a))) || + (Gx == VU_CHIP_ID)) { + /* VTA4 or VTB */ + pll = 200; + } else if (Gx == VT_CHIP_ID) { + /* other VT */ + pll = 135; + mclk = 63; + } else if ((Gx == GT_CHIP_ID) && (Rev & 0x01)) { + /* RAGE II */ + pll = 170; + } else if (((Gx == GT_CHIP_ID) && (Rev & 0x02)) || + (Gx == GU_CHIP_ID)) { + /* RAGE II+ */ + pll = 200; + } else if ((Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) || + (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || + (Gx == GQ_CHIP_ID)) { + /* RAGE PRO */ + pll = 230; + } else { + /* other RAGE */ + pll = 135; + mclk = 63; + } } } - 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) { + if (mclk < 44) + info->mem_refresh_rate = 0; /* 000 = 10 Mhz - 43 Mhz */ + else if (mclk < 50) + info->mem_refresh_rate = 1; /* 001 = 44 Mhz - 49 Mhz */ + else if (mclk < 55) + info->mem_refresh_rate = 2; /* 010 = 50 Mhz - 54 Mhz */ + else if (mclk < 66) + info->mem_refresh_rate = 3; /* 011 = 55 Mhz - 65 Mhz */ + else if (mclk < 75) + info->mem_refresh_rate = 4; /* 100 = 66 Mhz - 74 Mhz */ + else if (mclk < 80) + info->mem_refresh_rate = 5; /* 101 = 75 Mhz - 79 Mhz */ + else if (mclk < 100) + info->mem_refresh_rate = 6; /* 110 = 80 Mhz - 100 Mhz */ + else + info->mem_refresh_rate = 7; /* 111 = 100 Mhz and above */ + printk("%d MHz PLL, %d Mhz MCLK\n", pll, mclk); + info->pll_per = 1000000/pll; + info->mclk_per = 1000000/mclk; + + i = aty_ld_le32(MEM_CNTL, info); + if (((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) || + ((Gx == VT_CHIP_ID) && (Rev & 0x01)) || (Gx == VU_CHIP_ID) || + (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) || + (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID)) + switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ case MEM_SIZE_512K: - total_vram = 0x80000; + info->total_vram = 0x80000; break; case MEM_SIZE_1M: - total_vram = 0x100000; + info->total_vram = 0x100000; break; - case MEM_SIZE_2M: - total_vram = 0x200000; + case MEM_SIZE_2M_GTB: + info->total_vram = 0x200000; break; - case MEM_SIZE_4M: - total_vram = 0x400000; + case MEM_SIZE_4M_GTB: + info->total_vram = 0x400000; break; - case MEM_SIZE_6M: - total_vram = 0x600000; + case MEM_SIZE_6M_GTB: + info->total_vram = 0x600000; break; - case MEM_SIZE_8M: - total_vram = 0x800000; + case MEM_SIZE_8M_GTB: + info->total_vram = 0x800000; break; default: - total_vram = 0x80000; + info->total_vram = 0x80000; } else - switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ + switch (i & MEM_SIZE_ALIAS) { case MEM_SIZE_512K: - total_vram = 0x80000; + info->total_vram = 0x80000; break; case MEM_SIZE_1M: - total_vram = 0x100000; + info->total_vram = 0x100000; break; - case MEM_SIZE_2M_GTB: - total_vram = 0x200000; + case MEM_SIZE_2M: + info->total_vram = 0x200000; break; - case MEM_SIZE_4M_GTB: - total_vram = 0x400000; + case MEM_SIZE_4M: + info->total_vram = 0x400000; break; - case MEM_SIZE_6M_GTB: - total_vram = 0x600000; + case MEM_SIZE_6M: + info->total_vram = 0x600000; break; - case MEM_SIZE_8M_GTB: - total_vram = 0x800000; + case MEM_SIZE_8M: + info->total_vram = 0x800000; break; default: - total_vram = 0x80000; + info->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 (info->bus_type == ISA) + if ((info->total_vram == 0x400000) || (info->total_vram == 0x800000)) { + /* protect GUI-regs if complete Aperture is VRAM */ + info->total_vram -= GUI_RESERVE; } - 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; +#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP) + if (default_vmode == VMODE_NVRAM) { + default_vmode = nvram_read_byte(NV_VMODE); + if (default_vmode <= 0 || default_vmode > VMODE_MAX) + default_vmode = VMODE_CHOOSE; + } + if (default_vmode == VMODE_CHOOSE) { + sense = read_aty_sense(info); + default_vmode = mac_map_monitor_sense(sense); + } + if (default_vmode <= 0 || default_vmode > VMODE_MAX) + default_vmode = VMODE_640_480_60; + if (default_cmode == CMODE_NVRAM) + default_cmode = nvram_read_byte(NV_CMODE); + if (default_cmode < CMODE_8 || default_cmode > CMODE_32) + default_cmode = CMODE_8; + if (mac_vmode_to_var(default_vmode, default_cmode, &var)) + var = default_var; +#else /* !CONFIG_PMAC && !CONFIG_CHRP */ + var = default_var; +#endif /* !CONFIG_PMAC && !CONFIG_CHRP */ + var.accel_flags |= FB_ACCELF_TEXT; + if (atyfb_decode_var(&var, &info->default_par, info)) { + printk("atyfb: can't set default video mode\n"); + return 0; } - /* - * Reduce the pixel size if we don't have enough VRAM. - */ + if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) + strcat(atyfb_name, "GX"); + else if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) + strcat(atyfb_name, "CT"); + else if ((Gx == VT_CHIP_ID) || (Gx == VU_CHIP_ID)) + strcat(atyfb_name, "VT"); + else + strcat(atyfb_name, "GT"); + + disp = &info->disp; + + strcpy(info->fb_info.modename, atyfb_name); + info->fb_info.node = -1; + info->fb_info.fbops = &atyfb_ops; + info->fb_info.disp = disp; + strcpy(info->fb_info.fontname, fontname); + info->fb_info.changevar = NULL; + info->fb_info.switch_con = &atyfbcon_switch; + info->fb_info.updatevar = &atyfbcon_updatevar; + info->fb_info.blank = &atyfbcon_blank; + + for (j = 0; j < 16; j++) { + k = color_table[j]; + info->palette[j].red = default_red[k]; + info->palette[j].green = default_grn[k]; + info->palette[j].blue = default_blu[k]; + } + + if ((Gx == VT_CHIP_ID) || (Gx == GT_CHIP_ID) || (Gx == GU_CHIP_ID) || + (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) || + (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) || + (Gx == VU_CHIP_ID)) { + info->cursor = kmalloc(sizeof(struct aty_cursor), GFP_ATOMIC); + if (info->cursor) + memset(info->cursor, 0, sizeof(*info->cursor)); + } + + disp->dispsw = &info->dispsw; + atyfb_set_var(&var, -1, &info->fb_info); - 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); + if (register_framebuffer(&info->fb_info) < 0) + return 0; + + printk("fb%d: %s frame buffer device on %s\n", + GET_FB_IDX(info->fb_info.node), atyfb_name, name); + return 1; +} + +__initfunc(void atyfb_init(void)) +{ +#if defined(CONFIG_FB_OF) + /* We don't want to be called like this. */ + /* We rely on Open Firmware (offb) instead. */ +#elif defined(CONFIG_PCI) + struct pci_dev *pdev; + struct fb_info_aty *info; + unsigned long addr; +#ifdef __sparc__ + extern int con_is_present(void); + u32 chip_id; + int i, j; + + /* Do not attach when we have a serial console. */ + if (!con_is_present()) + return; +#else + u16 tmp; +#endif + + for (pdev = pci_devices; pdev; pdev = pdev->next) { + if (((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) && + (pdev->vendor == PCI_VENDOR_ID_ATI)) { + + info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC); + if (!info) { + printk("atyfb_init: can't alloc fb_info_aty\n"); + return; + } + memset(info, 0, sizeof(struct fb_info_aty)); + + addr = pdev->base_address[0]; + if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) + addr = pdev->base_address[1]; + if (!addr) + continue; + +#ifdef __sparc__ + /* + * Map memory-mapped registers. + */ + info->ati_regbase = addr + 0x7ffc00; + info->ati_regbase_phys = __pa(addr + 0x7ffc00); + + /* + * Map in big-endian aperture. + */ + info->frame_buffer = (unsigned long)(addr + 0x800000); + info->frame_buffer_phys = __pa(addr + 0x800000); + + /* + * Figure mmap addresses from PCI config space. + * Split Framebuffer in big- and little-endian halfs. + */ + for (i = 0; i < 6 && pdev->base_address[i]; i++) + /* nothing */; + j = i + 1; + + info->mmap_map = kmalloc(j * sizeof(*info->mmap_map), GFP_ATOMIC); + if (!info->mmap_map) { + printk("atyfb_init: can't alloc mmap_map\n"); + kfree(info); + } + + memset(info->mmap_map, 0, j * sizeof(*info->mmap_map)); + for (i = j = 0; i < 6 && pdev->base_address[i]; i++) { + int io, breg = PCI_BASE_ADDRESS_0 + (i << 2); + unsigned long base; + u32 size, pbase; + + base = pdev->base_address[i]; + + io = (base & PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO; + + pci_read_config_dword(pdev, breg, &pbase); + pci_write_config_dword(pdev, breg, 0xffffffff); + pci_read_config_dword(pdev, breg, &size); + pci_write_config_dword(pdev, breg, pbase); + + if (io) + size &= ~1; + size = ~(size) + 1; + + if (base == addr) { + info->mmap_map[j].voff = (pbase + 0x800000) + & PAGE_MASK; + info->mmap_map[j].poff = __pa((base + 0x800000) + & PAGE_MASK); + info->mmap_map[j].size = 0x800000; + info->mmap_map[j].prot_mask = _PAGE_CACHE; + info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE; + size -= 0x800000; + j++; + } + + info->mmap_map[j].voff = pbase & PAGE_MASK; + info->mmap_map[j].poff = __pa(base & PAGE_MASK); + info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK; + info->mmap_map[j].prot_mask = _PAGE_CACHE; + info->mmap_map[j].prot_flag = _PAGE_E; + j++; + } + + /* + * Fix PROMs idea of MEM_CNTL settings... + */ + chip_id = aty_ld_le32(CONFIG_CHIP_ID, info) & CFG_CHIP_TYPE; + if ((chip_id & 0xffff) == VT_CHIP_ID && !((chip_id >> 24) & 1)) { + u32 mem = aty_ld_le32(MEM_CNTL, info); + switch (mem & 0x0f) { + case 3: + mem = (mem & ~(0x0f)) | 2; + break; + case 7: + mem = (mem & ~(0x0f)) | 3; + break; + case 9: + mem = (mem & ~(0x0f)) | 4; + break; + case 11: + mem = (mem & ~(0x0f)) | 5; + break; + default: + break; + } + if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM) + mem &= ~(0x00f00000); + aty_st_le32(MEM_CNTL, mem, info); + } + + /* + * Set default vmode and cmode from PROM properties. + */ + { + struct pcidev_cookie *cookie = pdev->sysdata; + int node = cookie->prom_node; + int width = prom_getintdefault(node, "width", 1024); + int height = prom_getintdefault(node, "height", 768); + int depth = prom_getintdefault(node, "depth", 8); + + switch (width) { + case 1024: + if (height == 768) + default_var = default_var_1024x768; + break; + case 1152: + if (height == 900) + default_var = default_var_1152x900; + break; + case 1280: + if (height == 1024) + default_var = default_var_1280x1024; + break; + default: + break; + } + + switch (depth) { + case 8: + default_var.bits_per_pixel = 8; + break; + case 16: + default_var.bits_per_pixel = 16; + break; + case 24: + default_var.bits_per_pixel = 24; + break; + case 32: + default_var.bits_per_pixel = 32; + break; + default: + break; + } + } + +#else /* __sparc__ */ + + info->ati_regbase_phys = 0x7ff000 + addr; + info->ati_regbase = (unsigned long) + ioremap(info->ati_regbase_phys, 0x1000); + + info->ati_regbase_phys += 0xc00; + info->ati_regbase += 0xc00; + + /* + * Enable memory-space accesses using config-space + * command register. + */ + pci_read_config_word(pdev, PCI_COMMAND, &tmp); + if (!(tmp & PCI_COMMAND_MEMORY)) { + tmp |= PCI_COMMAND_MEMORY; + pci_write_config_word(pdev, PCI_COMMAND, tmp); + } + +#ifdef __BIG_ENDIAN + /* Use the big-endian aperture */ + addr += 0x800000; +#endif + + /* Map in frame buffer */ + info->frame_buffer_phys = addr; + info->frame_buffer = (unsigned long)ioremap(addr, 0x800000); + +#endif /* __sparc__ */ + + if (!aty_init(info, "PCI")) { + if (info->mmap_map) + kfree(info->mmap_map); + kfree(info); + } } + } +#elif defined(CONFIG_ATARI) + int m64_num; + struct fb_info_aty *info; + + for (m64_num = 0; m64_num < mach64_count; m64_num++) { + if (!phys_vmembase[m64_num] || !phys_size[m64_num] || + !phys_guiregbase[m64_num]) { + printk(" phys_*[%d] parameters not set => returning early. \n", + m64_num); + continue; + } + + info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC); + /* - * adjust the video mode smaller if there still is not enough VRAM + * Map the video memory (physical address given) to somewhere in the + * kernel address space. */ - 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)); + info->frame_buffer = kernel_map(phys_vmembase[m64_num], + phys_size[m64_num], + KERNELMAP_NOCACHE_SER, NULL); + info->frame_buffer_phys = info->frame_buffer; + info->ati_regbase = kernel_map(phys_guiregbase[m64_num], 0x10000, + KERNELMAP_NOCACHE_SER, NULL)+0xFC00ul; + info->ati_regbase_phys = info->ati_regbase; + + if (!aty_init(info, "ISA bus")) { + kfree(info); + /* This is insufficient! kernel_map has added two large chunks!! */ + return; + } } +#endif +} - 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); - } +#ifdef CONFIG_FB_OF +__initfunc(void atyfb_of_init(struct device_node *dp)) +{ + unsigned long addr; + u8 bus, devfn; + u16 cmd; + struct fb_info_aty *info; + int i; + + for (; dp; dp = dp->next) { + switch (dp->n_addrs) { + case 1: + case 3: + addr = dp->addrs[0].address; + break; + case 4: + addr = dp->addrs[1].address; + break; + default: + printk("Warning: got %d adresses for ATY:\n", dp->n_addrs); + for (i = 0; i < dp->n_addrs; i++) + printk(" %08x-%08x", dp->addrs[i].address, + dp->addrs[i].address+dp->addrs[i].size-1); + if (dp->n_addrs) + printk("\n"); + continue; + } - 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); + info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC); + + info->ati_regbase = (unsigned long)ioremap(0x7ff000+addr, + 0x1000)+0xc00; + info->ati_regbase_phys = 0x7ff000+addr; + info->ati_regbase = (unsigned long)ioremap(info->ati_regbase_phys, + 0x1000); + info->ati_regbase_phys += 0xc00; + info->ati_regbase += 0xc00; + + /* 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); + } + } + +#ifdef __BIG_ENDIAN + /* Use the big-endian aperture */ + addr += 0x800000; +#endif + + /* Map in frame buffer */ + info->frame_buffer_phys = addr; + info->frame_buffer = (unsigned long)ioremap(addr, 0x800000); - printk("fb%d: %s frame buffer device on %s\n", GET_FB_IDX(fb_info.node), - atyfb_name, dp->full_name); + if (!aty_init(info, dp->full_name)) { + kfree(info); + return; + } #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; + if (!console_fb_info) + console_fb_info = &info->fb_info; +#endif /* CONFIG_FB_COMPAT_XPMAC */ } -#endif /* CONFIG_FB_COMPAT_XPMAC) */ - - return mem_start; } +#endif /* CONFIG_FB_OF */ -/* XXX: doesn't work yet */ -void atyfb_setup(char *options, int *ints) +__initfunc(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, "font:", 5)) { + char *p; + int i; + + p = this_opt + 5; + for (i = 0; i < sizeof(fontname) - 1; i++) + if (!*p || *p == ' ' || *p == ',') + break; + memcpy(fontname, this_opt + 5, i); + fontname[i] = 0; + } +#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP) if (!strncmp(this_opt, "vmode:", 6)) { - vmode = simple_strtoul(this_opt+6, NULL, 0); + int vmode = simple_strtoul(this_opt+6, NULL, 0); if (vmode > 0 && vmode <= VMODE_MAX) - default_video_mode = vmode; + default_vmode = vmode; } else if (!strncmp(this_opt, "cmode:", 6)) { - depth = simple_strtoul(this_opt+6, NULL, 0); + int depth = simple_strtoul(this_opt+6, NULL, 0); switch (depth) { case 8: - default_color_mode = CMODE_8; + default_cmode = 0; break; case 15: case 16: - default_color_mode = CMODE_16; + default_cmode = 1; break; case 24: case 32: - default_color_mode = CMODE_32; + default_cmode = 2; break; - }; + } + } +#endif +#ifdef CONFIG_ATARI + /* + * Why do we need this silly Mach64 argument? + * We are already here because of mach64= so its redundant. + */ + if (MACH_IS_ATARI && (!strncmp(this_opt, "Mach64:", 7))) { + static unsigned char m64_num; + static char mach64_str[80]; + strncpy(mach64_str, this_opt+7, 80); + if (!store_video_par(mach64_str, m64_num)) { + m64_num++; + mach64_count = m64_num; + } } +#endif } } +#ifdef CONFIG_ATARI +__initfunc(static int store_video_par(char *video_str, unsigned char m64_num)) +{ + char *p; + unsigned long vmembase, size, guiregbase; + + printk("store_video_par() '%s' \n", video_str); + + if (!(p = strtoke(video_str, ";")) || !*p) + goto mach64_invalid; + vmembase = simple_strtoul(p, NULL, 0); + if (!(p = strtoke(NULL, ";")) || !*p) + goto mach64_invalid; + size = simple_strtoul(p, NULL, 0); + if (!(p = strtoke(NULL, ";")) || !*p) + goto mach64_invalid; + guiregbase = simple_strtoul(p, NULL, 0); + + phys_vmembase[m64_num] = vmembase; + phys_size[m64_num] = size; + phys_guiregbase[m64_num] = guiregbase; + printk(" stored them all: $%08lX $%08lX $%08lX \n", vmembase, size, + guiregbase); + return 0; + +mach64_invalid: + phys_vmembase[m64_num] = 0; + return -1; +} + +__initfunc(static char *strtoke(char *s, const char *ct)) +{ + static char *ssave = NULL; + char *sbegin, *send; + + sbegin = s ? s : ssave; + if (!sbegin) + return NULL; + if (*sbegin == '\0') { + ssave = NULL; + return NULL; + } + send = strpbrk(sbegin, ct); + if (send && *send != '\0') + *send++ = '\0'; + ssave = send; + return sbegin; +} +#endif /* CONFIG_ATARI */ -static int atyfbcon_switch(int con, struct fb_info *info) +static int atyfbcon_switch(int con, struct fb_info *fb) { + struct fb_info_aty *info = (struct fb_info_aty *)fb; 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); + atyfb_getcolreg, fb); + + /* Erase HW Cursor */ + if (info->cursor) + atyfb_cursor(&fb_display[currcon], CM_ERASE, + info->cursor->pos.x, info->cursor->pos.y); + currcon = con; - decode_var(&fb_display[con].var, &par); - atyfb_set_par(&par); + + atyfb_decode_var(&fb_display[con].var, &par, info); + atyfb_set_par(&par, info); + /* Install new colormap */ - do_install_cmap(con, info); - return 0; + do_install_cmap(con, fb); + + /* Install hw cursor */ + if (info->cursor) { + aty_set_cursor_color(info, cursor_pixel_map, cursor_color_map, + cursor_color_map, cursor_color_map); + aty_set_cursor_shape(info); + } + return 1; } /* * Update the `var' structure (called by fbcon.c) */ -static int atyfbcon_updatevar(int con, struct fb_info *info) +static int atyfbcon_updatevar(int con, struct fb_info *fb) { - current_par.yoffset = fb_display[con].var.yoffset; - set_off_pitch(¤t_par); + struct fb_info_aty *info = (struct fb_info_aty *)fb; + + info->current_par.crtc.yoffset = fb_display[con].var.yoffset; + set_off_pitch(&info->current_par, info); return 0; } @@ -1425,20 +2956,30 @@ static int atyfbcon_updatevar(int con, struct fb_info *info) * Blank the display. */ -static void atyfbcon_blank(int blank, struct fb_info *info) +static void atyfbcon_blank(int blank, struct fb_info *fb) { - 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); + struct fb_info_aty *info = (struct fb_info_aty *)fb; + u8 gen_cntl; + + gen_cntl = aty_ld_8(CRTC_GEN_CNTL, info); + if (blank > 0) + switch (blank-1) { + case VESA_NO_BLANKING: + gen_cntl |= 0x40; + break; + case VESA_VSYNC_SUSPEND: + gen_cntl |= 0x8; + break; + case VESA_HSYNC_SUSPEND: + gen_cntl |= 0x4; + break; + case VESA_POWERDOWN: + gen_cntl |= 0x4c; + break; + } + else + gen_cntl &= ~(0x4c); + aty_st_8(CRTC_GEN_CNTL, gen_cntl, info); } @@ -1448,13 +2989,15 @@ static void atyfbcon_blank(int blank, struct fb_info *info) */ static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp, struct fb_info *info) + u_int *transp, struct fb_info *fb) { + struct fb_info_aty *info = (struct fb_info_aty *)fb; + if (regno > 255) return 1; - *red = palette[regno].red; - *green = palette[regno].green; - *blue = palette[regno].blue; + *red = info->palette[regno].red; + *green = info->palette[regno].green; + *blue = info->palette[regno].blue; return 0; } @@ -1466,38 +3009,42 @@ static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, */ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *info) + u_int transp, struct fb_info *fb) { + struct fb_info_aty *info = (struct fb_info_aty *)fb; 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); + info->palette[regno].red = red; + info->palette[regno].green = green; + info->palette[regno].blue = blue; + i = aty_ld_8(DAC_CNTL, info) & 0xfc; + if ((Gx == GT_CHIP_ID) || (Gx == GU_CHIP_ID) || (Gx == LG_CHIP_ID) || + (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) || (Gx == GI_CHIP_ID) || + (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID)) + i |= 0x2; /*DAC_CNTL|0x2 turns off the extra brightness for gt*/ + aty_st_8(DAC_CNTL, i, info); + aty_st_8(DAC_REGS + DAC_MASK, 0xff, info); eieio(); - scale = ((chip_type != MACH64_GX_ID) && - (current_par.cmode == CMODE_16)) ? 3 : 0; - aty_WaitQueue(4); - aty_cmap_regs->windex = regno << scale; + scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) && + (info->current_par.crtc.bpp == 16)) ? 3 : 0; + info->aty_cmap_regs->windex = regno << scale; eieio(); - aty_cmap_regs->lut = red << scale; + info->aty_cmap_regs->lut = red << scale; eieio(); - aty_cmap_regs->lut = green << scale; + info->aty_cmap_regs->lut = green << scale; eieio(); - aty_cmap_regs->lut = blue << scale; + info->aty_cmap_regs->lut = blue << scale; eieio(); if (regno < 16) { -#ifdef CONFIG_FBCON_CFB16 +#ifdef FBCON_HAS_CFB16 fbcon_cfb16_cmap[regno] = (regno << 10) | (regno << 5) | regno; #endif -#ifdef CONFIG_FBCON_CFB32 +#ifdef FBCON_HAS_CFB24 + fbcon_cfb24_cmap[regno] = (regno << 16) | (regno << 8) | regno; +#endif +#ifdef FBCON_HAS_CFB32 fbcon_cfb32_cmap[regno] = (regno << 24) | (regno << 16) | (regno << 8) | regno; #endif @@ -1513,10 +3060,11 @@ static void do_install_cmap(int con, struct fb_info *info) 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); + else { + int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; + fb_set_cmap(fb_default_cmap(size), &fb_display[con].var, 1, + atyfb_setcolreg, info); + } } @@ -1524,15 +3072,34 @@ static void do_install_cmap(int con, struct fb_info *info) * Accelerated functions */ -void aty_waitblit(void) +static inline void draw_rect(s16 x, s16 y, u16 width, u16 height, + struct fb_info_aty *info) { - aty_WaitIdleEmpty(); /* Make sure that all commands have finished */ + /* perform rectangle fill */ + wait_for_fifo(2, info); + aty_st_le32(DST_Y_X, (x << 16) | y, info); + aty_st_le32(DST_HEIGHT_WIDTH, (width << 16) | height, info); } -void aty_rectcopy(int srcx, int srcy, int dstx, int dsty, u_int width, - u_int height) +static inline void aty_rectcopy(int srcx, int srcy, int dstx, int dsty, + u_int width, u_int height, + struct fb_info_aty *info) { - u_int direction = 0; + u32 direction = DST_LAST_PEL; + u32 pitch_value; + + if (!width || !height) + return; + + pitch_value = info->current_par.crtc.vxres; + if (info->current_par.crtc.bpp == 24) { + /* In 24 bpp, the engine is in 8 bpp - this requires that all */ + /* horizontal coordinates and widths must be adjusted */ + pitch_value *= 3; + srcx *= 3; + dstx *= 3; + width *= 3; + } if (srcy < dsty) { dsty += height - 1; @@ -1546,46 +3113,40 @@ void aty_rectcopy(int srcx, int srcy, int dstx, int dsty, u_int width, } 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 */ - + wait_for_fifo(5, info); + aty_st_le32(DP_SRC, FRGD_SRC_BLIT, info); /* - * 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. + * ++Geert: + * Warning: SRC_OFF_PITCH may be thrashed by writing to other registers + * (e.g. CRTC_H_TOTAL_DISP, DP_SRC, DP_FRGD_CLR) */ - aty_st_le32(DST_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); + aty_st_le32(SRC_OFF_PITCH, (pitch_value / 8) << 22, info); + aty_st_le32(SRC_Y_X, (srcx << 16) | srcy, info); + aty_st_le32(SRC_HEIGHT1_WIDTH1, (width << 16) | height, info); + aty_st_le32(DST_CNTL, direction, info); + draw_rect(dstx, dsty, width, height, info); } -void aty_rectfill(int dstx, int dsty, u_int width, u_int height, u_int color) +static inline void aty_rectfill(int dstx, int dsty, u_int width, u_int height, + u_int color, struct fb_info_aty *info) { 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)); + if (info->current_par.crtc.bpp == 24) { + /* In 24 bpp, the engine is in 8 bpp - this requires that all */ + /* horizontal coordinates and widths must be adjusted */ + dstx *= 3; + width *= 3; + } - aty_WaitIdleEmpty(); /* Make sure that all commands have finished */ + wait_for_fifo(3, info); + aty_st_le32(DP_FRGD_CLR, color, info); + aty_st_le32(DP_SRC, BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE, + info); + aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM | + DST_X_LEFT_TO_RIGHT, info); + draw_rect(dstx, dsty, width, height, info); } @@ -1593,9 +3154,16 @@ void aty_rectfill(int dstx, int dsty, u_int width, u_int height, u_int color) * Text console acceleration */ -static void fbcon_aty8_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) +static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) { +#ifdef __sparc__ + struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); + + if (fb->mmaped && currcon == fb->vtconsole) + return; +#endif + sx *= p->fontwidth; sy *= p->fontheight; dx *= p->fontwidth; @@ -1603,13 +3171,22 @@ static void fbcon_aty8_bmove(struct display *p, int sy, int sx, int dy, int dx, width *= p->fontwidth; height *= p->fontheight; - aty_rectcopy(sx, sy, dx, dy, width, height); + aty_rectcopy(sx, sy, dx, dy, width, height, + (struct fb_info_aty *)p->fb_info); } -static void fbcon_aty8_clear(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width) +static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width) { - u32 bgx = attr_bgcol_ec(p, conp); + u32 bgx; +#ifdef __sparc__ + struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); + + if (fb->mmaped && currcon == fb->vtconsole) + return; +#endif + + bgx = attr_bgcol_ec(p, conp); bgx |= (bgx << 8); bgx |= (bgx << 16); @@ -1618,68 +3195,154 @@ static void fbcon_aty8_clear(struct vc_data *conp, struct display *p, int sy, width *= p->fontwidth; height *= p->fontheight; - aty_rectfill(sx, sy, width, height, bgx); + aty_rectfill(sx, sy, width, height, bgx, + (struct fb_info_aty *)p->fb_info); } +#ifdef FBCON_HAS_CFB8 static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) { - aty_waitblit(); +#ifdef __sparc__ + struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); + + if (fb->mmaped && currcon == fb->vtconsole) + return; +#endif + + wait_for_idle((struct fb_info_aty *)p->fb_info); 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) + const unsigned short *s, int count, int yy, + int xx) { - aty_waitblit(); +#ifdef __sparc__ + struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); + + if (fb->mmaped && currcon == fb->vtconsole) + return; +#endif + + wait_for_idle((struct fb_info_aty *)p->fb_info); 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 + fbcon_cfb8_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty8_putc, + fbcon_aty8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins, + FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; +#endif +#ifdef FBCON_HAS_CFB16 +static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx) +{ +#ifdef __sparc__ + struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); -#ifdef CONFIG_FB_COMPAT_XPMAC + if (fb->mmaped && currcon == fb->vtconsole) + return; +#endif - /* - * Backward compatibility mode for Xpmac - */ + wait_for_idle((struct fb_info_aty *)p->fb_info); + fbcon_cfb16_putc(conp, p, c, yy, xx); +} -static int atyfb_console_setmode(struct vc_mode *mode, int doit) +static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int yy, + int xx) { - int err; - struct fb_var_screeninfo var; - struct atyfb_par par; - int vmode, cmode; +#ifdef __sparc__ + struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); - if (mode->mode <= 0 || mode->mode > VMODE_MAX ) - return -EINVAL; - vmode = mode->mode; + if (fb->mmaped && currcon == fb->vtconsole) + return; +#endif - 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; + wait_for_idle((struct fb_info_aty *)p->fb_info); + fbcon_cfb16_putcs(conp, p, s, count, yy, xx); } -#endif /* CONFIG_FB_COMPAT_XPMAC */ +static struct display_switch fbcon_aty16 = { + fbcon_cfb16_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty16_putc, + fbcon_aty16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins, + FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; +#endif + +#ifdef FBCON_HAS_CFB24 +static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx) +{ +#ifdef __sparc__ + struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); + + if (fb->mmaped && currcon == fb->vtconsole) + return; +#endif + + wait_for_idle((struct fb_info_aty *)p->fb_info); + fbcon_cfb24_putc(conp, p, c, yy, xx); +} + +static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int yy, + int xx) +{ +#ifdef __sparc__ + struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); + + if (fb->mmaped && currcon == fb->vtconsole) + return; +#endif + + wait_for_idle((struct fb_info_aty *)p->fb_info); + fbcon_cfb24_putcs(conp, p, s, count, yy, xx); +} + +static struct display_switch fbcon_aty24 = { + fbcon_cfb24_setup, fbcon_cfb24_bmove, fbcon_cfb24_clear, fbcon_aty24_putc, + fbcon_aty24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_cfb24_clear_margins, + FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; +#endif + +#ifdef FBCON_HAS_CFB32 +static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx) +{ +#ifdef __sparc__ + struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); + + if (fb->mmaped && currcon == fb->vtconsole) + return; +#endif + + wait_for_idle((struct fb_info_aty *)p->fb_info); + fbcon_cfb32_putc(conp, p, c, yy, xx); +} + +static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int yy, + int xx) +{ +#ifdef __sparc__ + struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info); + + if (fb->mmaped && currcon == fb->vtconsole) + return; +#endif + + wait_for_idle((struct fb_info_aty *)p->fb_info); + fbcon_cfb32_putcs(conp, p, s, count, yy, xx); +} + +static struct display_switch fbcon_aty32 = { + fbcon_cfb32_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty32_putc, + fbcon_aty32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_cfb32_clear_margins, + FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; +#endif diff --git a/drivers/video/bwtwofb.c b/drivers/video/bwtwofb.c new file mode 100644 index 000000000..a907fc2d1 --- /dev/null +++ b/drivers/video/bwtwofb.c @@ -0,0 +1,222 @@ +/* $Id: bwtwofb.c,v 1.1 1998/07/21 14:50:48 jj Exp $ + * bwtwofb.c: BWtwo frame buffer driver + * + * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) + * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) + * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) + * Copyright (C) 1998 Pavel Machek (pavel@ucw.cz) + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/sched.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 <linux/selection.h> + +#include "sbusfb.h" +#include <asm/io.h> +#ifndef __sparc_v9__ +#include <asm/sun4paddr.h> +#endif + +#include "fbcon-mfb.h" + +/* OBio addresses for the bwtwo registers */ +#define BWTWO_REGISTER_OFFSET 0x400000 + +struct bw2_regs { + struct bt_regs bt; + volatile u8 control; + volatile u8 status; + volatile u8 cursor_start; + volatile u8 cursor_end; + volatile u8 h_blank_start; + volatile u8 h_blank_end; + volatile u8 h_sync_start; + volatile u8 h_sync_end; + volatile u8 comp_sync_end; + volatile u8 v_blank_start_high; + volatile u8 v_blank_start_low; + volatile u8 v_blank_end; + volatile u8 v_sync_start; + volatile u8 v_sync_end; + volatile u8 xfer_holdoff_start; + volatile u8 xfer_holdoff_end; +}; + +/* Status Register Constants */ +#define BWTWO_SR_RES_MASK 0x70 +#define BWTWO_SR_1600_1280 0x50 +#define BWTWO_SR_1152_900_76_A 0x40 +#define BWTWO_SR_1152_900_76_B 0x60 +#define BWTWO_SR_ID_MASK 0x0f +#define BWTWO_SR_ID_MONO 0x02 +#define BWTWO_SR_ID_MONO_ECL 0x03 +#define BWTWO_SR_ID_MSYNC 0x04 + +/* Control Register Constants */ +#define BWTWO_CTL_ENABLE_INTS 0x80 +#define BWTWO_CTL_ENABLE_VIDEO 0x40 +#define BWTWO_CTL_ENABLE_TIMING 0x20 +#define BWTWO_CTL_ENABLE_CURCMP 0x10 +#define BWTWO_CTL_XTAL_MASK 0x0C +#define BWTWO_CTL_DIVISOR_MASK 0x03 + +/* Status Register Constants */ +#define BWTWO_STAT_PENDING_INT 0x80 +#define BWTWO_STAT_MSENSE_MASK 0x70 +#define BWTWO_STAT_ID_MASK 0x0f + +static struct sbus_mmap_map bw2_mmap_map[] = { + { 0, 0, SBUS_MMAP_FBSIZE(1) }, + { 0, 0, 0 } +}; + +static void bw2_blank (struct fb_info_sbusfb *fb) +{ + fb->s.bw2.regs->control &= ~BWTWO_CTL_ENABLE_VIDEO; +} + +static void bw2_unblank (struct fb_info_sbusfb *fb) +{ + fb->s.bw2.regs->control |= BWTWO_CTL_ENABLE_VIDEO; +} + +static void bw2_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) +{ + p->screen_base += ((y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin)) >> 3; +} + +static u8 bw2regs_1600[] __initdata = { + 0x14, 0x8b, 0x15, 0x28, 0x16, 0x03, 0x17, 0x13, + 0x18, 0x7b, 0x19, 0x05, 0x1a, 0x34, 0x1b, 0x2e, + 0x1c, 0x00, 0x1d, 0x0a, 0x1e, 0xff, 0x1f, 0x01, + 0x10, 0x21, 0 +}; + +static u8 bw2regs_ecl[] __initdata = { + 0x14, 0x65, 0x15, 0x1e, 0x16, 0x04, 0x17, 0x0c, + 0x18, 0x5e, 0x19, 0x03, 0x1a, 0xa7, 0x1b, 0x23, + 0x1c, 0x00, 0x1d, 0x08, 0x1e, 0xff, 0x1f, 0x01, + 0x10, 0x20, 0 +}; + +static u8 bw2regs_analog[] __initdata = { + 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x03, 0x17, 0x13, + 0x18, 0xb0, 0x19, 0x03, 0x1a, 0xa6, 0x1b, 0x22, + 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01, + 0x10, 0x20, 0 +}; + +static u8 bw2regs_76hz[] __initdata = { + 0x14, 0xb7, 0x15, 0x27, 0x16, 0x03, 0x17, 0x0f, + 0x18, 0xae, 0x19, 0x03, 0x1a, 0xae, 0x1b, 0x2a, + 0x1c, 0x01, 0x1d, 0x09, 0x1e, 0xff, 0x1f, 0x01, + 0x10, 0x24, 0 +}; + +static u8 bw2regs_66hz[] __initdata = { + 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x04, 0x17, 0x14, + 0x18, 0xae, 0x19, 0x03, 0x1a, 0xa8, 0x1b, 0x24, + 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01, + 0x10, 0x20, 0 +}; + +static char idstring[60] __initdata = { 0 }; + +__initfunc(char *bwtwofb_init(struct fb_info_sbusfb *fb)) +{ + struct fb_fix_screeninfo *fix = &fb->fix; + struct display *disp = &fb->disp; + struct fbtype *type = &fb->type; +#ifdef CONFIG_SUN4 + unsigned long phys = SUN4_300_BWTWO_PHYSADDR; +#else + unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; +#endif + +#ifndef FBCON_HAS_MFB + return NULL; +#endif + + if (!fb->s.bw2.regs) { + fb->s.bw2.regs = (struct bw2_regs *)sparc_alloc_io(phys+BWTWO_REGISTER_OFFSET, 0, + sizeof(struct bw2_regs), "bw2_regs", fb->iospace, 0); + if (!prom_getbool(fb->prom_node, "width")) { + /* Ugh, broken PROM didn't initialize us. + * Let's deal with this ourselves. + */ + u8 status, mon; + u8 *p; + int sizechange = 0; + + status = fb->s.bw2.regs->status; + mon = status & BWTWO_SR_RES_MASK; + switch (status & BWTWO_SR_ID_MASK) { + case BWTWO_SR_ID_MONO_ECL: + if (mon == BWTWO_SR_1600_1280) { + p = bw2regs_1600; + fb->type.fb_width = 1600; + fb->type.fb_height = 1280; + sizechange = 1; + } else + p = bw2regs_ecl; + break; + case BWTWO_SR_ID_MONO: + p = bw2regs_analog; + break; + case BWTWO_SR_ID_MSYNC: + if (mon == BWTWO_SR_1152_900_76_A || + mon == BWTWO_SR_1152_900_76_B) + p = bw2regs_76hz; + else + p = bw2regs_66hz; + break; + default: + prom_printf("bw2: can't handle SR %02x\n", + status); + prom_halt(); + return NULL; /* fool gcc. */ + } + for ( ; *p; p += 2) + ((u8 *)fb->s.bw2.regs)[p[0]] = p[1]; + } + } + + strcpy(fb->info.modename, "BWtwo"); + strcpy(fix->id, "BWtwo"); + fix->line_length = fb->var.xres_virtual>>3; + + disp->scrollmode = SCROLL_YREDRAW; + if (!disp->screen_base) + disp->screen_base = (char *)sparc_alloc_io(phys, 0, + type->fb_size, "bw2_ram", fb->iospace, 0); + disp->screen_base += (fix->line_length * fb->y_margin + fb->x_margin) >> 3; + fb->dispsw = fbcon_mfb; + fix->visual = FB_VISUAL_MONO01; + + fb->blank = bw2_blank; + fb->unblank = bw2_unblank; + fb->margins = bw2_margins; + + fb->physbase = phys; + fb->mmap_map = bw2_mmap_map; + +#ifdef __sparc_v9__ + sprintf(idstring, "bwtwo at %016lx", phys); +#else + sprintf(idstring, "bwtwo at %x.%08lx", fb->iospace, phys); +#endif + + return idstring; +} diff --git a/drivers/video/cgsixfb.c b/drivers/video/cgsixfb.c new file mode 100644 index 000000000..d5fc9f495 --- /dev/null +++ b/drivers/video/cgsixfb.c @@ -0,0 +1,683 @@ +/* $Id: cgsixfb.c,v 1.7 1998/07/22 12:44:59 jj Exp $ + * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver + * + * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) + * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) + * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/sched.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 <linux/selection.h> + +#include "sbusfb.h" +#include <asm/io.h> + +/* Offset of interesting structures in the OBIO space */ +/* + * Brooktree is the video dac and is funny to program on the cg6. + * (it's even funnier on the cg3) + * The FBC could be the frame buffer control + * The FHC could is the frame buffer hardware control. + */ +#define CG6_ROM_OFFSET 0x0 +#define CG6_BROOKTREE_OFFSET 0x200000 +#define CG6_DHC_OFFSET 0x240000 +#define CG6_ALT_OFFSET 0x280000 +#define CG6_FHC_OFFSET 0x300000 +#define CG6_THC_OFFSET 0x301000 +#define CG6_FBC_OFFSET 0x700000 +#define CG6_TEC_OFFSET 0x701000 +#define CG6_RAM_OFFSET 0x800000 + +/* FHC definitions */ +#define CG6_FHC_FBID_SHIFT 24 +#define CG6_FHC_FBID_MASK 255 +#define CG6_FHC_REV_SHIFT 20 +#define CG6_FHC_REV_MASK 15 +#define CG6_FHC_FROP_DISABLE (1 << 19) +#define CG6_FHC_ROW_DISABLE (1 << 18) +#define CG6_FHC_SRC_DISABLE (1 << 17) +#define CG6_FHC_DST_DISABLE (1 << 16) +#define CG6_FHC_RESET (1 << 15) +#define CG6_FHC_LITTLE_ENDIAN (1 << 13) +#define CG6_FHC_RES_MASK (3 << 11) +#define CG6_FHC_1024 (0 << 11) +#define CG6_FHC_1152 (1 << 11) +#define CG6_FHC_1280 (2 << 11) +#define CG6_FHC_1600 (3 << 11) +#define CG6_FHC_CPU_MASK (3 << 9) +#define CG6_FHC_CPU_SPARC (0 << 9) +#define CG6_FHC_CPU_68020 (1 << 9) +#define CG6_FHC_CPU_386 (2 << 9) +#define CG6_FHC_TEST (1 << 8) +#define CG6_FHC_TEST_X_SHIFT 4 +#define CG6_FHC_TEST_X_MASK 15 +#define CG6_FHC_TEST_Y_SHIFT 0 +#define CG6_FHC_TEST_Y_MASK 15 + +/* FBC mode definitions */ +#define CG6_FBC_BLIT_IGNORE 0x00000000 +#define CG6_FBC_BLIT_NOSRC 0x00100000 +#define CG6_FBC_BLIT_SRC 0x00200000 +#define CG6_FBC_BLIT_ILLEGAL 0x00300000 +#define CG6_FBC_BLIT_MASK 0x00300000 + +#define CG6_FBC_VBLANK 0x00080000 + +#define CG6_FBC_MODE_IGNORE 0x00000000 +#define CG6_FBC_MODE_COLOR8 0x00020000 +#define CG6_FBC_MODE_COLOR1 0x00040000 +#define CG6_FBC_MODE_HRMONO 0x00060000 +#define CG6_FBC_MODE_MASK 0x00060000 + +#define CG6_FBC_DRAW_IGNORE 0x00000000 +#define CG6_FBC_DRAW_RENDER 0x00008000 +#define CG6_FBC_DRAW_PICK 0x00010000 +#define CG6_FBC_DRAW_ILLEGAL 0x00018000 +#define CG6_FBC_DRAW_MASK 0x00018000 + +#define CG6_FBC_BWRITE0_IGNORE 0x00000000 +#define CG6_FBC_BWRITE0_ENABLE 0x00002000 +#define CG6_FBC_BWRITE0_DISABLE 0x00004000 +#define CG6_FBC_BWRITE0_ILLEGAL 0x00006000 +#define CG6_FBC_BWRITE0_MASK 0x00006000 + +#define CG6_FBC_BWRITE1_IGNORE 0x00000000 +#define CG6_FBC_BWRITE1_ENABLE 0x00000800 +#define CG6_FBC_BWRITE1_DISABLE 0x00001000 +#define CG6_FBC_BWRITE1_ILLEGAL 0x00001800 +#define CG6_FBC_BWRITE1_MASK 0x00001800 + +#define CG6_FBC_BREAD_IGNORE 0x00000000 +#define CG6_FBC_BREAD_0 0x00000200 +#define CG6_FBC_BREAD_1 0x00000400 +#define CG6_FBC_BREAD_ILLEGAL 0x00000600 +#define CG6_FBC_BREAD_MASK 0x00000600 + +#define CG6_FBC_BDISP_IGNORE 0x00000000 +#define CG6_FBC_BDISP_0 0x00000080 +#define CG6_FBC_BDISP_1 0x00000100 +#define CG6_FBC_BDISP_ILLEGAL 0x00000180 +#define CG6_FBC_BDISP_MASK 0x00000180 + +#define CG6_FBC_INDEX_MOD 0x00000040 +#define CG6_FBC_INDEX_MASK 0x00000030 + +/* THC definitions */ +#define CG6_THC_MISC_REV_SHIFT 16 +#define CG6_THC_MISC_REV_MASK 15 +#define CG6_THC_MISC_RESET (1 << 12) +#define CG6_THC_MISC_VIDEO (1 << 10) +#define CG6_THC_MISC_SYNC (1 << 9) +#define CG6_THC_MISC_VSYNC (1 << 8) +#define CG6_THC_MISC_SYNC_ENAB (1 << 7) +#define CG6_THC_MISC_CURS_RES (1 << 6) +#define CG6_THC_MISC_INT_ENAB (1 << 5) +#define CG6_THC_MISC_INT (1 << 4) +#define CG6_THC_MISC_INIT 0x9f + +/* The contents are unknown */ +struct cg6_tec { + volatile int tec_matrix; + volatile int tec_clip; + volatile int tec_vdc; +}; + +struct cg6_thc { + uint thc_pad0[512]; + volatile uint thc_hs; /* hsync timing */ + volatile uint thc_hsdvs; + volatile uint thc_hd; + volatile uint thc_vs; /* vsync timing */ + volatile uint thc_vd; + volatile uint thc_refresh; + volatile uint thc_misc; + uint thc_pad1[56]; + volatile uint thc_cursxy; /* cursor x,y position (16 bits each) */ + volatile uint thc_cursmask[32]; /* cursor mask bits */ + volatile uint thc_cursbits[32]; /* what to show where mask enabled */ +}; + +struct cg6_fbc { + u32 xxx0[1]; + volatile u32 mode; + volatile u32 clip; + u32 xxx1[1]; + volatile u32 s; + volatile u32 draw; + volatile u32 blit; + volatile u32 font; + u32 xxx2[24]; + volatile u32 x0, y0, z0, color0; + volatile u32 x1, y1, z1, color1; + volatile u32 x2, y2, z2, color2; + volatile u32 x3, y3, z3, color3; + volatile u32 offx, offy; + u32 xxx3[2]; + volatile u32 incx, incy; + u32 xxx4[2]; + volatile u32 clipminx, clipminy; + u32 xxx5[2]; + volatile u32 clipmaxx, clipmaxy; + u32 xxx6[2]; + volatile u32 fg; + volatile u32 bg; + volatile u32 alu; + volatile u32 pm; + volatile u32 pixelm; + u32 xxx7[2]; + volatile u32 patalign; + volatile u32 pattern[8]; + u32 xxx8[432]; + volatile u32 apointx, apointy, apointz; + u32 xxx9[1]; + volatile u32 rpointx, rpointy, rpointz; + u32 xxx10[5]; + volatile u32 pointr, pointg, pointb, pointa; + volatile u32 alinex, aliney, alinez; + u32 xxx11[1]; + volatile u32 rlinex, rliney, rlinez; + u32 xxx12[5]; + volatile u32 liner, lineg, lineb, linea; + volatile u32 atrix, atriy, atriz; + u32 xxx13[1]; + volatile u32 rtrix, rtriy, rtriz; + u32 xxx14[5]; + volatile u32 trir, trig, trib, tria; + volatile u32 aquadx, aquady, aquadz; + u32 xxx15[1]; + volatile u32 rquadx, rquady, rquadz; + u32 xxx16[5]; + volatile u32 quadr, quadg, quadb, quada; + volatile u32 arectx, arecty, arectz; + u32 xxx17[1]; + volatile u32 rrectx, rrecty, rrectz; + u32 xxx18[5]; + volatile u32 rectr, rectg, rectb, recta; +}; + +static struct sbus_mmap_map cg6_mmap_map[] = { + { CG6_FBC, CG6_FBC_OFFSET, PAGE_SIZE }, + { CG6_TEC, CG6_TEC_OFFSET, PAGE_SIZE }, + { CG6_BTREGS, CG6_BROOKTREE_OFFSET, PAGE_SIZE }, + { CG6_FHC, CG6_FHC_OFFSET, PAGE_SIZE }, + { CG6_THC, CG6_THC_OFFSET, PAGE_SIZE }, + { CG6_ROM, CG6_ROM_OFFSET, 0x10000 }, + { CG6_RAM, CG6_RAM_OFFSET, SBUS_MMAP_FBSIZE(1) }, + { CG6_DHC, CG6_DHC_OFFSET, 0x40000 }, + { 0, 0, 0 } +}; + +static void cg6_setup(struct display *p) +{ + p->next_line = sbusfbinfo(p->fb_info)->var.xres_virtual; + p->next_plane = 0; +} + +static void cg6_clear(struct vc_data *conp, struct display *p, int sy, int sx, + int height, int width) +{ + struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; + register struct cg6_fbc *fbc = fb->s.cg6.fbc; + int x, y, w, h; + int i; + + do { + i = fbc->s; + } while (i & 0x10000000); + fbc->fg = attr_bgcol_ec(p,conp); + fbc->bg = attr_bgcol_ec(p,conp); + fbc->pixelm = ~(0); + fbc->alu = 0xea80ff00; + fbc->s = 0; + fbc->clip = 0; + fbc->pm = ~(0); + + if (p->fontheightlog) { + y = sy << p->fontheightlog; h = height << p->fontheightlog; + } else { + y = sy * p->fontheight; h = height * p->fontheight; + } + if (p->fontwidthlog) { + x = sx << p->fontwidthlog; w = width << p->fontwidthlog; + } else { + x = sx * p->fontwidth; w = width * p->fontwidth; + } + fbc->arecty = y + fb->y_margin; + fbc->arectx = x + fb->x_margin; + fbc->arecty = y + fb->y_margin + h; + fbc->arectx = x + fb->x_margin + w; + do { + i = fbc->draw; + } while (i < 0 && (i & 0x20000000)); +} + +static void cg6_fill(struct fb_info_sbusfb *fb, struct display *p, int s, + int count, unsigned short *boxes) +{ + int i; + register struct cg6_fbc *fbc = fb->s.cg6.fbc; + + do { + i = fbc->s; + } while (i & 0x10000000); + fbc->fg = attr_bgcol(p,s); + fbc->bg = attr_bgcol(p,s); + fbc->pixelm = ~(0); + fbc->alu = 0xea80ff00; + fbc->s = 0; + fbc->clip = 0; + fbc->pm = ~(0); + while (count-- > 0) { + fbc->arecty = boxes[1]; + fbc->arectx = boxes[0]; + fbc->arecty = boxes[3]; + fbc->arectx = boxes[2]; + boxes += 4; + do { + i = fbc->draw; + } while (i < 0 && (i & 0x20000000)); + } +} + +static void cg6_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) +{ + struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; + register struct cg6_fbc *fbc = fb->s.cg6.fbc; + int i, x, y; + u8 *fd; + + if (p->fontheightlog) { + y = fb->y_margin + (yy << p->fontheightlog); + i = ((c & p->charmask) << p->fontheightlog); + } else { + y = fb->y_margin + (yy * p->fontheight); + i = (c & p->charmask) * p->fontheight; + } +#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY + fd = p->fontdata + i; + x = fb->x_margin + xx * 8; +#else + if (p->fontwidth <= 8) + fd = p->fontdata + i; + else + fd = p->fontdata + (i << 1); + if (p->fontwidthlog) + x = fb->x_margin + (xx << p->fontwidthlog); + else + x = fb->x_margin + (xx * p->fontwidth); +#endif + do { + i = fbc->s; + } while (i & 0x10000000); + fbc->fg = attr_fgcol(p,c); + fbc->bg = attr_bgcol(p,c); + fbc->mode = 0x140000; + fbc->alu = 0xe880fc30; + fbc->pixelm = ~(0); + fbc->s = 0; + fbc->clip = 0; + fbc->pm = 0xff; + fbc->incx = 0; + fbc->incy = 1; + fbc->x0 = x; + fbc->x1 = x + p->fontwidth - 1; + fbc->y0 = y; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth <= 8) { +#endif + for (i = 0; i < p->fontheight; i++) + fbc->font = *fd++ << 24; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + } else { + for (i = 0; i < p->fontheight; i++) { + fbc->font = *(u16 *)fd << 16; + fd += 2; + } + } +#endif +} + +static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, + int count, int yy, int xx) +{ + struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; + register struct cg6_fbc *fbc = fb->s.cg6.fbc; + int i, x, y; + u8 *fd1, *fd2, *fd3, *fd4; + + do { + i = fbc->s; + } while (i & 0x10000000); + fbc->fg = attr_fgcol(p,*s); + fbc->bg = attr_bgcol(p,*s); + fbc->mode = 0x140000; + fbc->alu = 0xe880fc30; + fbc->pixelm = ~(0); + fbc->s = 0; + fbc->clip = 0; + fbc->pm = 0xff; + x = fb->x_margin; + y = fb->y_margin; +#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY + x += xx * 8; +#else + if (p->fontwidthlog) + x += (xx << p->fontwidthlog); + else + x += xx * p->fontwidth; +#endif + if (p->fontheightlog) + y += (yy << p->fontheightlog); + else + y += (yy * p->fontheight); +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth <= 8) { +#endif + while (count >= 4) { + count -= 4; + fbc->incx = 0; + fbc->incy = 1; + fbc->x0 = x; + fbc->x1 = (x += 4 * p->fontwidth) - 1; + fbc->y0 = y; + if (p->fontheightlog) { + fd1 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog); + fd2 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog); + fd3 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog); + fd4 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog); + } else { + fd1 = p->fontdata + ((*s++ & p->charmask) * p->fontheight); + fd2 = p->fontdata + ((*s++ & p->charmask) * p->fontheight); + fd3 = p->fontdata + ((*s++ & p->charmask) * p->fontheight); + fd4 = p->fontdata + ((*s++ & p->charmask) * p->fontheight); + } +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth == 8) { +#endif + for (i = 0; i < p->fontheight; i++) + fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) + << 8)) << 8)) << 8); +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + } else { + for (i = 0; i < p->fontheight; i++) + fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) + << p->fontwidth)) << p->fontwidth)) << p->fontwidth)) << (24 - 3 * p->fontwidth); + } + } + } else { + while (count >= 2) { + count -= 2; + fbc->incx = 0; + fbc->incy = 1; + fbc->x0 = x; + fbc->x1 = (x += 2 * p->fontwidth) - 1; + fbc->y0 = y; + if (p->fontheightlog) { + fd1 = p->fontdata + ((*s++ & p->charmask) << (p->fontheightlog + 1)); + fd2 = p->fontdata + ((*s++ & p->charmask) << (p->fontheightlog + 1)); + } else { + fd1 = p->fontdata + (((*s++ & p->charmask) * p->fontheight) << 1); + fd2 = p->fontdata + (((*s++ & p->charmask) * p->fontheight) << 1); + } + for (i = 0; i < p->fontheight; i++) { + fbc->font = ((((u32)*(u16 *)fd1) << p->fontwidth) | ((u32)*(u16 *)fd2)) << (16 - p->fontwidth); + fd1 += 2; fd2 += 2; + } + } +#endif + } + while (count) { + count--; + fbc->incx = 0; + fbc->incy = 1; + fbc->x0 = x; + fbc->x1 = (x += p->fontwidth) - 1; + fbc->y0 = y; + if (p->fontheightlog) + i = ((*s++ & p->charmask) << p->fontheightlog); + else + i = ((*s++ & p->charmask) * p->fontheight); +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth <= 8) { +#endif + fd1 = p->fontdata + i; + for (i = 0; i < p->fontheight; i++) + fbc->font = *fd1++ << 24; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + } else { + fd1 = p->fontdata + (i << 1); + for (i = 0; i < p->fontheight; i++) { + fbc->font = *(u16 *)fd1 << 16; + fd1 += 2; + } + } +#endif + } +} + +static void cg6_revc(struct display *p, int xx, int yy) +{ + /* Not used if hw cursor */ +} + +static void cg6_loadcmap (struct fb_info_sbusfb *fb, int index, int count) +{ + struct bt_regs *bt = fb->s.cg6.bt; + int i; + + bt->addr = index << 24; + for (i = index; count--; i++){ + bt->color_map = fb->color_map CM(i,0) << 24; + bt->color_map = fb->color_map CM(i,1) << 24; + bt->color_map = fb->color_map CM(i,2) << 24; + } +} + +static void cg6_restore_palette (struct fb_info_sbusfb *fb) +{ + struct bt_regs *bt = fb->s.cg6.bt; + + bt->addr = 0; + bt->color_map = 0xffffffff; + bt->color_map = 0xffffffff; + bt->color_map = 0xffffffff; +} + +static struct display_switch cg6_dispsw __initdata = { + cg6_setup, fbcon_redraw_bmove, cg6_clear, cg6_putc, cg6_putcs, cg6_revc, + NULL, NULL, NULL, FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */ +}; + +static void cg6_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) +{ + struct bt_regs *bt = fb->s.cg6.bt; + + bt->addr = 1 << 24; + bt->cursor = red[0] << 24; + bt->cursor = green[0] << 24; + bt->cursor = blue[0] << 24; + bt->addr = 3 << 24; + bt->cursor = red[1] << 24; + bt->cursor = green[1] << 24; + bt->cursor = blue[1] << 24; +} + +/* Set cursor shape */ +static void cg6_setcurshape (struct fb_info_sbusfb *fb) +{ + struct cg6_thc *thc = fb->s.cg6.thc; + int i; + + for (i = 0; i < 32; i++) { + thc->thc_cursmask [i] = fb->cursor.bits[0][i]; + thc->thc_cursbits [i] = fb->cursor.bits[1][i]; + } +} + +/* Load cursor information */ +static void cg6_setcursor (struct fb_info_sbusfb *fb) +{ + unsigned int v; + struct cg_cursor *c = &fb->cursor; + + if (c->enable) + v = ((c->cpos.fbx - c->chot.fbx) << 16) + |((c->cpos.fby - c->chot.fby) & 0xffff); + else + /* Magic constant to turn off the cursor */ + v = ((65536-32) << 16) | (65536-32); + fb->s.cg6.thc->thc_cursxy = v; +} + +static void cg6_blank (struct fb_info_sbusfb *fb) +{ + fb->s.cg6.thc->thc_misc &= ~CG6_THC_MISC_VIDEO; +} + +static void cg6_unblank (struct fb_info_sbusfb *fb) +{ + fb->s.cg6.thc->thc_misc |= CG6_THC_MISC_VIDEO; +} + +static void cg6_reset (struct fb_info_sbusfb *fb) +{ + unsigned int rev, conf; + + /* Turn off stuff in the Transform Engine. */ + fb->s.cg6.tec->tec_matrix = 0; + fb->s.cg6.tec->tec_clip = 0; + fb->s.cg6.tec->tec_vdc = 0; + + /* Take care of bugs in old revisions. */ + rev = (*(fb->s.cg6.fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK; + if (rev < 5) { + conf = (*(fb->s.cg6.fhc) & CG6_FHC_RES_MASK) | + CG6_FHC_CPU_68020 | CG6_FHC_TEST | + (11 << CG6_FHC_TEST_X_SHIFT) | + (11 << CG6_FHC_TEST_Y_SHIFT); + if (rev < 2) + conf |= CG6_FHC_DST_DISABLE; + *(fb->s.cg6.fhc) = conf; + } + + /* Set things in the FBC. */ + fb->s.cg6.fbc->mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK | + CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK | + CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK | + CG6_FBC_BDISP_MASK); + fb->s.cg6.fbc->mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 | + CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE | + CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 | + CG6_FBC_BDISP_0); + fb->s.cg6.fbc->clip = 0; + fb->s.cg6.fbc->offx = 0; + fb->s.cg6.fbc->offy = 0; + fb->s.cg6.fbc->clipminx = 0; + fb->s.cg6.fbc->clipminy = 0; + fb->s.cg6.fbc->clipmaxx = fb->type.fb_width - 1; + fb->s.cg6.fbc->clipmaxy = fb->type.fb_height - 1; + /* Enable cursor in Brooktree DAC. */ + fb->s.cg6.bt->addr = 0x06 << 24; + fb->s.cg6.bt->control |= 0x03 << 24; +} + +static void cg6_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) +{ + p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin); +} + +static char idstring[60] __initdata = { 0 }; + +__initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb)) +{ + struct fb_fix_screeninfo *fix = &fb->fix; + struct fb_var_screeninfo *var = &fb->var; + struct display *disp = &fb->disp; + struct fbtype *type = &fb->type; + unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; + u32 conf; + char *p; + + strcpy(fb->info.modename, "CGsix"); + + strcpy(fix->id, "CGsix"); + fix->line_length = fb->var.xres_virtual; + fix->accel = FB_ACCEL_SUN_CGSIX; + + var->accel_flags = FB_ACCELF_TEXT; + + disp->scrollmode = SCROLL_YREDRAW; + if (!disp->screen_base) + disp->screen_base = (char *)sparc_alloc_io(phys + CG6_RAM_OFFSET, 0, + type->fb_size, "cgsix_ram", fb->iospace, 0); + disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; + fb->s.cg6.fbc = (struct cg6_fbc *)sparc_alloc_io(phys + CG6_FBC_OFFSET, 0, + 4096, "cgsix_fbc", fb->iospace, 0); + fb->s.cg6.tec = (struct cg6_tec *)sparc_alloc_io(phys + CG6_TEC_OFFSET, 0, + sizeof(struct cg6_tec), "cgsix_tec", fb->iospace, 0); + fb->s.cg6.thc = (struct cg6_thc *)sparc_alloc_io(phys + CG6_THC_OFFSET, 0, + sizeof(struct cg6_thc), "cgsix_thc", fb->iospace, 0); + fb->s.cg6.bt = (struct bt_regs *)sparc_alloc_io(phys + CG6_BROOKTREE_OFFSET, 0, + sizeof(struct bt_regs), "cgsix_dac", fb->iospace, 0); + fb->s.cg6.fhc = (u32 *)sparc_alloc_io(phys + CG6_FHC_OFFSET, 0, + sizeof(u32), "cgsix_fhc", fb->iospace, 0); + fb->dispsw = cg6_dispsw; + + fb->margins = cg6_margins; + fb->loadcmap = cg6_loadcmap; + fb->setcursor = cg6_setcursor; + fb->setcursormap = cg6_setcursormap; + fb->setcurshape = cg6_setcurshape; + fb->restore_palette = cg6_restore_palette; + fb->fill = cg6_fill; + fb->blank = cg6_blank; + fb->unblank = cg6_unblank; + fb->reset = cg6_reset; + + fb->physbase = phys; + fb->mmap_map = cg6_mmap_map; + + /* Initialize Brooktree DAC */ + fb->s.cg6.bt->addr = 0x04 << 24; /* color planes */ + fb->s.cg6.bt->control = 0xff << 24; + fb->s.cg6.bt->addr = 0x05 << 24; + fb->s.cg6.bt->control = 0x00 << 24; + fb->s.cg6.bt->addr = 0x06 << 24; /* overlay plane */ + fb->s.cg6.bt->control = 0x73 << 24; + fb->s.cg6.bt->addr = 0x07 << 24; + fb->s.cg6.bt->control = 0x00 << 24; + + conf = *fb->s.cg6.fhc; + switch(conf & CG6_FHC_CPU_MASK) { + case CG6_FHC_CPU_SPARC: p = "sparc"; break; + case CG6_FHC_CPU_68020: p = "68020"; break; + default: p = "i386"; break; + } + + sprintf(idstring, +#ifdef __sparc_v9__ + "cgsix at %016lx TEC Rev %x CPU %s Rev %x", phys, +#else + "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x", fb->iospace, phys, +#endif + (fb->s.cg6.thc->thc_misc >> CG6_THC_MISC_REV_SHIFT) & CG6_THC_MISC_REV_MASK, + p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK); + + cg6_reset(fb); + + return idstring; +} diff --git a/drivers/video/cgthreefb.c b/drivers/video/cgthreefb.c new file mode 100644 index 000000000..2cab0fc25 --- /dev/null +++ b/drivers/video/cgthreefb.c @@ -0,0 +1,247 @@ +/* $Id: cgthreefb.c,v 1.1 1998/07/21 14:50:47 jj Exp $ + * cgthreefb.c: CGthree frame buffer driver + * + * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) + * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) + * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) + */ + +#include <linux/module.h> +#include <linux/sched.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 <linux/selection.h> + +#include "sbusfb.h" +#include <asm/io.h> + +#include "fbcon-cfb8.h" + +/* Control Register Constants */ +#define CG3_CR_ENABLE_INTS 0x80 +#define CG3_CR_ENABLE_VIDEO 0x40 +#define CG3_CR_ENABLE_TIMING 0x20 +#define CG3_CR_ENABLE_CURCMP 0x10 +#define CG3_CR_XTAL_MASK 0x0c +#define CG3_CR_DIVISOR_MASK 0x03 + +/* Status Register Constants */ +#define CG3_SR_PENDING_INT 0x80 +#define CG3_SR_RES_MASK 0x70 +#define CG3_SR_1152_900_76_A 0x40 +#define CG3_SR_1152_900_76_B 0x60 +#define CG3_SR_ID_MASK 0x0f +#define CG3_SR_ID_COLOR 0x01 +#define CG3_SR_ID_MONO 0x02 +#define CG3_SR_ID_MONO_ECL 0x03 + +enum cg3_type { + CG3_AT_66HZ = 0, + CG3_AT_76HZ, + CG3_RDI +}; + +struct cg3_regs { + struct bt_regs cmap; + volatile u8 control; + volatile u8 status; + volatile u8 cursor_start; + volatile u8 cursor_end; + volatile u8 h_blank_start; + volatile u8 h_blank_end; + volatile u8 h_sync_start; + volatile u8 h_sync_end; + volatile u8 comp_sync_end; + volatile u8 v_blank_start_high; + volatile u8 v_blank_start_low; + volatile u8 v_blank_end; + volatile u8 v_sync_start; + volatile u8 v_sync_end; + volatile u8 xfer_holdoff_start; + volatile u8 xfer_holdoff_end; +}; + +/* Offset of interesting structures in the OBIO space */ +#define CG3_REGS_OFFSET 0x400000 +#define CG3_RAM_OFFSET 0x800000 + +static struct sbus_mmap_map cg3_mmap_map[] = { + { CG3_MMAP_OFFSET, CG3_RAM_OFFSET, SBUS_MMAP_FBSIZE(1) }, + { 0, 0, 0 } +}; + +/* The cg3 palette is loaded with 4 color values at each time */ +/* so you end up with: (rgb)(r), (gb)(rg), (b)(rgb), and so on */ + +#define D4M3(x) ((((x)>>2)<<1) + ((x)>>2)) /* (x/4)*3 */ +#define D4M4(x) ((x)&~0x3) /* (x/4)*4 */ + +static void cg3_loadcmap (struct fb_info_sbusfb *fb, int index, int count) +{ + struct bt_regs *bt = &fb->s.cg3.regs->cmap; + u32 *i; + int steps; + + i = (((u32 *)fb->color_map) + D4M3(index)); + steps = D4M3(index+count-1) - D4M3(index)+3; + + *(volatile u8 *)&bt->addr = (u8)D4M4(index); + while (steps--) + bt->color_map = *i++; +} + +static void cg3_blank (struct fb_info_sbusfb *fb) +{ + fb->s.cg3.regs->control &= ~CG3_CR_ENABLE_VIDEO; +} + +static void cg3_unblank (struct fb_info_sbusfb *fb) +{ + fb->s.cg3.regs->control |= CG3_CR_ENABLE_VIDEO; +} + +static void cg3_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) +{ + p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin); +} + +static u8 cg3regvals_66hz[] __initdata = { /* 1152 x 900, 66 Hz */ + 0x14, 0xbb, 0x15, 0x2b, 0x16, 0x04, 0x17, 0x14, + 0x18, 0xae, 0x19, 0x03, 0x1a, 0xa8, 0x1b, 0x24, + 0x1c, 0x01, 0x1d, 0x05, 0x1e, 0xff, 0x1f, 0x01, + 0x10, 0x20, 0 +}; + +static u8 cg3regvals_76hz[] __initdata = { /* 1152 x 900, 76 Hz */ + 0x14, 0xb7, 0x15, 0x27, 0x16, 0x03, 0x17, 0x0f, + 0x18, 0xae, 0x19, 0x03, 0x1a, 0xae, 0x1b, 0x2a, + 0x1c, 0x01, 0x1d, 0x09, 0x1e, 0xff, 0x1f, 0x01, + 0x10, 0x24, 0 +}; + +static u8 cg3regvals_rdi[] __initdata = { /* 640 x 480, cgRDI */ + 0x14, 0x70, 0x15, 0x20, 0x16, 0x08, 0x17, 0x10, + 0x18, 0x06, 0x19, 0x02, 0x1a, 0x31, 0x1b, 0x51, + 0x1c, 0x06, 0x1d, 0x0c, 0x1e, 0xff, 0x1f, 0x01, + 0x10, 0x22, 0 +}; + +static u8 *cg3_regvals[] __initdata = { + cg3regvals_66hz, cg3regvals_76hz, cg3regvals_rdi +}; + +static u_char cg3_dacvals[] __initdata = { + 4, 0xff, 5, 0x00, 6, 0x70, 7, 0x00, 0 +}; + +static char idstring[60] __initdata = { 0 }; + +__initfunc(char *cgthreefb_init(struct fb_info_sbusfb *fb)) +{ + struct fb_fix_screeninfo *fix = &fb->fix; + struct display *disp = &fb->disp; + struct fbtype *type = &fb->type; + unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; + int cgRDI = strstr(fb->sbdp->prom_name, "cgRDI") != NULL; + +#ifndef FBCON_HAS_CFB8 + return NULL; +#endif + + if (!fb->s.cg3.regs) { + fb->s.cg3.regs = (struct cg3_regs *)sparc_alloc_io(phys+CG3_REGS_OFFSET, 0, + sizeof(struct cg3_regs), "cg3_regs", fb->iospace, 0); + if (cgRDI) { + char buffer[40]; + char *p; + int ww, hh; + + *buffer = 0; + prom_getstring (fb->prom_node, "params", buffer, sizeof(buffer)); + if (*buffer) { + ww = simple_strtoul (buffer, &p, 10); + if (ww && *p == 'x') { + hh = simple_strtoul (p + 1, &p, 10); + if (hh && *p == '-') { + if (type->fb_width != ww || type->fb_height != hh) { + type->fb_width = ww; + type->fb_height = hh; + return SBUSFBINIT_SIZECHANGE; + } + } + } + } + } + } + + strcpy(fb->info.modename, "CGthree"); + strcpy(fix->id, "CGthree"); + fix->line_length = fb->var.xres_virtual; + + disp->scrollmode = SCROLL_YREDRAW; + if (!disp->screen_base) + disp->screen_base = (char *)sparc_alloc_io(phys+CG3_RAM_OFFSET, 0, + type->fb_size, "cg3_ram", fb->iospace, 0); + disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; + fb->dispsw = fbcon_cfb8; + + fb->margins = cg3_margins; + fb->loadcmap = cg3_loadcmap; + fb->blank = cg3_blank; + fb->unblank = cg3_unblank; + + fb->physbase = phys; + fb->mmap_map = cg3_mmap_map; + +#ifdef __sparc_v9__ + sprintf(idstring, "%s at %016lx", cgRDI ? "cgRDI" : "cgthree", phys); +#else + sprintf(idstring, "%s at %x.%08lx", cgRDI ? "cgRDI" : "cgthree", fb->iospace, phys); +#endif + + if (!prom_getbool(fb->prom_node, "width")) { + /* Ugh, broken PROM didn't initialize us. + * Let's deal with this ourselves. + */ + enum cg3_type type; + u8 *p; + + if (cgRDI) + type = CG3_RDI; + else { + u8 status = fb->s.cg3.regs->status, mon; + if ((status & CG3_SR_ID_MASK) == CG3_SR_ID_COLOR) { + mon = status & CG3_SR_RES_MASK; + if (mon == CG3_SR_1152_900_76_A || + mon == CG3_SR_1152_900_76_B) + type = CG3_AT_76HZ; + else + type = CG3_AT_66HZ; + } else { + prom_printf("cgthree: can't handle SR %02x\n", + status); + prom_halt(); + return NULL; /* fool gcc. */ + } + } + + for (p = cg3_regvals[type]; *p; p += 2) + ((u8 *)fb->s.cg3.regs)[p[0]] = p[1]; + + for (p = cg3_dacvals; *p; p += 2) { + *(volatile u8 *)&fb->s.cg3.regs->cmap.addr = p[0]; + *(volatile u8 *)&fb->s.cg3.regs->cmap.control = p[1]; + } + } + + return idstring; +} diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c new file mode 100644 index 000000000..c13954030 --- /dev/null +++ b/drivers/video/chipsfb.c @@ -0,0 +1,565 @@ +/* + * drivers/video/chipsfb.c -- frame buffer device for + * Chips & Technologies 65550 chip. + * + * Copyright (C) 1998 Paul Mackerras + * + * This file is derived from the Powermac "chips" driver: + * Copyright (C) 1997 Fabio Riccardi. + * And from the frame buffer device for Open Firmware-initialized devices: + * 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. + */ + +#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> +#ifdef CONFIG_FB_COMPAT_XPMAC +#include <asm/vc_ioctl.h> +#endif +#include <asm/io.h> +#include <asm/prom.h> +#include <asm/pci-bridge.h> +#include <asm/adb.h> +#include <asm/pmu.h> + +#include "fbcon.h" +#include "fbcon-cfb8.h" +#include "fbcon-cfb16.h" +#include "macmodes.h" + +static int currcon = 0; + +struct fb_info_chips { + struct fb_info info; + struct fb_fix_screeninfo fix; + struct fb_var_screeninfo var; + struct display disp; + struct { + __u8 red, green, blue; + } palette[256]; + __u8 *frame_buffer; + __u8 *blitter_regs; + __u8 *io_base; + unsigned long chips_base_phys; + unsigned long chips_io_phys; + struct fb_info_chips *next; +#ifdef CONFIG_PMAC_PBOOK + unsigned char *save_framebuffer; +#endif +}; + +#define write_xr(num,val) { out_8(p->io_base + 0x3D6, num); out_8(p->io_base + 0x3D7, val); } +#define read_xr(num,var) { out_8(p->io_base + 0x3D6, num); var = in_8(p->io_base + 0x3D7); } +#define write_fr(num,val) { out_8(p->io_base + 0x3D0, num); out_8(p->io_base + 0x3D1, val); } +#define read_fr(num,var) { out_8(p->io_base + 0x3D0, num); var = in_8(p->io_base + 0x3D1); } +#define write_cr(num,val) { out_8(p->io_base + 0x3D4, num); out_8(p->io_base + 0x3D5, val); } +#define read_cr(num,var) { out_8(p->io_base + 0x3D4, num); var = in_8(p->io_base + 0x3D5); } + + +static struct fb_info_chips *all_chips; + +#ifdef CONFIG_PMAC_PBOOK +int chips_sleep_notify(struct notifier_block *, unsigned long, void *); +static struct notifier_block chips_sleep_notifier = { + chips_sleep_notify, NULL, 0 +}; +#endif + +/* + * Exported functions + */ +void chips_init(void); +void chips_of_init(struct device_node *dp); + +static int chips_open(struct fb_info *info, int user); +static int chips_release(struct fb_info *info, int user); +static int chips_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int chips_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int chips_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int chips_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int chips_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int chips_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int chips_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info); + +static struct fb_ops chipsfb_ops = { + chips_open, + chips_release, + chips_get_fix, + chips_get_var, + chips_set_var, + chips_get_cmap, + chips_set_cmap, + chips_pan_display, + chips_ioctl +}; + +static int chipsfb_getcolreg(u_int regno, u_int *red, u_int *green, + u_int *blue, u_int *transp, struct fb_info *info); +static int chipsfb_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 void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, int con, int bpp); + + +static int chips_open(struct fb_info *info, int user) +{ + MOD_INC_USE_COUNT; + return 0; +} + +static int chips_release(struct fb_info *info, int user) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +static int chips_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + struct fb_info_chips *cp = (struct fb_info_chips *) info; + + *fix = cp->fix; + return 0; +} + +static int chips_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct fb_info_chips *cp = (struct fb_info_chips *) info; + + *var = cp->var; + return 0; +} + +static int chips_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct fb_info_chips *cp = (struct fb_info_chips *) info; + struct display *disp = (con >= 0)? &fb_display[con]: &cp->disp; + + if (var->xres > 800 || var->yres > 600 + || var->xres_virtual > 800 || var->yres_virtual > 600 + || (var->bits_per_pixel != 8 && var->bits_per_pixel != 16) + || var->nonstd + || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) + return -EINVAL; + + if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && + var->bits_per_pixel != disp->var.bits_per_pixel) { + chips_set_bitdepth(cp, disp, con, var->bits_per_pixel); + } + + return 0; +} + +static int chips_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + if (var->xoffset != 0 || var->yoffset != 0) + return -EINVAL; + return 0; +} + +static int chips_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, + chipsfb_getcolreg, info); + 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(256), cmap, kspc? 0: 2); + return 0; +} + +static int chips_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + struct display *disp = &fb_display[con]; + int err; + + if (disp->cmap.len == 0) { + err = fb_alloc_cmap(&disp->cmap, 256, 0); + if (err) + return err; + } + + if (con == currcon) + return fb_set_cmap(cmap, &disp->var, kspc, chipsfb_setcolreg, + info); + fb_copy_cmap(cmap, &disp->cmap, kspc==0); + return 0; +} + +static int chips_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info) +{ + return -EINVAL; +} + +static int chipsfb_switch(int con, struct fb_info *info) +{ + struct fb_info_chips *p = (struct fb_info_chips *) info; + struct display* old_disp = &fb_display[currcon]; + struct display* new_disp = &fb_display[con]; + int bit_depth; + + if (fb_display[currcon].cmap.len) + fb_get_cmap(&old_disp->cmap, + &old_disp->var, 1, chipsfb_getcolreg, + info); + + bit_depth = new_disp->var.bits_per_pixel; + if (old_disp->var.bits_per_pixel != bit_depth) + { + currcon = con; + chips_set_bitdepth(p, new_disp, con, bit_depth); + } + else + currcon = con; + + do_install_cmap(con, info); + return 0; +} + +static int chipsfb_updatevar(int con, struct fb_info *info) +{ + return 0; +} + +static void chipsfb_blank(int blank, struct fb_info *info) +{ + struct fb_info_chips *p = (struct fb_info_chips *) info; + int i; + + if (blank > 1) { + pmu_enable_backlight(0); + } else if (blank) { + for (i = 0; i < 256; ++i) { + out_8(p->io_base + 0x3c8, i); + udelay(1); + out_8(p->io_base + 0x3c9, 0); + out_8(p->io_base + 0x3c9, 0); + out_8(p->io_base + 0x3c9, 0); + } + } else { + pmu_enable_backlight(1); + do_install_cmap(currcon, info); + } +} + +static int chipsfb_getcolreg(u_int regno, u_int *red, u_int *green, + u_int *blue, u_int *transp, struct fb_info *info) +{ + struct fb_info_chips *p = (struct fb_info_chips *) info; + + if (regno > 255) + return 1; + *red = p->palette[regno].red; + *green = p->palette[regno].green; + *blue = p->palette[regno].blue; + return 0; +} + +static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + struct fb_info_chips *p = (struct fb_info_chips *) info; + + if (regno > 255) + return 1; + p->palette[regno].red = red; + p->palette[regno].green = green; + p->palette[regno].blue = blue; + out_8(p->io_base + 0x3c8, regno); + udelay(1); + out_8(p->io_base + 0x3c9, red); + out_8(p->io_base + 0x3c9, green); + out_8(p->io_base + 0x3c9, blue); + +#ifdef FBCON_HAS_CFB16 + if (regno < 16) + fbcon_cfb16_cmap[regno] = (red << 10) | (green << 5) | blue; +#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, + chipsfb_setcolreg, info); + else + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), &fb_display[con].var, 1, + chipsfb_setcolreg, info); +} + +#ifdef CONFIG_FB_COMPAT_XPMAC +/* from drivers/macintosh/pmac-cons.h */ +#define VMODE_800_600_60 10 /* 800x600, 60Hz */ +#endif /* CONFIG_FB_COMPAT_XPMAC */ + +static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, int con, int bpp) +{ + int err; + struct fb_fix_screeninfo* fix = &p->fix; + struct fb_var_screeninfo* var = &p->var; + + if (bpp == 16) { + if (con == currcon) { + write_cr(0x13, 200); // 16 bit display width (decimal) + write_xr(0x81, 0x14); // 15 bit (TrueColor) color mode + write_xr(0x82, 0x00); // disable palettes + write_xr(0x20, 0x10); // 16 bit blitter mode + } + + fix->line_length = 800*2; + fix->visual = FB_VISUAL_TRUECOLOR; + + var->red.offset = 10; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = var->green.length = var->blue.length = 5; + +#ifdef FBCON_HAS_CFB16 + disp->dispsw = &fbcon_cfb16; +#else + disp->dispsw = NULL; +#endif + } else if (bpp == 8) { + if (con == currcon) { + write_cr(0x13, 100); // 8 bit display width (decimal) + write_xr(0x81, 0x12); // 8 bit color mode + write_xr(0x82, 0x08); // Graphics gamma enable + write_xr(0x20, 0x00); // 8 bit blitter mode + } + + fix->line_length = 800; + fix->visual = FB_VISUAL_PSEUDOCOLOR; + + var->red.offset = var->green.offset = var->blue.offset = 0; + var->red.length = var->green.length = var->blue.length = 8; + +#ifdef FBCON_HAS_CFB8 + disp->dispsw = &fbcon_cfb8; +#else + disp->dispsw = NULL; +#endif + } + + var->bits_per_pixel = bpp; + disp->line_length = p->fix.line_length; + disp->visual = fix->visual; + disp->var = *var; + +#ifdef CONFIG_PMAC_PBOOK + display_info.depth = bpp; + display_info.pitch = fix->line_length; +#endif + + if (p->info.changevar) + (*p->info.changevar)(con); + + if ((err = fb_alloc_cmap(&disp->cmap, 0, 0))) + return; + do_install_cmap(con, (struct fb_info *)p); +} + +__initfunc(static void init_chips(struct fb_info_chips *p)) +{ + int i; + + memset(&p->fix, 0, sizeof(p->fix)); + strcpy(p->fix.id, "C&T 65550"); + p->fix.smem_start = (char *) p->chips_base_phys; + p->fix.smem_len = 800 * 600; + p->fix.mmio_start = (char *) p->chips_io_phys; + p->fix.type = FB_TYPE_PACKED_PIXELS; + p->fix.visual = FB_VISUAL_PSEUDOCOLOR; + p->fix.line_length = 800; + + memset(&p->var, 0, sizeof(p->var)); + p->var.xres = 800; + p->var.yres = 600; + p->var.xres_virtual = 800; + p->var.yres_virtual = 600; + p->var.bits_per_pixel = 8; + p->var.red.length = p->var.green.length = p->var.blue.length = 8; + p->var.height = p->var.width = -1; + p->var.vmode = FB_VMODE_NONINTERLACED; + p->var.pixclock = 10000; + p->var.left_margin = p->var.right_margin = 16; + p->var.upper_margin = p->var.lower_margin = 16; + p->var.hsync_len = p->var.vsync_len = 8; + + memset(&p->disp, 0, sizeof(p->disp)); + p->disp.var = p->var; + p->disp.cmap.red = NULL; + p->disp.cmap.green = NULL; + p->disp.cmap.blue = NULL; + p->disp.cmap.transp = NULL; + p->disp.screen_base = (char *) p->frame_buffer; + p->disp.visual = p->fix.visual; + p->disp.type = p->fix.type; + p->disp.type_aux = p->fix.type_aux; + p->disp.line_length = p->fix.line_length; + p->disp.can_soft_blank = 1; + p->disp.dispsw = &fbcon_cfb8; + p->disp.scrollmode = SCROLL_YREDRAW; + + strcpy(p->info.modename, p->fix.id); + p->info.node = -1; + p->info.fbops = &chipsfb_ops; + p->info.disp = &p->disp; + p->info.fontname[0] = 0; + p->info.changevar = NULL; + p->info.switch_con = &chipsfb_switch; + p->info.updatevar = &chipsfb_updatevar; + p->info.blank = &chipsfb_blank; + + for (i = 0; i < 16; ++i) { + int j = color_table[i]; + p->palette[i].red = default_red[j]; + p->palette[i].green = default_grn[j]; + p->palette[i].blue = default_blu[j]; + } + + if (register_framebuffer(&p->info) < 0) { + kfree(p); + return; + } + + printk("fb%d: Chips 65550 frame buffer\n", GET_FB_IDX(p->info.node)); + +#ifdef CONFIG_FB_COMPAT_XPMAC + if (!console_fb_info) { + display_info.height = p->var.yres; + display_info.width = p->var.xres; + display_info.depth = 8; + display_info.pitch = p->fix.line_length; + display_info.mode = VMODE_800_600_60; + strncpy(display_info.name, "chips65550", + sizeof(display_info.name)); + display_info.fb_address = p->chips_base_phys + 0x800000; + display_info.cmap_adr_address = p->chips_io_phys + 0x3c8; + display_info.cmap_data_address = p->chips_io_phys + 0x3c9; + display_info.disp_reg_address = p->chips_base_phys + 0xc00000; + console_fb_info = &p->info; + } +#endif /* CONFIG_FB_COMPAT_XPMAC */ + +#ifdef CONFIG_PMAC_PBOOK + if (all_chips == NULL) + notifier_chain_register(&sleep_notifier_list, + &chips_sleep_notifier); +#endif /* CONFIG_PMAC_PBOOK */ + p->next = all_chips; + all_chips = p; +} + +__initfunc(void chips_init(void)) +{ +#ifndef CONFIG_FB_OF + struct device_node *dp; + + dp = find_devices("chips65550"); + if (dp != 0) + chips_of_init(dp); +#endif /* CONFIG_FB_OF */ +} + +__initfunc(void chips_of_init(struct device_node *dp)) +{ + struct fb_info_chips *p; + unsigned long addr; + unsigned char bus, devfn; + unsigned short cmd; + + if (dp->n_addrs == 0) + return; + p = kmalloc(sizeof(*p), GFP_ATOMIC); + if (p == 0) + return; + addr = dp->addrs[0].address; + p->chips_base_phys = addr; + p->frame_buffer = __ioremap(addr+0x800000, 0x100000, _PAGE_NO_CACHE); + p->blitter_regs = ioremap(addr + 0xC00000, 0x1000); + + if (pci_device_loc(dp, &bus, &devfn) == 0) { + pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd); + cmd |= 3; /* enable memory and IO space */ + pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd); + p->io_base = (unsigned char *) pci_io_base(bus); + /* XXX really want the physical address here */ + p->chips_io_phys = (unsigned long) pci_io_base(bus); + } + + /* Clear the entire framebuffer */ + memset(p->frame_buffer, 0, 0x100000); + + /* turn on the backlight */ + pmu_enable_backlight(1); + + init_chips(p); +} + +#ifdef CONFIG_PMAC_PBOOK +/* + * Save the contents of the frame buffer when we go to sleep, + * and restore it when we wake up again. + */ +int +chips_sleep_notify(struct notifier_block *this, unsigned long code, void *x) +{ + struct fb_info_chips *p; + + for (p = all_chips; p != NULL; p = p->next) { + int nb = p->var.yres * p->fix.line_length; + + switch (code) { + case PBOOK_SLEEP: + p->save_framebuffer = vmalloc(nb); + if (p->save_framebuffer) + memcpy(p->save_framebuffer, + p->frame_buffer, nb); + break; + case PBOOK_WAKE: + if (p->save_framebuffer) { + memcpy(p->frame_buffer, + p->save_framebuffer, nb); + vfree(p->save_framebuffer); + p->save_framebuffer = 0; + } + break; + } + } + return NOTIFY_DONE; +} +#endif /* CONFIG_PMAC_PBOOK */ diff --git a/drivers/video/clgenfb.c b/drivers/video/clgenfb.c new file mode 100644 index 000000000..fc3f15efe --- /dev/null +++ b/drivers/video/clgenfb.c @@ -0,0 +1,2121 @@ +/* + * Based on retz3fb.c and clgen.c + */ + +#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 <linux/zorro.h> +#include <linux/init.h> +#include <asm/amigahw.h> +#include <asm/pgtable.h> +#include <asm/delay.h> +#include "fbcon.h" + +#include "fbcon.h" +#include "fbcon-mfb.h" +#include "fbcon-cfb8.h" +#include "fbcon-cfb16.h" +#include "fbcon-cfb24.h" +#include "fbcon-cfb32.h" + +#include "clgenfb.h" + +#define CLGEN_VERSION "1.4 ?" +/* #define DEBUG if(1) */ +#define DEBUG if(0) + +#define arraysize(x) (sizeof(x)/sizeof(*(x))) + +/* zorro IDs */ +#define ZORRO_PROD_HELFRICH_SD64_RAM 0x08930A00 +#define ZORRO_PROD_HELFRICH_SD64_REG 0x08930B00 +#define ZORRO_PROD_HELFRICH_PICCOLO_RAM 0x08930500 +#define ZORRO_PROD_HELFRICH_PICCOLO_REG 0x08930600 +#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM 0x08770B00 +#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG 0x08770C00 +#define ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM 0x08910200 +#define ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG 0x08910100 +#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3 0x08771800 + +/* board types */ +#define BT_NONE 0 +#define BT_SD64 1 +#define BT_PICCOLO 2 +#define BT_PICASSO 3 +#define BT_SPECTRUM 4 +#define BT_PICASSO4 5 + +#define MAX_NUM_BOARDS 7 + +#define TRUE 1 +#define FALSE 0 + +struct clgenfb_par +{ + struct fb_var_screeninfo var; + + __u32 line_length; /* in BYTES! */ + __u32 visual; + __u32 type; + + long freq; + long nom; + long den; + long div; + + long HorizRes; /* The x resolution in pixel */ + long HorizTotal; + long HorizDispEnd; + long HorizBlankStart; + long HorizBlankEnd; + long HorizSyncStart; + long HorizSyncEnd; + + long VertRes; /* the physical y resolution in scanlines */ + long VertTotal; + long VertDispEnd; + long VertSyncStart; + long VertSyncEnd; + long VertBlankStart; + long VertBlankEnd; +}; + +/* info about board */ +struct clgenfb_info +{ + struct fb_info_gen gen; + + int keyRAM; /* RAM, REG zorro board keys */ + int keyREG; + unsigned long fbmem; + volatile unsigned char *regs; + unsigned long mem; + unsigned long size; + int btype; + int smallboard; + unsigned char SFR; /* Shadow of special function register */ + + struct clgenfb_par currentmode; +}; + +static struct display disp; + +static struct clgenfb_info boards[MAX_NUM_BOARDS]; /* the boards */ +static struct clgenfb_info *fb_info=NULL; /* pointer to current board */ + +/* + * Predefined Video Modes + */ + +static struct fb_videomode clgenfb_predefined[] __initdata = +{ + { "Autodetect", /* autodetect mode */ + { 0 } + }, + + { "640x480", /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */ + { + 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, 40000, 32, 32, 33, 10, 96, 2, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, + + /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */ + /* + Modeline from XF86Config: + Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805 + */ + { + "1024x768", + { + 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, 12500, 92, 112, 31, 2, 204, 4, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + } +}; + +#define NUM_TOTAL_MODES arraysize(clgenfb_predefined) +static struct fb_var_screeninfo clgenfb_default; + +/* + * Frame Buffer Name + */ + +static char clgenfb_name[16] = "CLgen"; + +/****************************************************************************/ +/**** BEGIN PROTOTYPES ******************************************************/ + +/*--- Interface used by the world ------------------------------------------*/ +void clgenfb_init(void); +void clgenfb_setup(char *options, int *ints); +int clgenfb_open(struct fb_info *info, int user); +int clgenfb_release(struct fb_info *info, int user); +int clgenfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info); + +/* function table of the above functions */ +static struct fb_ops clgenfb_ops = +{ + clgenfb_open, + clgenfb_release, + fbgen_get_fix, /* using the generic functions */ + fbgen_get_var, /* makes things much easier... */ + fbgen_set_var, + fbgen_get_cmap, + fbgen_set_cmap, + fbgen_pan_display, + clgenfb_ioctl, + NULL +}; + +/*--- Hardware Specific Routines -------------------------------------------*/ +static void clgen_detect(void); +static int clgen_encode_fix(struct fb_fix_screeninfo *fix, const void *par, + struct fb_info_gen *info); +static int clgen_decode_var(const struct fb_var_screeninfo *var, void *par, + struct fb_info_gen *info); +static int clgen_encode_var(struct fb_var_screeninfo *var, const void *par, + struct fb_info_gen *info); +static void clgen_get_par(void *par, struct fb_info_gen *info); +static void clgen_set_par(const void *par, struct fb_info_gen *info); +static int clgen_getcolreg(unsigned regno, unsigned *red, unsigned *green, + unsigned *blue, unsigned *transp, + struct fb_info *info); +static int clgen_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info); +static int clgen_pan_display(const struct fb_var_screeninfo *var, + struct fb_info_gen *info); +static int clgen_blank(int blank_mode, struct fb_info_gen *info); + +static struct display_switch *clgen_get_dispsw(const void *par, + struct fb_info_gen *info); + +/* function table of the above functions */ +static struct fbgen_hwswitch clgen_hwswitch = +{ + clgen_detect, + clgen_encode_fix, + clgen_decode_var, + clgen_encode_var, + clgen_get_par, + clgen_set_par, + clgen_getcolreg, + clgen_setcolreg, + clgen_pan_display, + clgen_blank, + clgen_get_dispsw +}; + +/* Text console acceleration */ + +#ifdef FBCON_HAS_CFB8 +static void fbcon_clgen8_bmove(struct display *p, int sy, int sx, + int dy, int dx, int height, int width); +static void fbcon_clgen8_clear(struct vc_data *conp, struct display *p, + int sy, int sx, int height, int width); + +static struct display_switch fbcon_clgen_8 = { + fbcon_cfb8_setup, + fbcon_clgen8_bmove, + fbcon_clgen8_clear, + fbcon_cfb8_putc, + fbcon_cfb8_putcs, + fbcon_cfb8_revc, + NULL, + NULL, + fbcon_cfb8_clear_margins, + FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) +}; +#endif + + + +/*--- Internal routines ----------------------------------------------------*/ +static void init_vgachip(void); +static void switch_monitor(int on); + +static void WGen( int regnum, unsigned char val ); +static unsigned char RGen( int regnum ); +static void WSeq( unsigned char regnum, unsigned char val ); +static unsigned char RSeq( unsigned char regnum ); +static void WCrt( unsigned char regnum, unsigned char val ); +static unsigned char RCrt( unsigned char regnum ); +static void WGfx( unsigned char regnum, unsigned char val ); +static unsigned char RGfx( unsigned char regnum ); +static void WAttr( unsigned char regnum, unsigned char val ); +static void AttrOn( void ); +static unsigned char RAttr( unsigned char regnum ); +static void WHDR( unsigned char val ); +static unsigned char RHDR( void ); +static void WSFR( unsigned char val ); +static void WSFR2( unsigned char val ); +static void WClut( unsigned char regnum, unsigned char red, + unsigned char green, + unsigned char blue ); +static void RClut( unsigned char regnum, unsigned char *red, + unsigned char *green, + unsigned char *blue ); +static void clgen_WaitBLT( void ); +static void clgen_BitBLT (u_short curx, u_short cury, + u_short destx, u_short desty, + u_short width, u_short height, + u_short line_length); +static void clgen_RectFill (u_short x, u_short y, + u_short width, u_short height, + u_char color, u_short line_length); + +static void bestclock(long freq, long *best, + long *nom, long *den, + long *div, long maxfreq); + +/*** END PROTOTYPES ********************************************************/ +/*****************************************************************************/ +/*** BEGIN Interface Used by the World ***************************************/ + +static int opencount = 0; + +/*--- Open /dev/fbx ---------------------------------------------------------*/ +int clgenfb_open(struct fb_info *info, int user) +{ + MOD_INC_USE_COUNT; + if (opencount++ == 0) switch_monitor(1); + return 0; +} + +/*--- Close /dev/fbx --------------------------------------------------------*/ +int clgenfb_release(struct fb_info *info, int user) +{ + if (--opencount == 0) switch_monitor(0); + MOD_DEC_USE_COUNT; + return 0; +} + +/*--- handle /dev/fbx ioctl calls ------------------------------------------*/ +int clgenfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info) +{ + printk(">clgenfb_ioctl()\n"); + /* Nothing exciting here... */ + printk("<clgenfb_ioctl()\n"); + return -EINVAL; +} + +/**** END Interface used by the World *************************************/ +/****************************************************************************/ +/**** BEGIN Hardware specific Routines **************************************/ + +static void clgen_detect(void) +{ + printk(">clgen_detect()\n"); + printk("<clgen_detect()\n"); +} + +static int clgen_encode_fix(struct fb_fix_screeninfo *fix, const void *par, + struct fb_info_gen *info) +{ + struct clgenfb_par *_par = (struct clgenfb_par*) par; + struct clgenfb_info *_info = (struct clgenfb_info*)info; + + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + strcpy(fix->id, clgenfb_name); + + fix->smem_start = (char*)_info->fbmem; + + /* monochrome: only 1 memory plane */ + /* 8 bit and above: Use whole memory area */ + fix->smem_len = _par->var.bits_per_pixel == 1 ? _info->size / 4 + : _info->size; + fix->type = _par->type; + fix->type_aux = 0; + fix->visual = _par->visual; + fix->xpanstep = 1; + fix->ypanstep = 1; + fix->ywrapstep = 0; + fix->line_length = _par->line_length; + fix->mmio_start = (char *)_info->regs; + fix->mmio_len = 0x10000; + fix->accel = FB_ACCEL_NONE; + + return 0; +} + +static int clgen_decode_var(const struct fb_var_screeninfo *var, void *par, + struct fb_info_gen *info) +{ + long freq; + int xres, hfront, hsync, hback; + int yres, vfront, vsync, vback; + int nom,den; /* translyting from pixels->bytes */ + int i; + static struct + { + int xres,yres; + } + modes[] = { {1600,1280}, {1280,1024}, {1024,768}, + {800,600}, {640,480}, {-1,-1} }; + + struct clgenfb_par *_par = (struct clgenfb_par *)par; + + fb_info = (struct clgenfb_info*)info; + printk("clgen_decode_var()\n"); + + printk("Requested: %dx%dx%d\n", var->xres,var->yres,var->bits_per_pixel); + printk(" virtual: %dx%d\n", var->xres_virtual,var->yres_virtual); + printk(" offset: (%d,%d)\n", var->xoffset, var->yoffset); + printk("grayscale: %d\n", var->grayscale); +#if 0 + printk(" activate: 0x%x\n", var->activate); + printk(" pixclock: %d\n", var->pixclock); + printk(" htiming: %d;%d %d\n", var->left_margin,var->right_margin,var->hsync_len); + printk(" vtiming: %d;%d %d\n", var->upper_margin,var->lower_margin,var->vsync_len); + printk(" sync: 0x%x\n", var->sync); + printk(" vmode: 0x%x\n", var->vmode); +#endif + + _par->var = *var; + + switch (var->bits_per_pixel) + { + case 1: nom = 4; den = 8; break; /* 8 pixel per byte, only 1/4th of mem usable */ + case 8: nom = 1; den = 1; break; /* 1 pixel == 1 byte */ + case 16: nom = 2; den = 1; break; /* 2 bytes per pixel */ + case 24: nom = 3; den = 1; break; /* 3 bytes per pixel */ + case 32: nom = 4; den = 1; break; /* 4 bytes per pixel */ + default: + printk("clgen: mode %dx%dx%d rejected...color depth not supported.\n", + var->xres, var->yres, var->bits_per_pixel); + return -EINVAL; + } + + if (_par->var.xres*nom/den * _par->var.yres > fb_info->size) + { + printk("clgen: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n", + var->xres, var->yres, var->bits_per_pixel); + return -EINVAL; + } + + /* use highest possible virtual resolution */ + if (_par->var.xres_virtual == -1 && + _par->var.xres_virtual == -1) + { + printk("clgen: using maximum available virtual resolution\n"); + for (i=0; modes[i].xres != -1; i++) + { + if (modes[i].xres*nom/den * modes[i].yres < fb_info->size/2) + break; + } + if (modes[i].xres == -1) + { + printk("clgen: could not find a virtual resolution that fits into video memory!!\n"); + return -EINVAL; + } + _par->var.xres_virtual = modes[i].xres; + _par->var.yres_virtual = modes[i].yres; + + printk("clgen: virtual resolution set to maximum of %dx%d\n", + _par->var.xres_virtual, _par->var.yres_virtual); + } + else if (_par->var.xres_virtual == -1) + { + } + else if (_par->var.yres_virtual == -1) + { + } + + if (_par->var.xoffset < 0) _par->var.xoffset = 0; + if (_par->var.yoffset < 0) _par->var.yoffset = 0; + + /* truncate xoffset and yoffset to maximum if too high */ + if (_par->var.xoffset > _par->var.xres_virtual-_par->var.xres) + _par->var.xoffset = _par->var.xres_virtual-_par->var.xres -1; + + if (_par->var.yoffset > _par->var.yres_virtual-_par->var.yres) + _par->var.yoffset = _par->var.yres_virtual-_par->var.yres -1; + + switch (var->bits_per_pixel) + { + case 1: + _par->line_length = _par->var.xres_virtual / 8; + _par->visual = FB_VISUAL_MONO10; + break; + + case 8: + _par->line_length = _par->var.xres_virtual; + _par->visual = FB_VISUAL_PSEUDOCOLOR; + break; + + case 16: + _par->line_length = _par->var.xres_virtual * 2; + _par->visual = FB_VISUAL_DIRECTCOLOR; + break; + + case 24: + _par->line_length = _par->var.xres_virtual * 3; + _par->visual = FB_VISUAL_DIRECTCOLOR; + break; + + case 32: + _par->line_length = _par->var.xres_virtual * 4; + _par->visual = FB_VISUAL_DIRECTCOLOR; + break; + } + _par->type = FB_TYPE_PACKED_PIXELS; + + /* convert from ps to kHz */ + freq = 1000000000 / var->pixclock; + + DEBUG printk("desired pixclock: %ld kHz\n", freq); + + /* the SD64/P4 have a higher max. videoclock */ + bestclock(freq, &_par->freq, &_par->nom, &_par->den, &_par->div, + fb_info->btype == BT_SD64 || fb_info->btype == BT_PICASSO4 + ? 140000 : 90000); + + DEBUG printk("Best possible values for given frequency: best: %ld kHz nom: %ld den: %ld div: %ld\n", + _par->freq, _par->nom, _par->den, _par->div); + + xres = _par->var.xres; + hfront = _par->var.right_margin; + hsync = _par->var.hsync_len; + hback = _par->var.left_margin; + + yres = _par->var.yres; + vfront = _par->var.lower_margin; + vsync = _par->var.vsync_len; + vback = _par->var.upper_margin; + + if (_par->var.vmode & FB_VMODE_DOUBLE) + { + yres *= 2; + vfront *= 2; + vsync *= 2; + vback *= 2; + } + else if (_par->var.vmode & FB_VMODE_INTERLACED) + { + yres = ++yres / 2; + vfront = ++vfront / 2; + vsync = ++vsync / 2; + vback = ++vback / 2; + } + + _par->HorizRes = xres; + _par->HorizTotal = (xres + hfront + hsync + hback)/8 - 5; + _par->HorizDispEnd = xres/8 - 1; + _par->HorizBlankStart = xres/8; + _par->HorizBlankEnd = _par->HorizTotal+5; /* does not count with "-5" */ + _par->HorizSyncStart = (xres + hfront)/8 + 1; + _par->HorizSyncEnd = (xres + hfront + hsync)/8 + 1; + + _par->VertRes = yres; + _par->VertTotal = yres + vfront + vsync + vback -2; + _par->VertDispEnd = yres - 1; + _par->VertBlankStart = yres; + _par->VertBlankEnd = _par->VertTotal; + _par->VertSyncStart = yres + vfront - 1; + _par->VertSyncEnd = yres + vfront + vsync - 1; + + if (_par->VertTotal >= 1024) + { + printk(KERN_WARNING "clgen: ERROR: VerticalTotal >= 1024; special treatment required! (TODO)\n"); + return -EINVAL; + } + + return 0; +} + + +static int clgen_encode_var(struct fb_var_screeninfo *var, const void *par, + struct fb_info_gen *info) +{ + *var = ((struct clgenfb_par*)par)->var; + return 0; +} + +/* get current video mode */ +static void clgen_get_par(void *par, struct fb_info_gen *info) +{ + struct clgenfb_par *_par = (struct clgenfb_par*)par; + struct clgenfb_info*_info = (struct clgenfb_info*)fb_info; + + *_par = _info->currentmode; +} + +/************************************************************************* + clgen_set_par() + + actually writes the values for a new video mode into the hardware, +**************************************************************************/ +static void clgen_set_par(const void *par, struct fb_info_gen *info) +{ + unsigned char tmp; + int offset = 0; + struct clgenfb_par *_par = (struct clgenfb_par*)par; + + printk(KERN_INFO">clgen_set_par()\n"); + printk(KERN_INFO"Requested mode: %dx%dx%d\n", + _par->var.xres, _par->var.yres, _par->var.bits_per_pixel); + printk(KERN_INFO"pixclock: %d\n", _par->var.pixclock); + + fb_info = (struct clgenfb_info *)info; + + /* unlock register CRT0..CRT7 */ + WCrt(CRT11, 0x20); /* previously: 0x00) */ + + /* if DEBUG is set, all parameters get output before writing */ + DEBUG printk("CRT0: %ld\n", _par->HorizTotal); + WCrt(CRT0, _par->HorizTotal); + + DEBUG printk("CRT1: %ld\n", _par->HorizDispEnd); + WCrt(CRT1, _par->HorizDispEnd); + + DEBUG printk("CRT2: %ld\n", _par->HorizBlankStart); + WCrt(CRT2, _par->HorizBlankStart); + + DEBUG printk("CRT3: 128+%ld\n", _par->HorizBlankEnd % 32); /* + 128: Compatible read */ + WCrt(CRT3, 128 + (_par->HorizBlankEnd % 32)); + + DEBUG printk("CRT4: %ld\n", _par->HorizSyncStart); + WCrt(CRT4, _par->HorizSyncStart); + + tmp = _par->HorizSyncEnd % 32; + if (_par->HorizBlankEnd & 32) + tmp += 128; + DEBUG printk("CRT5: %d\n", tmp); + WCrt(CRT5, tmp); + + DEBUG printk("CRT6: %ld\n", _par->VertTotal & 0xff); + WCrt(CRT6, (_par->VertTotal & 0xff)); + + tmp = 16; /* LineCompare bit #9 */ + if (_par->VertTotal & 256) tmp |= 1; + if (_par->VertDispEnd & 256) tmp |= 2; + if (_par->VertSyncStart & 256) tmp |= 4; + if (_par->VertBlankStart & 256) tmp |= 8; + if (_par->VertTotal & 512) tmp |= 32; + if (_par->VertDispEnd & 512) tmp |= 64; + if (_par->VertSyncStart & 512) tmp |= 128; + DEBUG printk("CRT7: %d\n", tmp); + WCrt(CRT7, tmp); + + tmp = 0x40; /* LineCompare bit #8 */ + if (_par->VertBlankStart & 512) tmp |= 0x20; + if (_par->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80; + DEBUG printk("CRT9: %d\n", tmp); + WCrt(CRT9, tmp); + + DEBUG printk("CRT10: %ld\n", _par->VertSyncStart & 0xff); + WCrt(CRT10, (_par->VertSyncStart & 0xff)); + + DEBUG printk("CRT11: 64+32+%ld\n", _par->VertSyncEnd % 16); + WCrt(CRT11, (_par->VertSyncEnd % 16 + 64 + 32)); + + DEBUG printk("CRT12: %ld\n", _par->VertDispEnd & 0xff); + WCrt(CRT12, (_par->VertDispEnd & 0xff)); + + DEBUG printk("CRT15: %ld\n", _par->VertBlankStart & 0xff); + WCrt(CRT15, (_par->VertBlankStart & 0xff)); + + DEBUG printk("CRT16: %ld\n", _par->VertBlankEnd & 0xff); + WCrt(CRT16, (_par->VertBlankEnd & 0xff)); + + DEBUG printk("CRT18: 0xff\n"); + WCrt(CRT18, 0xff); + + tmp = 0; + if (_par->var.vmode & FB_VMODE_INTERLACED) tmp |= 1; + if (_par->HorizBlankEnd & 64) tmp |= 16; + if (_par->HorizBlankEnd & 128) tmp |= 32; + if (_par->VertBlankEnd & 256) tmp |= 64; + if (_par->VertBlankEnd & 512) tmp |= 128; + + DEBUG printk("CRT1a: %d\n", tmp); + WCrt(CRT1A, tmp); + + /* set VCLK0 */ + /* hardware RefClock: 14.31818 MHz */ + /* formula: VClk = (OSC * N) / (D * (1+P)) */ + /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ + + WSeq(SEQRB, _par->nom); + tmp = _par->den<<1; + if (_par->div != 0) tmp |= 1; + + if (fb_info->btype == BT_SD64) + tmp |= 0x80; /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ + + WSeq(SEQR1B, tmp); + + WCrt(CRT17, 0xc3); /* mode control: CRTC enable, ROTATE(?), 16bit address wrap, no compat. */ + +/* HAEH? WCrt(CRT11, 0x20); * previously: 0x00 unlock CRT0..CRT7 */ + + /* don't know if it would hurt to also program this if no interlaced */ + /* mode is used, but I feel better this way.. :-) */ + if (_par->var.vmode & FB_VMODE_INTERLACED) + WCrt(CRT19, _par->HorizTotal / 2); + else + WCrt(CRT19, 0x00); /* interlace control */ + + WSeq(SEQR3, 0); + + /* adjust horizontal/vertical sync type (low/high) */ + tmp = 0x03; /* enable display memory & CRTC I/O address for color mode */ + if (_par->var.sync & FB_SYNC_HOR_HIGH_ACT) tmp |= 0x40; + if (_par->var.sync & FB_SYNC_VERT_HIGH_ACT) tmp |= 0x80; + WGen(MISC_W, tmp); + + WCrt(CRT8, 0); /* Screen A Preset Row-Scan register */ + WCrt(CRTA, 0); /* text cursor on and start line */ + WCrt(CRTB, 31); /* text cursor end line */ + + /* programming for different color depths */ + if (_par->var.bits_per_pixel == 1) + { + DEBUG printk(KERN_INFO "clgen: preparing for 1 bit deep display\n"); +#if 0 + /* restore first 2 color registers for mono mode */ + WClut( 0, 0x00, 0x00, 0x00); /* background: black */ + WClut( 1, 0xff, 0xff, 0xff); /* foreground: white */ +#endif + WGfx(GR5, 0); /* mode register */ + + /* Extended Sequencer Mode */ + switch(fb_info->btype) + { + case BT_SD64: + /* setting the SEQRF on SD64 is not necessary (only during init) */ + DEBUG printk(KERN_INFO "(for SD64)\n"); + WSeq(SEQR7, 0xf0); + WSeq(SEQR1F, 0x1a); /* MCLK select */ + break; + + case BT_PICCOLO: + DEBUG printk(KERN_INFO "(for Piccolo)\n"); + WSeq(SEQR7, 0x80); +/* ### ueberall 0x22? */ + WSeq(SEQR1F, 0x22); /* ##vorher 1c MCLK select */ + WSeq(SEQRF, 0xb0); /* evtl d0 bei 1 bit? avoid FIFO underruns..? */ + break; + + case BT_PICASSO: + DEBUG printk(KERN_INFO "(for Picasso)\n"); + WSeq(SEQR7, 0x20); + WSeq(SEQR1F, 0x22); /* ##vorher 22 MCLK select */ + WSeq(SEQRF, 0xd0); /* ## vorher d0 avoid FIFO underruns..? */ + break; + + case BT_SPECTRUM: + DEBUG printk(KERN_INFO "(for Spectrum)\n"); + WSeq(SEQR7, 0x80); +/* ### ueberall 0x22? */ + WSeq(SEQR1F, 0x22); /* ##vorher 1c MCLK select */ + WSeq(SEQRF, 0xb0); /* evtl d0? avoid FIFO underruns..? */ + break; + + case BT_PICASSO4: + DEBUG printk(KERN_INFO "(for Picasso 4)\n"); + WSeq(SEQR7, 0x20); +/* WSeq(SEQR1F, 0x1c); */ +/* SEQRF not being set here... WSeq(SEQRF, 0xd0); */ + break; + + default: + printk(KERN_WARNING "clgen: unknown Board\n"); + break; + } + + WGen(M_3C6,0x01); /* pixel mask: pass-through for first plane */ + WHDR(0); /* hidden dac reg: nothing special */ + WSeq(SEQR4, 0x06); /* memory mode: odd/even, ext. memory */ + WSeq(SEQR2, 0x01); /* plane mask: only write to first plane */ + offset = _par->var.xres_virtual / 16; + } + else if (_par->var.bits_per_pixel == 8) + { + DEBUG printk(KERN_INFO "clgen: preparing for 8 bit deep display\n"); + switch(fb_info->btype) + { + case BT_SD64: + WSeq(SEQR7, 0xf1); /* Extended Sequencer Mode: 256c col. mode */ + WSeq(SEQR1F, 0x1d); /* MCLK select */ + break; + + case BT_PICCOLO: + WSeq(SEQR7, 0x81); + WSeq(SEQR1F, 0x22); /* ### vorher 1c MCLK select */ + WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ + break; + + case BT_PICASSO: + WSeq(SEQR7, 0x21); + WSeq(SEQR1F, 0x22); /* ### vorher 1c MCLK select */ + WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ + break; + + case BT_SPECTRUM: + WSeq(SEQR7, 0x81); + WSeq(SEQR1F, 0x22); /* ### vorher 1c MCLK select */ + WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ + break; + + case BT_PICASSO4: + WSeq(SEQR7, 0x21); + WSeq(SEQRF, 0xb8); /* ### INCOMPLETE!! */ +/* WSeq(SEQR1F, 0x1c); */ + break; + + default: + printk(KERN_WARNING "clgen: unknown Board\n"); + break; + } + + WGfx(GR5, 64); /* mode register: 256 color mode */ + WGen(M_3C6,0xff); /* pixel mask: pass-through all planes */ + WHDR(0); /* hidden dac reg: nothing special */ + WSeq(SEQR4, 0x0a); /* memory mode: chain4, ext. memory */ + WSeq(SEQR2, 0xff); /* plane mask: enable writing to all 4 planes */ + offset = _par->var.xres_virtual / 8; + } + else if (_par->var.bits_per_pixel == 16) + { + DEBUG printk(KERN_INFO "clgen: preparing for 16 bit deep display\n"); + switch(fb_info->btype) + { + case BT_SD64: + WSeq(SEQR7, 0xf7); /* Extended Sequencer Mode: 256c col. mode */ + WSeq(SEQR1F, 0x1e); /* MCLK select */ + break; + + case BT_PICCOLO: + WSeq(SEQR7, 0x87); + WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ + WSeq(SEQR1F, 0x22); /* MCLK select */ + break; + + case BT_PICASSO: + WSeq(SEQR7, 0x27); + WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ + WSeq(SEQR1F, 0x22); /* MCLK select */ + break; + + case BT_SPECTRUM: + WSeq(SEQR7, 0x87); + WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ + WSeq(SEQR1F, 0x22); /* MCLK select */ + break; + + case BT_PICASSO4: + WSeq(SEQR7, 0x27); +/* WSeq(SEQR1F, 0x1c); */ + break; + + default: + printk(KERN_WARNING "CLGEN: unknown Board\n"); + break; + } + + WGfx(GR5, 64); /* mode register: 256 color mode */ + WGen(M_3C6,0xff); /* pixel mask: pass-through all planes */ + WHDR(0xa0); /* hidden dac reg: nothing special */ + WSeq(SEQR4, 0x0a); /* memory mode: chain4, ext. memory */ + WSeq(SEQR2, 0xff); /* plane mask: enable writing to all 4 planes */ + offset = _par->var.xres_virtual / 4; + } + else if (_par->var.bits_per_pixel == 32) + { + DEBUG printk(KERN_INFO "clgen: preparing for 24/32 bit deep display\n"); + switch(fb_info->btype) + { + case BT_SD64: + WSeq(SEQR7, 0xf9); /* Extended Sequencer Mode: 256c col. mode */ + WSeq(SEQR1F, 0x1e); /* MCLK select */ + break; + + case BT_PICCOLO: + WSeq(SEQR7, 0x85); + WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ + WSeq(SEQR1F, 0x22); /* MCLK select */ + break; + + case BT_PICASSO: + WSeq(SEQR7, 0x25); + WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ + WSeq(SEQR1F, 0x22); /* MCLK select */ + break; + + case BT_SPECTRUM: + WSeq(SEQR7, 0x85); + WSeq(SEQRF, 0xb0); /* Fast Page-Mode writes */ + WSeq(SEQR1F, 0x22); /* MCLK select */ + break; + + case BT_PICASSO4: + WSeq(SEQR7, 0x25); +/* WSeq(SEQR1F, 0x1c); */ + break; + + default: + printk(KERN_WARNING "clgen: unknown Board\n"); + break; + } + + WGfx(GR5, 64); /* mode register: 256 color mode */ + WGen(M_3C6,0xff); /* pixel mask: pass-through all planes */ + WHDR(0xc5); /* hidden dac reg: 8-8-8 mode (24 or 32) */ + WSeq(SEQR4, 0x0a); /* memory mode: chain4, ext. memory */ + WSeq(SEQR2, 0xff); /* plane mask: enable writing to all 4 planes */ + offset = _par->var.xres_virtual / 4; + } + else + printk(KERN_ERR "clgen: What's this?? requested color depth == %d.\n", + _par->var.bits_per_pixel); + + WCrt(CRT13, offset & 0xff); + tmp = 0x22; + if (offset & 0x100) tmp |= 0x10; /* offset overflow bit */ + + WCrt(CRT1B,tmp); /* screen start addr #16-18, fastpagemode cycles */ + + if (fb_info->btype == BT_SD64 || fb_info->btype == BT_PICASSO4) + WCrt(CRT1D, 0x00); /* screen start address bit 19 */ + + WCrt(CRTE, 0); /* text cursor location high */ + WCrt(CRTF, 0); /* text cursor location low */ + WCrt(CRT14, 0); /* underline row scanline = at very bottom */ + + WAttr(AR10, 1); /* controller mode */ + WAttr(AR11, 0); /* overscan (border) color */ + WAttr(AR12, 15); /* color plane enable */ + WAttr(AR33, 0); /* pixel panning */ + WAttr(AR14, 0); /* color select */ + + /* [ EGS: SetOffset(); ] */ + /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */ + AttrOn(); + + WGfx(GR0, 0); /* set/reset register */ + WGfx(GR1, 0); /* set/reset enable */ + WGfx(GR2, 0); /* color compare */ + WGfx(GR3, 0); /* data rotate */ + WGfx(GR4, 0); /* read map select */ + WGfx(GR6, 1); /* miscellaneous register */ + WGfx(GR7, 15); /* color don't care */ + WGfx(GR8, 255); /* bit mask */ + + WSeq(SEQR12, 0x0); /* graphics cursor attributes: nothing special */ + + /* finally, turn on everything - turn off "FullBandwidth" bit */ + /* also, set "DotClock%2" bit where requested */ + tmp = 0x01; + +/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ? + if (var->vmode & FB_VMODE_CLOCK_HALVE) + tmp |= 0x08; +*/ + + WSeq(SEQR1, tmp); + DEBUG printk("SEQR1: %d\n", tmp); + +#if 0 + DEBUG printk(KERN_INFO "clgen: clearing display..."); + clgen_RectFill(0, 0, _par->HorizRes, _par->VertRes, 0, _par->line_length); + clgen_WaitBLT(); + DEBUG printk("done.\n"); +#endif + + fb_info->currentmode = *_par; + + printk("virtual offset: (%d,%d)\n", _par->var.xoffset,_par->var.yoffset); + /* pan to requested offset */ + clgen_pan_display (&fb_info->currentmode.var, (struct fb_info_gen*)fb_info); + + DEBUG printk("<clgen_set_par()\n"); + return; +} + +static int clgen_getcolreg(unsigned regno, unsigned *red, unsigned *green, + unsigned *blue, unsigned *transp, + struct fb_info *info) +{ + unsigned char bred, bgreen, bblue; + + if (regno > 255 || regno < 0) + return (1); + + fb_info = (struct clgenfb_info *)info; + + RClut(regno, &bred, &bgreen, &bblue); + + *red = (u_int)bred; + *green = (u_int)bgreen; + *blue = (u_int)bblue; + *transp = 0; + return (0); +} + +static int clgen_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + if (regno > 255 || regno < 0) + return (1); + + fb_info = (struct clgenfb_info *)info; + + /* "transparent" stuff is completely ignored. */ + WClut(regno, (red & 0xff), (green & 0xff), (blue & 0xff)); + + return (0); +} + +/************************************************************************* + clgen_pan_display() + + performs display panning - provided hardware permits this +**************************************************************************/ +static int clgen_pan_display(const struct fb_var_screeninfo *var, + struct fb_info_gen *info) +{ + int xoffset = 0; + int yoffset = 0; + unsigned long base; + unsigned char tmp = 0, tmp2 = 0, xpix; + + fb_info = (struct clgenfb_info*)fb_info; + + /* no range checks for xoffset and yoffset, */ + /* as fbgen_pan_display has already done this */ + + fb_info->currentmode.var.xoffset = var->xoffset; + fb_info->currentmode.var.yoffset = var->yoffset; + + xoffset = var->xoffset * fb_info->currentmode.var.bits_per_pixel / 8; + yoffset = var->yoffset; + + base = yoffset * fb_info->currentmode.line_length + xoffset; + + if (fb_info->currentmode.var.bits_per_pixel == 1) + { + /* base is already correct */ + xpix = (unsigned char)(var->xoffset % 8); + } + else + { + base /= 4; + xpix = (unsigned char)((xoffset % 4) * 2); + } + + /* lower 8 + 8 bits of screen start address */ + WCrt(CRTD, (unsigned char)(base & 0xff)); + WCrt(CRTC, (unsigned char)(base >> 8)); + + /* construct bits 16, 17 and 18 of screen start address */ + if (base & 0x10000) tmp |= 0x01; + if (base & 0x20000) tmp |= 0x04; + if (base & 0x40000) tmp |= 0x08; + + tmp2 = (RCrt(CRT1B) & 0xf2) | tmp; /* 0xf2 is %11110010, exclude tmp bits */ + WCrt(CRT1B, tmp2); + /* construct bit 19 of screen start address (only on SD64) */ + if (fb_info->btype == BT_SD64 || + fb_info->btype == BT_PICASSO4) + { + tmp2 = 0; + if (base & 0x80000) tmp2 = 0x80; + WCrt(CRT1D, tmp2); + } + + /* write pixel panning value to AR33; this does not quite work in 8bpp */ + /* ### Piccolo..? Will this work? */ + if (fb_info->currentmode.var.bits_per_pixel == 1) + WAttr(AR33, xpix); + + return(0); +} + + +static int clgen_blank(int blank_mode, struct fb_info_gen *info) +{ + unsigned char val; + printk(">clgen_blank(%d)\n",blank_mode); + + fb_info = (struct clgenfb_info *)info; + + val = RSeq(SEQR1); + if (blank_mode) + WSeq(SEQR1, val | 0x20); /* set "FullBandwidth" bit */ + else + WSeq(SEQR1, val & 0xdf); /* clear "FullBandwidth" bit */ + + printk("<clgen_blank()\n"); + return 0; +} + +/**** END Hardware specific Routines **************************************/ +/****************************************************************************/ +/**** BEGIN Internal Routines ***********************************************/ + +static void init_vgachip(void) +{ + printk(">init_vgachip()\n"); + + /* reset board globally */ + switch(fb_info->btype) + { + case BT_SD64: WSFR(0x1f); udelay(500); WSFR(0x4f); udelay(500); break; + case BT_PICCOLO: WSFR(0x01); udelay(500); WSFR(0x51); udelay(500); break; + case BT_PICASSO: WSFR2(0xff); udelay(500); break; + case BT_SPECTRUM: WSFR(0x1f); udelay(500); WSFR(0x4f); udelay(500); break; + case BT_PICASSO4: + WCrt(CRT51, 0x00); /* disable flickerfixer */ + udelay(100000); + WGfx(GR2F, 0x00); /* from Klaus' NetBSD driver: */ + WGfx(GR33, 0x00); /* put blitter into 542x compat */ + WGfx(GR31, 0x00); /* mode */ + break; + + default: + printk(KERN_ERR "clgen: Warning: Unknown board type\n"); + break; + } + + /* "pre-set" a RAMsize; if the test succeeds, double it */ + if (fb_info->btype == BT_SD64 || + fb_info->btype == BT_PICASSO4) + fb_info->size = 0x400000; + else + fb_info->size = 0x200000; + + /* assume it's a "large memory" board (2/4 MB) */ + fb_info->smallboard = FALSE; + + /* the P4 is not fully initialized here; I rely on it having been */ + /* inited under AmigaOS already, which seems to work just fine */ + /* (Klaus advised to do it this way) */ + + if (fb_info->btype != BT_PICASSO4) + { + WGen(VSSM, 0x10); /* EGS: 0x16 */ + WGen(POS102, 0x01); + WGen(VSSM, 0x08); /* EGS: 0x0e */ + + if(fb_info->btype != BT_SD64) + WGen(VSSM2, 0x01); + + WSeq(SEQR0, 0x03); /* reset sequencer logic */ + + WSeq(SEQR1, 0x21); /* FullBandwidth (video off) and 8/9 dot clock */ + WGen(MISC_W, 0xc1); /* polarity (-/-), disable access to display memory, CRTC base address: color */ + +/* WGfx(GRA, 0xce); "magic cookie" - doesn't make any sense to me.. */ + WSeq(SEQR6, 0x12); /* unlock all extension registers */ + + WGfx(GR31, 0x04); /* reset blitter */ + + if (fb_info->btype == BT_SD64) + { + WSeq(SEQRF, 0xb8); /* 4 MB Ram SD64, disable CRT fifo(!), 64 bit bus */ + } + else + { + WSeq(SEQR16, 0x0f); /* Perf. Tuning: Fix value..(?) */ + WSeq(SEQRF, 0xb0); /* 2 MB DRAM, 8level write buffer, 32bit bus */ + } + } + + WSeq(SEQR2, 0xff); /* plane mask: nothing */ + WSeq(SEQR3, 0x00); /* character map select: doesn't even matter in gx mode */ + WSeq(SEQR4, 0x0e); /* memory mode: chain-4, no odd/even, ext. memory */ + + /* controller-internal base address of video memory */ + switch(fb_info->btype) + { + case BT_SD64: WSeq(SEQR7, 0xf0); break; + case BT_PICCOLO: WSeq(SEQR7, 0x80); break; + case BT_SPECTRUM: WSeq(SEQR7, 0x80); break; + case BT_PICASSO: WSeq(SEQR7, 0x20); break; + case BT_PICASSO4: WSeq(SEQR7, 0x20); break; + } + +/* WSeq(SEQR8, 0x00);*/ /* EEPROM control: shouldn't be necessary to write to this at all.. */ + + WSeq(SEQR10, 0x00); /* graphics cursor X position (incomplete; position gives rem. 3 bits */ + WSeq(SEQR11, 0x00); /* graphics cursor Y position (..."... ) */ + WSeq(SEQR12, 0x00); /* graphics cursor attributes */ + WSeq(SEQR13, 0x00); /* graphics cursor pattern address */ + + /* writing these on a P4 might give problems.. */ + if (fb_info->btype != BT_PICASSO4) + { + WSeq(SEQR17, 0x00); /* configuration readback and ext. color */ + WSeq(SEQR18, 0x02); /* signature generator */ + } + + /* MCLK select etc. */ + switch(fb_info->btype) + { + case BT_PICCOLO: + case BT_PICASSO: + case BT_SPECTRUM: WSeq(SEQR1F, 0x22); break; + case BT_SD64: WSeq(SEQR1F, 0x20); break; + case BT_PICASSO4:/*WSeq(SEQR1F, 0x1c); */ break; + } + + WCrt(CRT8, 0x00); /* Screen A preset row scan: none */ + WCrt(CRTA, 0x20); /* Text cursor start: disable text cursor */ + WCrt(CRTB, 0x00); /* Text cursor end: - */ + WCrt(CRTC, 0x00); /* Screen start address high: 0 */ + WCrt(CRTD, 0x00); /* Screen start address low: 0 */ + WCrt(CRTE, 0x00); /* text cursor location high: 0 */ + WCrt(CRTF, 0x00); /* text cursor location low: 0 */ + + WCrt(CRT14, 0x00); /* Underline Row scanline: - */ + WCrt(CRT17, 0xc3); /* mode control: timing enable, byte mode, no compat modes */ + WCrt(CRT18, 0x00); /* Line Compare: not needed */ + /* ### add 0x40 for text modes with > 30 MHz pixclock */ + WCrt(CRT1B, 0x02); /* ext. display controls: ext.adr. wrap */ + + WGfx(GR0, 0x00); /* Set/Reset registes: - */ + WGfx(GR1, 0x00); /* Set/Reset enable: - */ + WGfx(GR2, 0x00); /* Color Compare: - */ + WGfx(GR3, 0x00); /* Data Rotate: - */ + WGfx(GR4, 0x00); /* Read Map Select: - */ + WGfx(GR5, 0x00); /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */ + WGfx(GR6, 0x01); /* Miscellaneous: memory map base address, graphics mode */ + WGfx(GR7, 0x0f); /* Color Don't care: involve all planes */ + WGfx(GR8, 0xff); /* Bit Mask: no mask at all */ + WGfx(GRB, 0x28); /* Graphics controller mode extensions: finer granularity, 8byte data latches */ + + WGfx(GRC, 0xff); /* Color Key compare: - */ + WGfx(GRD, 0x00); /* Color Key compare mask: - */ + WGfx(GRE, 0x00); /* Miscellaneous control: - */ +/* WGfx(GR10, 0x00);*/ /* Background color byte 1: - */ +/* WGfx(GR11, 0x00); */ + + WAttr(AR0, 0x00); /* Attribute Controller palette registers: "identity mapping" */ + WAttr(AR1, 0x01); + WAttr(AR2, 0x02); + WAttr(AR3, 0x03); + WAttr(AR4, 0x04); + WAttr(AR5, 0x05); + WAttr(AR6, 0x06); + WAttr(AR7, 0x07); + WAttr(AR8, 0x08); + WAttr(AR9, 0x09); + WAttr(ARA, 0x0a); + WAttr(ARB, 0x0b); + WAttr(ARC, 0x0c); + WAttr(ARD, 0x0d); + WAttr(ARE, 0x0e); + WAttr(ARF, 0x0f); + + WAttr(AR10, 0x01); /* Attribute Controller mode: graphics mode */ + WAttr(AR11, 0x00); /* Overscan color reg.: reg. 0 */ + WAttr(AR12, 0x0f); /* Color Plane enable: Enable all 4 planes */ +/* ### WAttr(AR33, 0x00); * Pixel Panning: - */ + WAttr(AR14, 0x00); /* Color Select: - */ + + WGen(M_3C6, 0xff); /* Pixel mask: no mask */ + + WGen(MISC_W, 0xc3); /* polarity (-/-), enable display mem, CRTC i/o base = color */ + + WGfx(GR31, 0x04); /* BLT Start/status: Blitter reset */ + WGfx(GR31, 0x00); /* - " - : "end-of-reset" */ + + /* CLUT setup */ + WClut( 0, 0x00, 0x00, 0x00); /* background: black */ + WClut( 1, 0xff, 0xff, 0xff); /* foreground: white */ + WClut( 2, 0x00, 0x80, 0x00); + WClut( 3, 0x00, 0x80, 0x80); + WClut( 4, 0x80, 0x00, 0x00); + WClut( 5, 0x80, 0x00, 0x80); + WClut( 6, 0x80, 0x40, 0x00); + WClut( 7, 0x80, 0x80, 0x80); + WClut( 8, 0x40, 0x40, 0x40); + WClut( 9, 0x40, 0x40, 0xc0); + WClut(10, 0x40, 0xc0, 0x40); + WClut(11, 0x40, 0xc0, 0xc0); + WClut(12, 0xc0, 0x40, 0x40); + WClut(13, 0xc0, 0x40, 0xc0); + WClut(14, 0xc0, 0xc0, 0x40); + WClut(15, 0xc0, 0xc0, 0xc0); + + /* the rest a grey ramp */ + { + int i; + + for (i = 16; i < 256; i++) + WClut(i, i, i, i); + } + + + /* misc... */ + WHDR(0); /* Hidden DAC register: - */ + +#if 0 + /* check for 1/2 MB Piccolo/Picasso/Spectrum resp. 2/4 MB SD64 */ + /* DRAM register has already been pre-set for "large", so it is*/ + /* only modified if we find that this is a "small" version */ + { + unsigned volatile char *ram = fb_info->fbmem; + int i, flag = 0; + + ram += (fb_info->size >> 1); + + for (i = 0; i < 256; i++) + ram[i] = (unsigned char)i; + + for (i = 0; i < 256; i++) + { + if (ram[i] != i) + flag = 1; + } + + /* if the DRAM test failed, halve RAM value */ + if (flag) + { + fb_info->size /= 2; + fb_info->smallboard = TRUE; + switch(fb_info->btype) + { + case BT_SD64: WSeq(SEQRF, 0x38); break; /* 2 MB Ram SD64 */ + case BT_PICASSO4: WSeq(SEQRF, 0x38); break; /* ### like SD64? */ + case BT_PICCOLO: + case BT_PICASSO: + case BT_SPECTRUM: WSeq(SEQRF, 0x30); break; /* 1 MB DRAM */ + default: + printk(KERN_WARNING "clgen: Uuhh..could not determine RAM size!\n"); + } + } + + } +#endif + printk(KERN_INFO "clgen: This board has %ld bytes of DRAM memory\n", fb_info->size); + printk("<init_vgachip()\n"); + return; +} + +static void switch_monitor(int on) +{ + static int IsOn = 0; /* XXX not ok for multiple boards */ + + if (fb_info->btype == BT_PICASSO4) return; /* nothing to switch */ + if (fb_info->btype == BT_PICASSO) + { + if ((on && !IsOn) || (!on && IsOn)) + WSFR(0xff); + return; + } + if (on) + switch(fb_info->btype) + { + case BT_SD64: WSFR(fb_info->SFR | 0x21); break; + case BT_PICCOLO: WSFR(fb_info->SFR | 0x28); break; + case BT_SPECTRUM: WSFR(0x6f); break; + } + else + switch(fb_info->btype) + { + case BT_SD64: WSFR(fb_info->SFR & 0xde); break; + case BT_PICCOLO: WSFR(fb_info->SFR & 0xd7); break; + case BT_SPECTRUM: WSFR(0x4f); break; + } +} + +static struct display_switch *clgen_get_dispsw(const void *par, + struct fb_info_gen *info) +{ + struct clgenfb_par *_par = (struct clgenfb_par*) par; + + printk("clgen_get_dispsw(): "); + switch (_par->var.bits_per_pixel) + { +#ifdef FBCON_HAS_MFB + case 1: + printk("monochrome\n"); + return &fbcon_mfb; +#endif +#ifdef FBCON_HAS_CFB8 + case 8: + printk("8 bit color depth\n"); + return &fbcon_clgen_8; +#endif +#ifdef FBCON_HAS_CFB16 + case 16: + printk("16 bit color depth\n"); + return &fbcon_cfb16; +#endif +#ifdef FBCON_HAS_CFB24 + case 24: + printk("24 bit color depth\n"); + return &fbcon_cfb24; +#endif +#ifdef FBCON_HAS_CFB32 + case 32: + printk("32 bit color depth\n"); + return &fbcon_cfb32; +#endif + + default: + printk("unsupported color depth\n"); + return NULL; + } +} + +static void fbcon_clgen8_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; + + fb_info = (struct clgenfb_info*)p->fb_info; + + clgen_BitBLT((unsigned short)sx, (unsigned short)sy, + (unsigned short)dx, (unsigned short)dy, + (unsigned short)width, (unsigned short)height, + fb_info->currentmode.line_length); + clgen_WaitBLT(); +} + +static void fbcon_clgen8_clear(struct vc_data *conp, struct display *p, + int sy, int sx, int height, int width) +{ + unsigned short col; + + fb_info = (struct clgenfb_info*)p->fb_info; + + sx *= p->fontwidth; + sy *= p->fontheight; + width *= p->fontwidth; + height *= p->fontheight; + + col = attr_bgcol_ec(p, conp); + col &= 0xff; + + clgen_RectFill((unsigned short)sx, (unsigned short)sy, + (unsigned short)width,(unsigned short)height, + col, fb_info->currentmode.line_length); + clgen_WaitBLT(); +} + + +/********************************************************************/ +/* clgenfb_init() - master initialization function */ +/********************************************************************/ +__initfunc(void clgenfb_init(void)) +{ + const struct ConfigDev *cd = NULL; + const struct ConfigDev *cd2 = NULL; + int err; + int btype; + int key,key2; + unsigned long board_addr,board_size; + + printk(">clgenfb_init()\n"); + printk(KERN_INFO "clgen: Driver for Cirrus Logic based graphic boards, v" CLGEN_VERSION "\n"); + + btype = -1; + + if ((key = zorro_find(ZORRO_PROD_HELFRICH_SD64_RAM, 0, 0))) + { + key2 = zorro_find(ZORRO_PROD_HELFRICH_SD64_REG, 0, 0); + btype = BT_SD64; + printk(KERN_INFO "clgen: SD64 board detected; "); + } + else if ((key = zorro_find(ZORRO_PROD_HELFRICH_PICCOLO_RAM, 0, 0))) + { + key2 = zorro_find(ZORRO_PROD_HELFRICH_PICCOLO_REG, 0, 0); + btype = BT_PICCOLO; + printk(KERN_INFO "clgen: Piccolo board detected; "); + } + else if ((key = zorro_find(ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, 0, 0))) + { + key2 = zorro_find(ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG, 0, 0); + btype = BT_PICASSO; + printk(KERN_INFO "clgen: Picasso II board detected; "); + } + else if ((key = zorro_find(ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, 0, 0))) + { + key2 = zorro_find(ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG, 0, 0); + btype = BT_SPECTRUM; + printk(KERN_INFO "clgen: Spectrum board detected; "); + } + else if ((key = zorro_find(ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3, 0, 0))) + { + btype = BT_PICASSO4; + printk(KERN_INFO "clgen: Picasso 4 board detected; "); + } + else + { + printk(KERN_NOTICE "clgen: no supported board found.\n"); + return; + } + + fb_info = &boards[0]; /* FIXME support multiple boards ...*/ + + fb_info->keyRAM = key; + fb_info->keyREG = key2; + fb_info->btype = btype; + + cd = zorro_get_board(key); + board_addr = (unsigned long)cd->cd_BoardAddr; + board_size = (unsigned long)cd->cd_BoardSize; + printk(" RAM (%lu MB) at $%lx, ", board_size/0x100000, board_addr); + + if (btype == BT_PICASSO4) + { + printk(" REG at $%lx\n", board_addr + 0x600000); + + /* To be precise, for the P4 this is not the */ + /* begin of the board, but the begin of RAM. */ + /* for P4, map in its address space in 2 chunks (### TEST! ) */ + /* (note the ugly hardcoded 16M number) */ + fb_info->regs = (unsigned char *)kernel_map(board_addr, 16777216, + KERNELMAP_NOCACHE_SER, NULL); + DEBUG printk(KERN_INFO "clgen: Virtual address for board set to: $%p\n", fb_info->regs); + fb_info->regs += 0x600000; + + fb_info->fbmem = kernel_map(board_addr + 16777216, 16777216, + KERNELMAP_NOCACHE_SER, NULL); + DEBUG printk(KERN_INFO "clgen: (RAM start set to: $%lx)\n", fb_info->fbmem); + } + else + { + cd2 = zorro_get_board(key2); + printk(" REG at $%lx\n", (unsigned long)cd2->cd_BoardAddr); + + if (board_addr > 0x01000000) + fb_info->fbmem = kernel_map(board_addr, board_size, + KERNELMAP_NOCACHE_SER, NULL); + else + fb_info->fbmem = ZTWO_VADDR(board_addr); + + /* set address for REG area of board */ + fb_info->regs = (unsigned char *)ZTWO_VADDR(cd2->cd_BoardAddr); + + DEBUG printk(KERN_INFO "clgen: Virtual address for board set to: $%p\n", fb_info->regs); + DEBUG printk(KERN_INFO "clgen: (RAM start set to: $%lx)\n", fb_info->fbmem); + } + + init_vgachip(); + + /* set up a few more things, register framebuffer driver etc */ + fb_info->gen.parsize = sizeof(struct clgenfb_par); + fb_info->gen.fbhw = &clgen_hwswitch; + strcpy (fb_info->gen.info.modename, clgenfb_name); + fb_info->gen.info.node = -1; + fb_info->gen.info.fbops = &clgenfb_ops; + fb_info->gen.info.disp = &disp; + fb_info->gen.info.changevar = NULL; + fb_info->gen.info.switch_con = &fbgen_switch; + fb_info->gen.info.updatevar = &fbgen_update_var; + fb_info->gen.info.blank = &fbgen_blank; + + /* mark this board as "autoconfigured" */ + zorro_config_board(key, 0); + if (btype != BT_PICASSO4) + zorro_config_board(key2, 0); + + /* now that we know the board has been registered n' stuff, we */ + /* can finally initialize it to a default mode (640x480) */ + clgenfb_default = clgenfb_predefined[1].var; + clgenfb_default.activate = FB_ACTIVATE_NOW; + clgenfb_default.yres_virtual = 480*3; /* for fast scrolling (YPAN-Mode) */ + err = fbgen_do_set_var(&clgenfb_default, 1, &fb_info->gen); + + if (err) + return; + + disp.var = clgenfb_default; + fbgen_set_disp(-1, &fb_info->gen); + fbgen_install_cmap(0, &fb_info->gen); + + err = register_framebuffer(&fb_info->gen.info); + if (err) + { + printk(KERN_ERR "clgen: ERROR - could not register fb device; err = %d!\n", err); + return; + } + + printk("<clgenfb_init()\n"); + return; +} + + /* + * Cleanup + */ + +void clgenfb_cleanup(struct clgenfb_info *info) +{ + printk(">clgenfb_cleanup()\n"); + + fb_info = info; + + switch_monitor(0); + + zorro_unconfig_board(info->keyRAM, 0); + if (fb_info->btype != BT_PICASSO4) + zorro_unconfig_board(info->keyREG, 0); + + unregister_framebuffer(&info->gen.info); + printk("Framebuffer unregistered\n"); + printk("<clgenfb_cleanup()\n"); +} + + +/* A strtok which returns empty strings, too */ +static char *strtoke(char *s,const char *ct) +{ + char *sbegin, *send; + static char *ssave = NULL; + + sbegin = s ? s : ssave; + if (!sbegin) + return NULL; + if (*sbegin == '\0') { + ssave = NULL; + return NULL; + } + send = strpbrk(sbegin, ct); + if (send && *send != '\0') + *send++ = '\0'; + ssave = send; + return sbegin; +} + +/*****************************************************************/ +/* clgenfb_setup() might be used later for parsing possible */ +/* arguments to the video= bootstrap parameter. Right now, there */ +/* is nothing I do here. */ +/*****************************************************************/ +__initfunc(void clgenfb_setup(char *options, int *ints)) +{ +// char *this_opt; + +// printk("clgenfb_setup(): options: %s\n", options); +} + + + /* + * Modularization + */ + +#ifdef MODULE +int init_module(void) +{ + printk("init_module()\n"); + clgenfb_init(0); + return 0; +} + +void cleanup_module(void) +{ + printk("module_cleanup()\n"); + clgenfb_cleanup(fb_info); +} +#endif /* MODULE */ + + + +/**********************************************************************/ +/* about the following functions - I have used the same names for the */ +/* functions as Markus Wild did in his Retina driver for NetBSD as */ +/* they just made sense for this purpose. Apart from that, I wrote */ +/* these functions myself. */ +/**********************************************************************/ + +/*** WGen() - write into one of the external/general registers ***/ +void WGen(int regnum, unsigned char val) +{ + unsigned volatile char *reg = fb_info->regs + regnum; + + if(fb_info->btype == BT_PICASSO) + { + /* Picasso II specific hack */ +/* if (regnum == M_3C7_W || regnum == M_3C9 || regnum == VSSM2) */ + if (regnum == M_3C7_W || regnum == M_3C9) + reg += 0xfff; + } + + *reg = val; +} + +/*** RGen() - read out one of the external/general registers ***/ +unsigned char RGen(int regnum) +{ + unsigned volatile char *reg = fb_info->regs + regnum; + + if(fb_info->btype == BT_PICASSO) + { + /* Picasso II specific hack */ +/* if (regnum == M_3C7_W || regnum == M_3C9 || regnum == VSSM2) */ + if (regnum == M_3C7_W || regnum == M_3C9) + reg += 0xfff; + } + + return *reg; +} + +/*** WSeq() - write into a register of the sequencer ***/ +void WSeq(unsigned char regnum, unsigned char val) +{ + fb_info->regs[SEQRX] = regnum; + fb_info->regs[SEQRX+1] = val; +} + +/*** RSeq() - read out one of the Sequencer registers ***/ +unsigned char RSeq(unsigned char regnum) +{ + fb_info->regs[SEQRX] = regnum; + return fb_info->regs[SEQRX+1]; +} + +/*** WCrt() - write into a register of the CRT controller ***/ +void WCrt(unsigned char regnum, unsigned char val) +{ + fb_info->regs[CRTX] = regnum; + fb_info->regs[CRTX+1] = val; +} + +/*** RCrt() - read out one of the CRT controller registers ***/ +unsigned char RCrt(unsigned char regnum) +{ + fb_info->regs[CRTX] = regnum; + return fb_info->regs[CRTX+1]; +} + +/*** WGfx() - write into a register of the Gfx controller ***/ +void WGfx(unsigned char regnum, unsigned char val) +{ + fb_info->regs[GRX] = regnum; + fb_info->regs[GRX+1] = val; +} + +/*** RGfx() - read out one of the Gfx controller registers ***/ +unsigned char RGfx(unsigned char regnum) +{ + fb_info->regs[GRX] = regnum; + return fb_info->regs[GRX+1]; +} + +/*** WAttr() - write into a register of the Attribute controller ***/ +void WAttr(unsigned char regnum, unsigned char val) +{ + /* if the next access to the attribute controller is a data write access, */ + /* simply write back the information that was already there before, so that */ + /* the next write access after that will be an index write. */ + if (RCrt(CRT24) & 0x80) + /* can't use WAttr() here - we would go into a recursive loop otherwise */ + fb_info->regs[ARX] = fb_info->regs[ARX+1]; + + if (RCrt(CRT24) & 0x80) + printk(KERN_WARNING "clgen: *** AttrIdx BAD!***\n"); + + /* now, first set index and after that the value - both to the same address (!) */ + fb_info->regs[ARX] = regnum; + fb_info->regs[ARX] = val; +} + +/*** AttrOn() - turn on VideoEnable for Attribute controller ***/ +void AttrOn() +{ + if (RCrt(CRT24) & 0x80) + /* if we're just in "write value" mode, write back the */ + /* same value as before to not modify anything */ + fb_info->regs[ARX] = fb_info->regs[ARX+1]; + + /* turn on video bit */ +/* fb_info->regs[ARX] = 0x20; */ + fb_info->regs[ARX] = 0x33; + + /* dummy write on Reg0 to be on "write index" mode next time */ + fb_info->regs[ARX] = 0x00; +} + +/*** RAttr() - read out a register of the Attribute controller ***/ +unsigned char RAttr(unsigned char regnum) +{ + /* (explanation see above in WAttr() ) */ + if (RCrt(CRT24) & 0x80) + fb_info->regs[ARX] = fb_info->regs[ARX+1]; + + fb_info->regs[ARX] = regnum; + return fb_info->regs[ARX+1]; +} + + +/*** WHDR() - write into the Hidden DAC register ***/ +/* as the HDR is the only extension register that requires special treatment + * (the other extension registers are accessible just like the "ordinary" + * registers of their functional group) here is a specialized routine for + * accessing the HDR + */ +void WHDR(unsigned char val) +{ + unsigned char dummy; + + if(fb_info->btype == BT_PICASSO) + { + /* Klaus' hint for correct access to HDR on some boards */ + /* first write 0 to pixel mask (3c6) */ + WGen(M_3C6, 0x00); udelay(200); + /* next read dummy from pixel address (3c8) */ + dummy = RGen(M_3C8); udelay(200); + } + + /* now do the usual stuff to access the HDR */ + + dummy = RGen(M_3C6); udelay(200); + dummy = RGen(M_3C6); udelay(200); + dummy = RGen(M_3C6); udelay(200); + dummy = RGen(M_3C6); udelay(200); + + WGen(M_3C6, val); udelay(200); + + if(fb_info->btype == BT_PICASSO) + { + /* now first reset HDR access counter */ + dummy = RGen(M_3C8); udelay(200); + + /* and at the end, restore the mask value */ + /* ## is this mask always 0xff? */ + WGen(M_3C6, 0xff); udelay(200); + } +} + +/*** RHDR() - read out the Hidden DAC register ***/ +/* I hope this does not break on the GD5428 - cannot test it. */ +/* (Is there any board for the Amiga that uses the 5428 ?) */ +unsigned char RHDR() +{ + unsigned char dummy; + + dummy = RGen(M_3C6); + dummy = RGen(M_3C6); + dummy = RGen(M_3C6); + dummy = RGen(M_3C6); + + return RGen(M_3C6); +} + + +/*** WSFR() - write to the "special function register" (SFR) ***/ +void WSFR(unsigned char val) +{ + fb_info->SFR = val; + fb_info->regs[0x8000] = val; +} + +/* The Picasso has a second register for switching the monitor bit */ +void WSFR2(unsigned char val) +{ + /* writing an arbitrary value to this one causes the monitor switcher */ + /* to flip to Amiga display */ + fb_info->SFR = val; + fb_info->regs[0x9000] = val; +} + +/*** WClut - set CLUT entry (range: 0..255 is automat. shifted to 0..63) ***/ +void WClut(unsigned char regnum, unsigned char red, unsigned char green, unsigned char blue) +{ + unsigned int data = 0x3c9; + + /* address write mode register is not translated.. */ + fb_info->regs[0x3c8] = regnum; + + if(fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4) + { + /* but DAC data register IS, at least for Picasso II */ + if(fb_info->btype == BT_PICASSO) + data += 0xfff; + fb_info->regs[data] = (red >> 2); + fb_info->regs[data] = (green >> 2); + fb_info->regs[data] = (blue >> 2); + } + else + { + fb_info->regs[data] = (blue >> 2); + fb_info->regs[data] = (green >> 2); + fb_info->regs[data] = (red >> 2); + } +} + +/*** RClut - read CLUT entry and convert to 0..255 range ***/ +void RClut(unsigned char regnum, unsigned char *red, unsigned char *green, unsigned char *blue) +{ + unsigned int data = 0x3c9; + + fb_info->regs[0x3c7] = regnum; + + if(fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4) + { + if(fb_info->btype == BT_PICASSO) + data += 0xfff; + *red = fb_info->regs[data] << 2; + *green = fb_info->regs[data] << 2; + *blue = fb_info->regs[data] << 2; + } + else + { + *blue = fb_info->regs[data] << 2; + *green = fb_info->regs[data] << 2; + *red = fb_info->regs[data] << 2; + } +} + + +/******************************************************************* + clgen_WaitBLT() + + Wait for the BitBLT engine to complete a possible earlier job +*********************************************************************/ + +void clgen_WaitBLT() +{ + /* now busy-wait until we're done */ + while (RGfx(GR31) & 0x08) + ; +} + +/******************************************************************* + clgen_BitBLT() + + perform accelerated "scrolling" +********************************************************************/ + +void clgen_BitBLT (u_short curx, u_short cury, u_short destx, u_short desty, + u_short width, u_short height, u_short line_length) +{ + u_short nwidth, nheight; + u_long nsrc, ndest; + u_char bltmode; + + nwidth = width - 1; + nheight = height - 1; + + bltmode = 0x00; + /* if source adr < dest addr, do the Blt backwards */ + if (cury <= desty) + { + if (cury == desty) + { + /* if src and dest are on the same line, check x */ + if (curx < destx) + bltmode |= 0x01; + } + else + bltmode |= 0x01; + } + + if (!bltmode) + { + /* standard case: forward blitting */ + nsrc = (cury * line_length) + curx; + ndest = (desty * line_length) + destx; + } + else + { + /* this means start addresses are at the end, counting backwards */ + nsrc = cury * line_length + curx + nheight * line_length + nwidth; + ndest = desty * line_length + destx + nheight * line_length + nwidth; + } + +// clgen_WaitBLT(); /* ### NOT OK for multiple boards! */ + + /* + run-down of registers to be programmed: + destination pitch + source pitch + BLT width/height + source start + destination start + BLT mode + BLT ROP + GR0 / GR1: "fill color" + start/stop + */ + + /* pitch: set to line_length */ + WGfx(GR24, line_length & 0xff); /* dest pitch low */ + WGfx(GR25, (line_length >> 8)); /* dest pitch hi */ + WGfx(GR26, line_length & 0xff); /* source pitch low */ + WGfx(GR27, (line_length >> 8)); /* source pitch hi */ + + /* BLT width: actual number of pixels - 1 */ + WGfx(GR20, nwidth & 0xff); /* BLT width low */ + WGfx(GR21, (nwidth >> 8)); /* BLT width hi */ + + /* BLT height: actual number of lines -1 */ + WGfx(GR22, nheight & 0xff); /* BLT height low */ + WGfx(GR23, (nheight >> 8)); /* BLT width hi */ + + /* BLT destination */ + WGfx(GR28, (u_char)(ndest & 0xff)); /* BLT dest low */ + WGfx(GR29, (u_char)(ndest >> 8)); /* BLT dest mid */ + WGfx(GR2A, (u_char)(ndest >> 16)); /* BLT dest hi */ + + /* BLT source */ + WGfx(GR2C, (u_char)(nsrc & 0xff)); /* BLT src low */ + WGfx(GR2D, (u_char)(nsrc >> 8)); /* BLT src mid */ + WGfx(GR2E, (u_char)(nsrc >> 16)); /* BLT src hi */ + + /* BLT mode */ + WGfx(GR30, bltmode); /* BLT mode */ + + /* BLT ROP: SrcCopy */ + WGfx(GR32, 0x0d); /* BLT ROP */ + + /* and finally: GO! */ + WGfx(GR31, 0x02); /* BLT Start/status */ +} + +/******************************************************************* + clgen_RectFill() + + perform accelerated rectangle fill +********************************************************************/ + +void clgen_RectFill (u_short x, u_short y, u_short width, u_short height, + u_char color, u_short line_length) +{ + u_short nwidth, nheight; + u_long ndest; + + nwidth = width - 1; + nheight = height - 1; + + ndest = (y * line_length) + x; + +// clgen_WaitBLT(); /* ### NOT OK for multiple boards! */ + + /* pitch: set to line_length */ + WGfx(GR24, line_length & 0xff); /* dest pitch low */ + WGfx(GR25, (line_length >> 8)); /* dest pitch hi */ + WGfx(GR26, line_length & 0xff); /* source pitch low */ + WGfx(GR27, (line_length >> 8)); /* source pitch hi */ + + /* BLT width: actual number of pixels - 1 */ + WGfx(GR20, nwidth & 0xff); /* BLT width low */ + WGfx(GR21, (nwidth >> 8)); /* BLT width hi */ + + /* BLT height: actual number of lines -1 */ + WGfx(GR22, nheight & 0xff); /* BLT height low */ + WGfx(GR23, (nheight >> 8)); /* BLT width hi */ + + /* BLT destination */ + WGfx(GR28, (u_char)(ndest & 0xff)); /* BLT dest low */ + WGfx(GR29, (u_char)(ndest >> 8)); /* BLT dest mid */ + WGfx(GR2A, (u_char)(ndest >> 16)); /* BLT dest hi */ + + /* BLT source: set to 0 (is a dummy here anyway) */ + WGfx(GR2C, 0x00); /* BLT src low */ + WGfx(GR2D, 0x00); /* BLT src mid */ + WGfx(GR2E, 0x00); /* BLT src hi */ + + /* This is a ColorExpand Blt, using the */ + /* same color for foreground and background */ + WGfx(GR0, color); /* foreground color */ + WGfx(GR1, color); /* background color */ + + /* BLT mode: color expand, Enable 8x8 copy (faster?) */ + WGfx(GR30, 0xc0); /* BLT mode */ + + /* BLT ROP: SrcCopy */ + WGfx(GR32, 0x0d); /* BLT ROP */ + + /* and finally: GO! */ + WGfx(GR31, 0x02); /* BLT Start/status */ +} + +/************************************************************************** + * bestclock() - determine closest possible clock lower(?) than the + * desired pixel clock + **************************************************************************/ +#define abs(x) ((x)<0 ? -(x) : (x)) +static void bestclock(long freq, long *best, long *nom, + long *den, long *div, long maxfreq) +{ + long n, h, d, f; + + *nom = 0; + *den = 0; + *div = 0; + + if (freq < 8000) + freq = 8000; + + if (freq > maxfreq) + freq = maxfreq; + + *best = 0; + f = freq * 10; + + for(n = 32; n < 128; n++) + { + d = (143181 * n) / f; + if ( (d >= 7) && (d <= 63) ) + { + if (d > 31) + d = (d / 2) * 2; + h = (14318 * n) / d; + if ( abs(h - freq) < abs(*best - freq) ) + { + *best = h; + *nom = n; + if (d < 32) + { + *den = d; + *div = 0; + } + else + { + *den = d / 2; + *div = 1; + } + } + } + d = ( (143181 * n)+f-1) / f; + if ( (d >= 7) && (d <= 63) ) + { + if (d > 31) + d = (d / 2) * 2; + h = (14318 * n) / d; + if ( abs(h - freq) < abs(*best - freq) ) + { + *best = h; + *nom = n; + if (d < 32) + { + *den = d; + *div = 0; + } + else + { + *den = d / 2; + *div = 1; + } + } + } + } +} + diff --git a/drivers/video/clgenfb.h b/drivers/video/clgenfb.h new file mode 100644 index 000000000..3f66ec294 --- /dev/null +++ b/drivers/video/clgenfb.h @@ -0,0 +1,175 @@ + +/* definitions for Piccolo/SD64 VGA controller chip */ +/* these definitions might most of the time also work */ +/* for other CL-GD542x/543x based boards.. */ + +/*** External/General Registers ***/ +#define POS102 0x102 /* POS102 register */ +#define VSSM 0x46e8 /* Adapter Sleep */ +#define VSSM2 0x3c3 /* Motherboard Sleep */ +#define MISC_W 0x3c2 /* Miscellaneous Output register, write */ +#define MISC_R 0x3cc /* Miscellaneous Output register, read */ +#define FC_W 0x3da /* Feature Control Register, write (color) */ +#define FC_R 0x3ca /* Feature Control Register, read */ +#define FEAT 0x3c2 /* Input Status Register 0 */ +#define STAT 0x3da /* Input Status Register 1, read-only */ +#define M_3C6 0x3c6 /* Pixel Mask */ +#define M_3C7_W 0x3c7 /* Pixel Address Read Mode (write) */ +#define M_3C7_R 0x3c7 /* DAC State (read-only */ +#define M_3C8 0x3c8 /* Pixel Address Write Mode */ +#define M_3C9 0x3c9 /* Pixel Data */ + +/*** VGA Sequencer Registers ***/ +#define SEQRX 0x3c4 /* Sequencer Index */ +#define SEQR0 0x0 /* Reset */ +#define SEQR1 0x1 /* Clocking Mode */ +#define SEQR2 0x2 /* Plane Mask / Write Pixel Extension */ +#define SEQR3 0x3 /* Character Map Select */ +#define SEQR4 0x4 /* Memory Mode */ +/* the following are from the "extension registers" group */ +#define SEQR6 0x6 /* Unlock ALL Extensions */ +#define SEQR7 0x7 /* Extended Sequencer Mode */ +#define SEQR8 0x8 /* EEPROM Control */ +#define SEQR9 0x9 /* Scratch Pad 0 (do not access!) */ +#define SEQRA 0xa /* Scratch Pad 1 (do not access!) */ +#define SEQRB 0xb /* VCLK0 Numerator */ +#define SEQRC 0xc /* VCLK1 Numerator */ +#define SEQRD 0xd /* VCLK2 Numerator */ +#define SEQRE 0xe /* VCLK3 Numerator */ +#define SEQRF 0xf /* DRAM Control */ +#define SEQR10 0x10 /* Graphics Cursor X Position */ +#define SEQR11 0x11 /* Graphics Cursor Y Position */ +#define SEQR12 0x12 /* Graphics Cursor Attributes */ +#define SEQR13 0x13 /* Graphics Cursor Pattern Address Offset */ +#define SEQR14 0x14 /* Scratch Pad 2 (CL-GD5426/'28 Only) (do not access!) */ +#define SEQR15 0x15 /* Scratch Pad 3 (CL-GD5426/'28 Only) (do not access!) */ +#define SEQR16 0x16 /* Performance Tuning (CL-GD5424/'26/'28 Only) */ +#define SEQR17 0x17 /* Configuration ReadBack and Extended Control (CL-GF5428 Only) */ +#define SEQR18 0x18 /* Signature Generator Control (Not CL-GD5420) */ +#define SEQR19 0x19 /* Signature Generator Result Low Byte (Not CL-GD5420) */ +#define SEQR1A 0x1a /* Signature Generator Result High Byte (Not CL-GD5420) */ +#define SEQR1B 0x1b /* VCLK0 Denominator and Post-Scalar Value */ +#define SEQR1C 0x1c /* VCLK1 Denominator and Post-Scalar Value */ +#define SEQR1D 0x1d /* VCLK2 Denominator and Post-Scalar Value */ +#define SEQR1E 0x1e /* VCLK3 Denominator and Post-Scalar Value */ +#define SEQR1F 0x1f /* BIOS ROM write enable and MCLK Select */ + +/*** CRT Controller Registers ***/ +#define CRTX 0x3d4 /* CRTC Index */ +#define CRT0 0x0 /* Horizontal Total */ +#define CRT1 0x1 /* Horizontal Display End */ +#define CRT2 0x2 /* Horizontal Blanking Start */ +#define CRT3 0x3 /* Horizontal Blabking End */ +#define CRT4 0x4 /* Horizontal Sync Start */ +#define CRT5 0x5 /* Horizontal Sync End */ +#define CRT6 0x6 /* Vertical Total */ +#define CRT7 0x7 /* Overflow */ +#define CRT8 0x8 /* Screen A Preset Row Scan */ +#define CRT9 0x9 /* Character Cell Height */ +#define CRTA 0xa /* Text Cursor Start */ +#define CRTB 0xb /* Text Cursor End */ +#define CRTC 0xc /* Screen Start Address High */ +#define CRTD 0xd /* Screen Start Address Low */ +#define CRTE 0xe /* Text Cursor Location High */ +#define CRTF 0xf /* Text Cursor Location Low */ +#define CRT10 0x10 /* Vertical Sync Start */ +#define CRT11 0x11 /* Vertical Sync End */ +#define CRT12 0x12 /* Vertical Display End */ +#define CRT13 0x13 /* Offset */ +#define CRT14 0x14 /* Underline Row Scan */ +#define CRT15 0x15 /* Vertical Blanking Start */ +#define CRT16 0x16 /* Vertical Blanking End */ +#define CRT17 0x17 /* Mode Control */ +#define CRT18 0x18 /* Line Compare */ +#define CRT22 0x22 /* Graphics Data Latches ReadBack */ +#define CRT24 0x24 /* Attribute Controller Toggle ReadBack */ +#define CRT26 0x26 /* Attribute Controller Index ReadBack */ +/* the following are from the "extension registers" group */ +#define CRT19 0x19 /* Interlace End */ +#define CRT1A 0x1a /* Interlace Control */ +#define CRT1B 0x1b /* Extended Display Controls */ +#define CRT1C 0x1c /* Sync adjust and genlock register */ +#define CRT1D 0x1d /* Overlay Extended Control register */ +#define CRT25 0x25 /* Part Status Register */ +#define CRT27 0x27 /* ID Register */ +#define CRT51 0x51 /* P4 disable "flicker fixer" */ + +/*** Graphics Controller Registers ***/ +#define GRX 0x3ce /* Graphics Controller Index */ +#define GR0 0x0 /* Set/Reset, Write Mode 5 Background Extension */ +#define GR1 0x1 /* Set/Reset Enable, Write Mode 4, 5 Foreground Ext. */ +#define GR2 0x2 /* Color Compare */ +#define GR3 0x3 /* Data Rotate */ +#define GR4 0x4 /* Read Map Select */ +#define GR5 0x5 /* Mode */ +#define GR6 0x6 /* Miscellaneous */ +#define GR7 0x7 /* Color Don't Care */ +#define GR8 0x8 /* Bit Mask */ +/* the following are from the "extension registers" group */ +#define GR9 0x9 /* Offset Register 0 */ +#define GRA 0xa /* Offset Register 1 */ +#define GRB 0xb /* Graphics Controller Mode Extensions */ +#define GRC 0xc /* Color Key (CL-GD5424/'26/'28 Only) */ +#define GRD 0xd /* Color Key Mask (CL-GD5424/'26/'28 Only) */ +#define GRE 0xe /* Miscellaneous Control (Cl-GD5428 Only) */ +#define GRF 0xf /* Display Compression Control register */ +#define GR10 0x10 /* 16-bit Pixel BG Color High Byte (Not CL-GD5420) */ +#define GR11 0x11 /* 16-bit Pixel FG Color High Byte (Not CL-GD5420) */ +#define GR12 0x12 /* Background Color Byte 2 Register */ +#define GR13 0x13 /* Foreground Color Byte 2 Register */ +#define GR14 0x14 /* Background Color Byte 3 Register */ +#define GR15 0x15 /* Foreground Color Byte 3 Register */ +/* the following are CL-GD5426/'28 specific blitter registers */ +#define GR20 0x20 /* BLT Width Low */ +#define GR21 0x21 /* BLT Width High */ +#define GR22 0x22 /* BLT Height Low */ +#define GR23 0x23 /* BLT Height High */ +#define GR24 0x24 /* BLT Destination Pitch Low */ +#define GR25 0x25 /* BLT Destination Pitch High */ +#define GR26 0x26 /* BLT Source Pitch Low */ +#define GR27 0x27 /* BLT Source Pitch High */ +#define GR28 0x28 /* BLT Destination Start Low */ +#define GR29 0x29 /* BLT Destination Start Mid */ +#define GR2A 0x2a /* BLT Destination Start High */ +#define GR2C 0x2c /* BLT Source Start Low */ +#define GR2D 0x2d /* BLT Source Start Mid */ +#define GR2E 0x2e /* BLT Source Start High */ +#define GR2F 0x2f /* Picasso IV Blitter compat mode..? */ +#define GR30 0x30 /* BLT Mode */ +#define GR31 0x31 /* BLT Start/Status */ +#define GR32 0x32 /* BLT Raster Operation */ +#define GR33 0x33 /* another P4 "compat" register.. */ +#define GR34 0x34 /* Transparent Color Select Low */ +#define GR35 0x35 /* Transparent Color Select High */ +#define GR38 0x38 /* Source Transparent Color Mask Low */ +#define GR39 0x39 /* Source Transparent Color Mask High */ + +/*** Attribute Controller Registers ***/ +#define ARX 0x3c0 /* Attribute Controller Index */ +#define AR0 0x0 /* Attribute Controller Palette Register 0 */ +#define AR1 0x1 /* Attribute Controller Palette Register 1 */ +#define AR2 0x2 /* Attribute Controller Palette Register 2 */ +#define AR3 0x3 /* Attribute Controller Palette Register 3 */ +#define AR4 0x4 /* Attribute Controller Palette Register 4 */ +#define AR5 0x5 /* Attribute Controller Palette Register 5 */ +#define AR6 0x6 /* Attribute Controller Palette Register 6 */ +#define AR7 0x7 /* Attribute Controller Palette Register 7 */ +#define AR8 0x8 /* Attribute Controller Palette Register 8 */ +#define AR9 0x9 /* Attribute Controller Palette Register 9 */ +#define ARA 0xa /* Attribute Controller Palette Register 10 */ +#define ARB 0xb /* Attribute Controller Palette Register 11 */ +#define ARC 0xc /* Attribute Controller Palette Register 12 */ +#define ARD 0xd /* Attribute Controller Palette Register 13 */ +#define ARE 0xe /* Attribute Controller Palette Register 14 */ +#define ARF 0xf /* Attribute Controller Palette Register 15 */ +#define AR10 0x10 /* Attribute Controller Mode Register */ +#define AR11 0x11 /* Overscan (Border) Color Register */ +#define AR12 0x12 /* Color Plane Enable Register */ +#define AR13 0x13 /* Pixel Panning Register */ +#define AR14 0x14 /* Color Select Register */ +#define AR33 0x33 /* The "real" Pixel Panning register (?) */ +#define AR34 0x34 /* *TEST* */ + +/*** Extension Registers ***/ +#define HDR 0x3c6 /* Hidden DAC Register (Not CL-GD5420) */ + diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c new file mode 100644 index 000000000..466bf52ee --- /dev/null +++ b/drivers/video/controlfb.c @@ -0,0 +1,997 @@ +/* + * controlfb.c -- frame buffer device for the PowerMac 'control' display + * + * Created 12 July 1998 by Dan Jacobowitz <dan@debian.org> + * Copyright (C) 1998 Dan Jacobowitz + * + * Frame buffer structure from: + * drivers/video/chipsfb.c -- frame buffer device for + * Chips & Technologies 65550 chip. + * + * Copyright (C) 1998 Paul Mackerras + * + * This file is derived from the Powermac "chips" driver: + * Copyright (C) 1997 Fabio Riccardi. + * And from the frame buffer device for Open Firmware-initialized devices: + * Copyright (C) 1997 Geert Uytterhoeven. + * + * Hardware information from: + * control.c: Console support for PowerMac "control" display adaptor. + * Copyright (C) 1996 Paul Mackerras + * + * 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> +#ifdef CONFIG_FB_COMPAT_XPMAC +#include <asm/vc_ioctl.h> +#endif +#include <asm/io.h> +#include <asm/prom.h> +#include <asm/pgtable.h> +#include <asm/adb.h> +#include <asm/cuda.h> + +#include "fbcon.h" +#include "fbcon-cfb8.h" +#include "fbcon-cfb16.h" +#include "fbcon-cfb32.h" + +#include "macmodes.h" +#include "controlfb.h" + +static int currcon = 0; +static int switching = 0; + +struct fb_par_control { + int vmode, cmode; + int xres, yres; + int vxres, vyres; + int xoffset, yoffset; +}; + +struct fb_info_control { + struct fb_info info; + struct fb_fix_screeninfo fix; + struct fb_var_screeninfo var; + struct display disp; + struct fb_par_control par; + struct { + __u8 red, green, blue; + } palette[256]; + + struct cmap_regs *cmap_regs; + unsigned long cmap_regs_phys; + + struct control_regs *control_regs; + unsigned long control_regs_phys; + + __u8 *frame_buffer; + unsigned long frame_buffer_phys; + + int sense, control_use_bank2; + unsigned long total_vram; +}; + +/* + * Exported functions + */ +void control_init(void); +void control_of_init(struct device_node *dp); + +static int control_open(struct fb_info *info, int user); +static int control_release(struct fb_info *info, int user); +static int control_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int control_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int control_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int control_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int control_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int control_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int control_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info); + +static int read_control_sense(struct fb_info_control *p); +static inline int control_vram_reqd(int video_mode, int color_mode); +static void set_control_clock(unsigned char *params); +static void control_set_hardware(struct fb_info_control *p); +static void control_par_to_all(struct fb_info_control *p, int init); +static inline void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var); +static int control_var_to_par(struct fb_var_screeninfo *var, + struct fb_par_control *par, const struct fb_info *fb_info); + +static void control_init_info(struct fb_info *info, struct fb_info_control *p); +static void control_par_to_display(struct fb_par_control *par, + struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_control *p); +static void control_init_display(struct display *disp); +static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeninfo *fix, + struct fb_info_control *p); +static void control_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_control *p); + +static struct fb_ops controlfb_ops = { + control_open, + control_release, + control_get_fix, + control_get_var, + control_set_var, + control_get_cmap, + control_set_cmap, + control_pan_display, + control_ioctl +}; + +static int controlfb_getcolreg(u_int regno, u_int *red, u_int *green, + u_int *blue, u_int *transp, struct fb_info *info); +static int controlfb_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); + + +__openfirmware + + +static int control_open(struct fb_info *info, int user) +{ + MOD_INC_USE_COUNT; + return 0; +} + +static int control_release(struct fb_info *info, int user) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +static int control_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + struct fb_info_control *cp = (struct fb_info_control *) info; + + *fix = cp->fix; + return 0; +} + +static int control_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct fb_info_control *cp = (struct fb_info_control *) info; + + *var = cp->var; + return 0; +} + +/* Sets everything according to var */ +static int control_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct fb_info_control *p = (struct fb_info_control *) info; + struct display *disp; + struct fb_par_control par; + int depthchange, err; + + disp = (con >= 0) ? &fb_display[con] : &p->disp; + if((err = control_var_to_par(var, &par, info))) { + printk (KERN_ERR "Error in control_set_var, calling control_var_to_par: %d.\n", err); + return err; + } + + if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) { + printk("Not activating, in control_set_var.\n"); + control_par_to_var(&par, var); + return 0; + } +/* I know, we want to use fb_display[con], but grab certain info from p->var instead. */ +#define DIRTY(x) (p->var.x != var->x) + depthchange = DIRTY(bits_per_pixel); + if(!DIRTY(xres) && !DIRTY(yres) && !DIRTY(xres_virtual) && + !DIRTY(yres_virtual) && !DIRTY(bits_per_pixel)) { + control_par_to_var(&par, var); + p->var = disp->var = *var; + return 0; + } +printk("Original bpp is %d, new bpp %d.\n", p->var.bits_per_pixel, var->bits_per_pixel); + /* OK, we're getting here at the right times... */ + p->par = par; + control_par_to_var(&par, var); + p->var = *var; + control_par_to_fix(&par, &p->fix, p); + control_par_to_display(&par, disp, &p->fix, p); + p->disp = *disp; + + if(info->changevar && !switching) /* Don't want to do this if just switching consoles. */ + (*info->changevar)(con); + if(con == currcon) + control_set_hardware(p); + if(depthchange) + if((err = fb_alloc_cmap(&disp->cmap, 0, 0))) + return err; + if(depthchange || switching) + do_install_cmap(con, info); + return 0; +} + +static int control_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + if (var->xoffset != 0 || var->yoffset != 0) + return -EINVAL; + return 0; +} + +static int control_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, + controlfb_getcolreg, info); + if (fb_display[con].cmap.len) /* non default colormap? */ + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc? 0: 2); + else { + int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; + fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2); + } + return 0; +} + +static int control_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + struct display *disp = &fb_display[con]; + int err; + + if (disp->cmap.len == 0) { + int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; + err = fb_alloc_cmap(&disp->cmap, size, 0); + if (err) + return err; + } + + if (con == currcon) + return fb_set_cmap(cmap, &disp->var, kspc, controlfb_setcolreg, + info); + fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); + return 0; +} + +static int control_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info) +{ + return -EINVAL; +} + +static int controlfb_switch(int con, struct fb_info *info) +{ + if (fb_display[currcon].cmap.len) + fb_get_cmap(&fb_display[currcon].cmap, + &fb_display[currcon].var, 1, controlfb_getcolreg, + info); + currcon = con; +#if 0 + control_var_to_par(&fb_display[currcon].var, &par, info); + control_set_par(&par, info); /*STOPPEDHERE - did i define that? */ + do_install_cmap(con, info); +#else + /* I see no reason not to do this. Minus info->changevar(). */ + /* DOH. This makes control_set_var compare, you guessed it, */ + /* fb_display[con].var (first param), and fb_display[con].var! */ + /* Perhaps I just fixed that... */ + switching = 1; + control_set_var(&fb_display[con].var, con, info); + switching = 0; +#endif + return 0; +} + +static int controlfb_updatevar(int con, struct fb_info *info) +{ + return 0; +} + +static void controlfb_blank(int blank_mode, struct fb_info *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 + */ +/* [danj] I think there's something fishy about those constants... */ + struct fb_info_control *p = (struct fb_info_control *) info; + int ctrl; + + ctrl = ld_le32(&p->control_regs->ctrl.r) | 0x33; + if (blank_mode) + --blank_mode; + if (blank_mode & VESA_VSYNC_SUSPEND) + ctrl &= ~3; + if (blank_mode & VESA_HSYNC_SUSPEND) + ctrl &= ~0x30; + out_le32(&p->control_regs->ctrl.r, ctrl); + +/* TODO: Figure out how the heck to powerdown this thing! */ + + return; +} + +static int controlfb_getcolreg(u_int regno, u_int *red, u_int *green, + u_int *blue, u_int *transp, struct fb_info *info) +{ + struct fb_info_control *p = (struct fb_info_control *) info; + + if (regno > 255) + return 1; + *red = p->palette[regno].red; + *green = p->palette[regno].green; + *blue = p->palette[regno].blue; + return 0; +} + +static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + struct fb_info_control *p = (struct fb_info_control *) info; + + if (regno > 255 || regno < 0) + return 1; + p->palette[regno].red = red; + p->palette[regno].green = green; + p->palette[regno].blue = blue; + + out_8(&p->cmap_regs->addr, regno); /* tell clut what addr to fill */ + out_8(&p->cmap_regs->lut, red); /* send one color channel at */ + out_8(&p->cmap_regs->lut, green); /* a time... */ + out_8(&p->cmap_regs->lut, blue); + + if(regno < 16) { +#if 0 +#ifdef FBCON_HAS_CFB16 + fbcon_cfb16_cmap[regno] = (red << 10) | (green << 5) | blue; +#endif +#ifdef FBCON_HAS_CFB32 + fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue; + /* I think. */ +#endif +#else +#ifdef FBCON_HAS_CFB16 + fbcon_cfb16_cmap[regno] = (regno << 10) | (regno << 5) | regno; +#endif +#ifdef FBCON_HAS_CFB32 + fbcon_cfb32_cmap[regno] = (regno << 24) | (regno << 16) | (regno << 8) | regno; + /* I think. */ +#endif +#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, + controlfb_setcolreg, info); + else { + int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; + fb_set_cmap(fb_default_cmap(size), &fb_display[con].var, 1, + controlfb_setcolreg, info); + } +} + +#ifdef CONFIG_FB_COMPAT_XPMAC +extern struct vc_mode display_info; +extern struct fb_info *console_fb_info; +#if 0 +extern int (*console_setmode_ptr)(struct vc_mode *, int); +extern int (*console_set_cmap_ptr)(struct fb_cmap *, int, int, + struct fb_info *); +int console_setmode(struct vc_mode *, int); +#endif +#endif /* CONFIG_FB_COMPAT_XPMAC */ + +static inline int control_vram_reqd(int video_mode, int color_mode) +{ + return control_reg_init[video_mode-1]->vres + * control_reg_init[video_mode-1]->pitch[color_mode]; +} + +static void set_control_clock(unsigned char *params) +{ + struct adb_request req; + int i; + + for (i = 0; i < 3; ++i) { + cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC, + 0x50, i + 1, params[i]); + while (!req.complete) + cuda_poll(); + } +} + + +__initfunc(static void init_control(struct fb_info_control *p)) +{ + struct fb_par_control *par = &p->par; + + p->sense = read_control_sense(p); + printk("Monitor sense value = 0x%x, ", p->sense); + /* Try to pick a video mode out of NVRAM if we have one. */ + par->vmode = nvram_read_byte(NV_VMODE); + if(par->vmode <= 0 || par->vmode > VMODE_MAX || !control_reg_init[par->vmode - 1]) + par->vmode = VMODE_CHOOSE; + if(par->vmode == VMODE_CHOOSE) + par->vmode = mac_map_monitor_sense(p->sense); + if(!control_reg_init[par->vmode - 1]) + par->vmode = VMODE_640_480_60; + + par->cmode = nvram_read_byte(NV_CMODE); + if(par->cmode < CMODE_8 || par->cmode > CMODE_32) + par->cmode = CMODE_8; + /* + * Reduce the pixel size if we don't have enough VRAM. + */ + while(par->cmode > CMODE_8 && control_vram_reqd(par->vmode, par->cmode) > p->total_vram) + par->cmode--; + + printk("using video mode %d and color mode %d.\n", par->vmode, par->cmode); + + par->vxres = par->xres = control_reg_init[par->vmode - 1]->hres; + par->vyres = par->yres = control_reg_init[par->vmode - 1]->vres; + par->xoffset = par->yoffset = 0; + + control_par_to_all(p, 1); + + if (register_framebuffer(&p->info) < 0) { + kfree(p); + return; + } + control_set_hardware(p); + + printk("fb%d: control display adapter\n", GET_FB_IDX(p->info.node)); +} + +/* Now how about actually saying, Make it so! */ +/* Some things in here probably don't need to be done each time. */ +static void control_set_hardware(struct fb_info_control *p) +{ + struct control_regvals *init; + struct preg *rp; + int flags, ctrl, i; + int vmode, cmode; + + vmode = p->par.vmode; + cmode = p->par.cmode; + + init = control_reg_init[vmode - 1]; + + if (control_vram_reqd(vmode, cmode) > 0x200000) + flags = 0x51; + else if (p->control_use_bank2) + flags = 0x39; + else + flags = 0x31; + if (vmode >= VMODE_1280_960_75 && cmode >= CMODE_16) + ctrl = 0x7f; + else + ctrl = 0x3b; + + /* Initialize display timing registers */ + out_le32(&p->control_regs->ctrl.r, 0x43b); + + set_control_clock(init->clock_params); + + p->cmap_regs->addr = 0x20; p->cmap_regs->d2 = init->radacal_ctrl[cmode]; + p->cmap_regs->addr = 0x21; p->cmap_regs->d2 = p->control_use_bank2 ? 0: 1; + p->cmap_regs->addr = 0x10; p->cmap_regs->d2 = 0; + p->cmap_regs->addr = 0x11; p->cmap_regs->d2 = 0; + + rp = &p->control_regs->vswin; + for (i = 0; i < 16; ++i, ++rp) + out_le32(&rp->r, init->regs[i]); + + out_le32(&p->control_regs->pitch.r, init->pitch[cmode]); + out_le32(&p->control_regs->mode.r, init->mode[cmode]); + out_le32(&p->control_regs->flags.r, flags); + out_le32(&p->control_regs->start_addr.r, 0); + out_le32(&p->control_regs->reg18.r, 0x1e5); + out_le32(&p->control_regs->reg19.r, 0); + + for (i = 0; i < 16; ++i) { + controlfb_setcolreg(color_table[i], default_red[i], default_grn[i], + default_blu[i], 0, (struct fb_info *)p); + } +/* Does the above need to be here each time? -- danj */ + + /* Turn on display */ + out_le32(&p->control_regs->ctrl.r, ctrl); + +#ifdef CONFIG_FB_COMPAT_XPMAC + /* And let the world know the truth. */ + if (!console_fb_info || console_fb_info == &p->info) { + display_info.height = p->var.yres; + display_info.width = p->var.xres; + display_info.depth = (cmode == CMODE_32) ? 32 : + ((cmode == CMODE_16) ? 16 : 8); + display_info.pitch = p->fix.line_length; + display_info.mode = vmode; + strncpy(display_info.name, "control", + sizeof(display_info.name)); + display_info.fb_address = p->frame_buffer_phys + + control_reg_init[vmode-1]->offset[cmode]; + display_info.cmap_adr_address = p->cmap_regs_phys; + display_info.cmap_data_address = p->cmap_regs_phys + 0x30; + display_info.disp_reg_address = p->control_regs_phys; + console_fb_info = &p->info; + } +#endif /* CONFIG_FB_COMPAT_XPMAC */ +} + +__initfunc(void control_init(void)) +{ +#ifndef CONFIG_FB_OF + struct device_node *dp; + + dp = find_devices("control"); + if (dp != 0) + control_of_init(dp); +#endif /* CONFIG_FB_OF */ +} + +__initfunc(void control_of_init(struct device_node *dp)) +{ + struct fb_info_control *p; + unsigned long addr, size; + int i, bank1, bank2; + + if(dp->next != 0) + printk("Warning: only using first control display device.\n"); + /* danj: I have a feeling this no longer applies - if we somehow * + * had two of them, they'd be two framebuffers, right? */ + if(dp->n_addrs != 2) + panic("expecting 2 address for control (got %d)", dp->n_addrs); + p = kmalloc(sizeof(*p), GFP_ATOMIC); + if (p == 0) + return; + + /* Map in frame buffer and registers */ + for (i = 0; i < dp->n_addrs; ++i) { + addr = dp->addrs[i].address; + size = dp->addrs[i].size; + if (size >= 0x800000) { + /* use the big-endian aperture (??) */ + addr += 0x800000; + /* map at most 8MB for the frame buffer */ + p->frame_buffer_phys = addr; + p->frame_buffer = __ioremap(addr, 0x800000, _PAGE_WRITETHRU); + } else { + p->control_regs_phys = addr; + p->control_regs = ioremap(addr, size); + } + } + p->cmap_regs_phys = 0xf301b000; /* XXX not in prom? */ + p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000); + + /* Work out which banks of VRAM we have installed. */ + /* danj: I guess the card just ignores writes to nonexistant VRAM... */ + p->frame_buffer[0] = 0x5a; + p->frame_buffer[1] = 0xc7; + bank1 = p->frame_buffer[0] == 0x5a && p->frame_buffer[1] == 0xc7; + p->frame_buffer[0x600000] = 0xa5; + p->frame_buffer[0x600001] = 0x38; + bank2 = p->frame_buffer[0x600000] == 0xa5 && p->frame_buffer[0x600001] == 0x38; + p->total_vram = (bank1 + bank2) * 0x200000; + /* If we don't have bank 1 installed, we hope we have bank 2 :-) */ + p->control_use_bank2 = !bank1; + if (p->control_use_bank2) + p->frame_buffer += 0x600000; + +#ifdef CONFIG_FB_COMPAT_XPMAC +#if 0 + console_set_cmap_ptr = control_set_cmap; + console_setmode_ptr = control_console_setmode; +#endif +#endif /* CONFIG_FB_COMPAT_XPMAC */ + + init_control(p); +} + +/* + * Get the monitor sense value. + * Note that this can be called before calibrate_delay, + * so we can't use udelay. + * + * Hmm - looking at platinum, should we be calling eieio() here? + */ +static int read_control_sense(struct fb_info_control *p) +{ + int sense; + + out_le32(&p->control_regs->mon_sense.r, 7); /* drive all lines high */ + __delay(200); + out_le32(&p->control_regs->mon_sense.r, 077); /* turn off drivers */ + __delay(2000); + sense = (in_le32(&p->control_regs->mon_sense.r) & 0x1c0) << 2; + + /* drive each sense line low in turn and collect the other 2 */ + out_le32(&p->control_regs->mon_sense.r, 033); /* drive A low */ + __delay(2000); + sense |= (in_le32(&p->control_regs->mon_sense.r) & 0xc0) >> 2; + out_le32(&p->control_regs->mon_sense.r, 055); /* drive B low */ + __delay(2000); + sense |= ((in_le32(&p->control_regs->mon_sense.r) & 0x100) >> 5) + | ((in_le32(&p->control_regs->mon_sense.r) & 0x40) >> 4); + out_le32(&p->control_regs->mon_sense.r, 066); /* drive C low */ + __delay(2000); + sense |= (in_le32(&p->control_regs->mon_sense.r) & 0x180) >> 7; + + out_le32(&p->control_regs->mon_sense.r, 077); /* turn off drivers */ + + return sense; +} + +#if 1 +/* This routine takes a user-supplied var, and picks the best vmode/cmode from it. */ +static int control_var_to_par(struct fb_var_screeninfo *var, + struct fb_par_control *par, const struct fb_info *fb_info) +{ + int xres = var->xres; + int yres = var->yres; + int bpp = var->bits_per_pixel; + + struct control_regvals *init; + struct fb_info_control *p = (struct fb_info_control *) 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. + */ + /* swiped by jonh from atyfb.c */ + 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 = control_reg_init[par->vmode-1]->hres; + yres = control_reg_init[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; +*/ + + /* I'm too chicken to think about virtual */ + /* resolutions just yet. Bok bok. */ + + /* And I'm too chicken to even figure out what they are. Awk awk. [danj] */ + if (var->xres_virtual > xres || var->yres_virtual > yres + || var->xoffset != 0 || var->yoffset != 0) { + return -EINVAL; + } + + par->xres = xres; + par->yres = yres; + par->vxres = xres; + par->vyres = yres; + par->xoffset = 0; + par->yoffset = 0; + + 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 (control_vram_reqd(par->vmode, par->cmode) > p->total_vram) + return -EINVAL; + + /* Check if we know about the wanted video mode */ + init = control_reg_init[par->vmode-1]; + if (init == NULL) { + /* I'm not sure if control has any specific requirements -- */ + /* if we have a regvals struct, we're good to go? */ + return -EINVAL; + } + + return 0; +} +#else +/* This routine takes a user-supplied var, and picks the best vmode/cmode from it. */ +static int control_var_to_par(struct fb_var_screeninfo *var, + struct fb_par_control *par, const struct fb_info *fb_info) +{ + struct fb_info_control *p = (struct fb_info_control *) fb_info; + + if(mac_var_to_vmode(var, &par->vmode, &par->cmode) != 0) + return -EINVAL; + par->xres = par->vxres = vmode_attrs[par->vmode - 1].hres; + par->yres = par->vyres = vmode_attrs[par->vmode - 1].vres; + par->xoffset = par->yoffset = 0; + + if (control_vram_reqd(par->vmode, par->cmode) > p->total_vram) + return -EINVAL; + + /* Check if we know about the wanted video mode */ + if(!control_reg_init[par->vmode-1]) { + /* I'm not sure if control has any specific requirements -- */ + /* if we have a regvals struct, we're good to go? */ + return -EINVAL; + } + return 0; +} +#endif + +#if 1 +static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var) +{ + memset(var, 0, sizeof(*var)); + var->xres = control_reg_init[par->vmode - 1]->hres; + var->yres = control_reg_init[par->vmode - 1]->vres; + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; /* For now. */ + var->xoffset = par->xoffset; + var->yoffset = par->yoffset; + var->grayscale = 0; + + if(par->cmode != CMODE_8 && par->cmode != CMODE_16 && par->cmode != CMODE_32) { + printk(KERN_ERR "Bad color mode in control_par_to_var()!\n"); + par->cmode = CMODE_8; + } + 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->vmode = FB_VMODE_NONINTERLACED; + + /* these are total guesses, copied right out of atyfb.c */ + var->left_margin = var->right_margin = 64; + var->upper_margin = var->lower_margin = 32; + var->hsync_len = /*64*/8; + var->vsync_len = /*2*/8; + var->sync = 0; + +#if 0 +/* jonh's pixclocks...*/ + /* 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); +#else +/* danj's */ + /* 10^12 * clock_params[0] / (3906400 * clock_params[1] * 2^clock_params[2]) */ + /* (10^12 * clock_params[0] / (3906400 * clock_params[1])) >> clock_params[2] */ + /* (255990.17 * clock_params[0] / clock_params[1]) >> clock_params[2] */ + var->pixclock = 255990 * control_reg_init[par->vmode-1]->clock_params[0]; + var->pixclock /= control_reg_init[par->vmode-1]->clock_params[1]; + var->pixclock >>= control_reg_init[par->vmode-1]->clock_params[2]; +#endif +} +#else +static inline void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var) +{ + mac_vmode_to_var(par->vmode, par->cmode, var); +} +#endif + +static void control_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_control *p) +{ + memset(fix, 0, sizeof(*fix)); + strcpy(fix->id, "control"); + fix->mmio_start = (char *)p->control_regs_phys; + fix->mmio_len = sizeof(struct control_regs); + fix->type = FB_TYPE_PACKED_PIXELS; + + /* + fix->type_aux = 0; + fix->ywrapstep = 0; + fix->ypanstep = 0; + fix->xpanstep = 0; + */ +} + +/* Fix must already be inited ^^^^^^^ */ +static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeninfo *fix, + struct fb_info_control *p) +{ + fix->smem_start = (void *)(p->frame_buffer_phys + + control_reg_init[par->vmode-1]->offset[par->cmode]); + p->fix.smem_len = control_vram_reqd(par->vmode, par->cmode); + /* Hmm, jonh used total_vram here. */ + p->fix.visual = (par->cmode == CMODE_8) ? + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; + p->fix.line_length = par->vxres << par->cmode; + /* ywrapstep, xpanstep, ypanstep */ +} + +static void control_init_display(struct display *disp) +{ + memset(disp, 0, sizeof(*disp)); + disp->type = /* fix->type */ FB_TYPE_PACKED_PIXELS; + disp->can_soft_blank = 1; + disp->scrollmode = SCROLL_YREDRAW; +#if 0 + disp->type_aux = fix->type_aux; + disp->cmap.red = NULL; /* ??? danj */ + disp->cmap.green = NULL; + disp->cmap.blue = NULL; + disp->cmap.transp = NULL; + /* Yeah, I realize I just set 0 = 0. */ +#endif +} + +static void control_par_to_display(struct fb_par_control *par, + struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_control *p) +{ + disp->var = p->var; + disp->screen_base = (char *) p->frame_buffer + + control_reg_init[par->vmode-1]->offset[par->cmode]; + disp->visual = fix->visual; + disp->line_length = fix->line_length; + +if(disp->scrollmode != SCROLL_YREDRAW) { + printk(KERN_ERR "Scroll mode not YREDRAW in control_par_to_display!!\n"); + disp->scrollmode = SCROLL_YREDRAW; +} + disp->dispsw = (par->cmode == CMODE_32) ? &fbcon_cfb32 : + ((par->cmode == CMODE_16) ? &fbcon_cfb16 : &fbcon_cfb8); +} + +static void control_init_info(struct fb_info *info, struct fb_info_control *p) +{ + strcpy(info->modename, p->fix.id); + info->node = -1; /* ??? danj */ + info->fbops = &controlfb_ops; + info->disp = &p->disp; + info->fontname[0] = 0; + info->changevar = NULL; + info->switch_con = &controlfb_switch; + info->updatevar = &controlfb_updatevar; + info->blank = &controlfb_blank; +} + +/* danj: Oh, I HOPE I didn't miss anything major in here... */ +static void control_par_to_all(struct fb_info_control *p, int init) +{ + if(init) { + control_init_fix(&p->fix, p); + } + control_par_to_fix(&p->par, &p->fix, p); + + control_par_to_var(&p->par, &p->var); + + if(init) { + control_init_display(&p->disp); + } + control_par_to_display(&p->par, &p->disp, &p->fix, p); + + if(init) { + control_init_info(&p->info, p); + } +} + +#if 0 +__initfunc(void controlfb_setup(char *options, int *ints)) +{ + /* Parse user speficied options (`video=controlfb:') */ + FUNCID; +} + +static int controlfb_pan_display(struct fb_var_screeninfo *var, + struct controlfb_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. + */ + + FUNCID; + + return 0; +} + +#endif diff --git a/drivers/video/controlfb.h b/drivers/video/controlfb.h new file mode 100644 index 000000000..2e138b7c7 --- /dev/null +++ b/drivers/video/controlfb.h @@ -0,0 +1,262 @@ +/* + * controlfb_hw.h: Constants of all sorts for controlfb + * + * Copyright (C) 1998 Daniel Jacobowitz <dan@debian.org> + * + * 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. + * + * Based on an awful lot of code, including: + * + * control.c: Console support for PowerMac "control" display adaptor. + * Copyright (C) 1996 Paul Mackerras. + * + * The so far unpublished platinumfb.c + * Copyright (C) 1998 Jon Howell + */ + +/* + * Structure of the registers for the RADACAL colormap device. + */ +struct cmap_regs { + unsigned char addr; + char pad1[15]; + unsigned char d1; + char pad2[15]; + unsigned char d2; + char pad3[15]; + unsigned char lut; + char pad4[15]; +}; + +/* + * Structure of the registers for the "control" display adaptor. + */ +#define PAD(x) char x[12] + +struct preg { /* padded register */ + unsigned r; + char pad[12]; +}; + +struct control_regs { + struct preg vcount; /* vertical counter */ + /* Vertical parameters are in units of 1/2 scan line */ + struct preg vswin; /* between vsblank and vssync */ + struct preg vsblank; /* vert start blank */ + struct preg veblank; /* vert end blank (display start) */ + struct preg vewin; /* between vesync and veblank */ + struct preg vesync; /* vert end sync */ + struct preg vssync; /* vert start sync */ + struct preg vperiod; /* vert period */ + struct preg reg8; + /* Horizontal params are in units of 2 pixels */ + struct preg hperiod; /* horiz period - 2 */ + struct preg hsblank; /* horiz start blank */ + struct preg heblank; /* horiz end blank */ + struct preg hesync; /* horiz end sync */ + struct preg hssync; /* horiz start sync */ + struct preg rege; + struct preg regf; + struct preg reg10; + struct preg reg11; + struct preg ctrl; /* display control */ + struct preg start_addr; /* start address: 5 lsbs zero */ + struct preg pitch; /* addrs diff between scan lines */ + struct preg mon_sense; /* monitor sense bits */ + struct preg flags; + struct preg mode; + struct preg reg18; + struct preg reg19; + struct preg res[6]; +}; + +/* + * Register initialization tables for the control display. + * + * Dot clock rate is + * 3.9064MHz * 2**clock_params[2] * clock_params[1] / clock_params[0]. + * + * The values for vertical frequency (V) in the comments below + * are the values measured using the modes under MacOS. + */ +struct control_regvals { + int pitch[3]; /* bytes/line, indexed by color_mode */ + int offset[3]; /* first pixel address */ + unsigned regs[16]; /* for vswin .. reg10 */ + unsigned char mode[3]; /* indexed by color_mode */ + unsigned char radacal_ctrl[3]; + unsigned char clock_params[3]; + int hres; + int vres; +}; + +/* Register values for 1280x1024, 75Hz mode (20) */ +static struct control_regvals control_reg_init_20 = { + { 1280, 2560, 0 }, + { 0x10, 0x20, 0 }, + { 2129, 2128, 80, 42, 4, 2130, 2132, 88, + 420, 411, 91, 35, 421, 18, 211, 386, }, + { 1, 1, 1}, + { 0x50, 0x64, 0x64 }, + { 13, 56, 3 }, /* pixel clock = 134.61MHz for V=74.81Hz */ + 1280, 1024 +}; + +/* Register values for 1280x960, 75Hz mode (19) */ +static struct control_regvals control_reg_init_19 = { + { 1280, 2560, 0 }, + { 0x10, 0x20, 0 }, + { 1997, 1996, 76, 40, 4, 1998, 2000, 86, + 418, 409, 89, 35, 419, 18, 210, 384, }, + { 1, 1, 1 }, + { 0x50, 0x64, 0x64 }, + { 31, 125, 3 }, /* pixel clock = 126.01MHz for V=75.01 Hz */ + 1280, 960 +}; + +/* Register values for 1152x870, 75Hz mode (18) */ +static struct control_regvals control_reg_init_18 = { + { 1152, 2304, 4608 }, + { 0x10, 0x28, 0x50 }, + { 1825, 1822, 82, 43, 4, 1828, 1830, 120, + 726, 705, 129, 63, 727, 32, 364, 664 }, + { 2, 1, 1 }, + { 0x10, 0x14, 0x28 }, + { 19, 61, 3 }, /* pixel clock = 100.33MHz for V=75.31Hz */ + 1152, 870 +}; + +/* Register values for 1024x768, 75Hz mode (17) */ +static struct control_regvals control_reg_init_17 = { + { 1024, 2048, 4096 }, + { 0x10, 0x28, 0x50 }, + { 1603, 1600, 64, 34, 4, 1606, 1608, 120, + 662, 641, 129, 47, 663, 24, 332, 616 }, + { 2, 1, 1 }, + { 0x10, 0x14, 0x28 }, + { 11, 28, 3 }, /* pixel clock = 79.55MHz for V=74.50Hz */ + 1024, 768 +}; + +/* Register values for 1024x768, 72Hz mode (15) */ +static struct control_regvals control_reg_init_15 = { + { 1024, 2048, 4096 }, + { 0x10, 0x28, 0x50 }, + { 1607, 1604, 68, 39, 10, 1610, 1612, 132, + 670, 653, 141, 67, 671, 34, 336, 604, }, + { 2, 1, 1 }, + { 0x10, 0x14, 0x28 }, + { 12, 30, 3 }, /* pixel clock = 78.12MHz for V=72.12Hz */ + 1024, 768 +}; + +/* Register values for 1024x768, 60Hz mode (14) */ +static struct control_regvals control_reg_init_14 = { + { 1024, 2048, 4096 }, + { 0x10, 0x28, 0x50 }, + { 1607, 1604, 68, 39, 10, 1610, 1612, 132, + 670, 653, 141, 67, 671, 34, 336, 604, }, + { 2, 1, 1 }, + { 0x10, 0x14, 0x28 }, + { 15, 31, 3 }, /* pixel clock = 64.58MHz for V=59.62Hz */ + 1024, 768 +}; + +/* Register values for 832x624, 75Hz mode (13) */ +static struct control_regvals control_reg_init_13 = { + { 832, 1664, 3328 }, + { 0x10, 0x28, 0x50 }, + { 1331, 1330, 82, 43, 4, 1332, 1334, 128, + 574, 553, 137, 31, 575, 16, 288, 544 }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 23, 42, 3 }, /* pixel clock = 57.07MHz for V=74.27Hz */ + 832, 624 +}; + +/* Register values for 800x600, 75Hz mode (12) */ +static struct control_regvals control_reg_init_12 = { + { 800, 1600, 3200 }, + { 0x10, 0x28, 0x50 }, + { 1247, 1246, 46, 25, 4, 1248, 1250, 104, + 526, 513, 113, 39, 527, 20, 264, 488, }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 7, 11, 3 }, /* pixel clock = 49.11MHz for V=74.40Hz */ + 800, 600 +}; + +/* Register values for 800x600, 72Hz mode (11) */ +static struct control_regvals control_reg_init_11 = { + { 800, 1600, 3200 }, + { 0x10, 0x28, 0x50 }, + { 1293, 1256, 56, 33, 10, 1330, 1332, 76, + 518, 485, 85, 59, 519, 30, 260, 460, }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 17, 27, 3 }, /* pixel clock = 49.63MHz for V=71.66Hz */ + 800, 600 +}; + +/* Register values for 800x600, 60Hz mode (10) */ +static struct control_regvals control_reg_init_10 = { + { 800, 1600, 3200 }, + { 0x10, 0x28, 0x50 }, + { 1293, 1256, 56, 33, 10, 1330, 1332, 76, + 518, 485, 85, 59, 519, 30, 260, 460, }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 20, 53, 2 }, /* pixel clock = 41.41MHz for V=59.78Hz */ + 800, 600 +}; + +/* Register values for 640x870, 75Hz Full Page Display (7) */ +static struct control_regvals control_reg_init_7 = { + { 640, 1280, 2560 }, + { 0x10, 0x30, 0x68 }, + { 0x727, 0x724, 0x58, 0x2e, 0x4, 0x72a, 0x72c, 0x40, + 0x19e, 0x18c, 0x4c, 0x27, 0x19f, 0x14, 0xd0, 0x178 }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 9, 33, 2 }, /* pixel clock = 57.29MHz for V=75.01Hz */ + 640, 870 +}; + +/* Register values for 640x480, 67Hz mode (6) */ +static struct control_regvals control_reg_init_6 = { + { 640, 1280, 2560 }, + { 0, 8, 0x10 }, + { 1045, 1042, 82, 43, 4, 1048, 1050, 72, + 430, 393, 73, 31, 431, 16, 216, 400 }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 14, 27, 2 }, /* pixel clock = 30.13MHz for V=66.43Hz */ + 640, 480 +}; + +/* Register values for 640x480, 60Hz mode (5) */ +static struct control_regvals control_reg_init_5 = { + { 640, 1280, 2560 }, + { 0x10, 0x28, 0x50 }, + { 1037, 1026, 66, 34, 2, 1048, 1050, 56, + 398, 385, 65, 47, 399, 24, 200, 352, }, + { 2, 1, 0 }, { 0x10, 0x14, 0x18 }, + { 23, 37, 2 }, /* pixel clock = 25.14MHz for V=59.85Hz */ + 640, 480 +}; + +static struct control_regvals *control_reg_init[VMODE_MAX] = { + NULL, NULL, NULL, NULL, + &control_reg_init_5, + &control_reg_init_6, + &control_reg_init_7, + NULL, NULL, + &control_reg_init_10, + &control_reg_init_11, + &control_reg_init_12, + &control_reg_init_13, + &control_reg_init_14, + &control_reg_init_15, + NULL, + &control_reg_init_17, + &control_reg_init_18, + &control_reg_init_19, + &control_reg_init_20 +}; diff --git a/drivers/video/creatorfb.c b/drivers/video/creatorfb.c new file mode 100644 index 000000000..2175c9e5d --- /dev/null +++ b/drivers/video/creatorfb.c @@ -0,0 +1,537 @@ +/* $Id: creatorfb.c,v 1.10 1998/07/25 22:54:37 davem Exp $ + * creatorfb.c: Creator/Creator3D frame buffer driver + * + * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/sched.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 <linux/selection.h> + +#include "sbusfb.h" + +#define FFB_SFB8R_VOFF 0x00000000 +#define FFB_SFB8G_VOFF 0x00400000 +#define FFB_SFB8B_VOFF 0x00800000 +#define FFB_SFB8X_VOFF 0x00c00000 +#define FFB_SFB32_VOFF 0x01000000 +#define FFB_SFB64_VOFF 0x02000000 +#define FFB_FBC_REGS_VOFF 0x04000000 +#define FFB_BM_FBC_REGS_VOFF 0x04002000 +#define FFB_DFB8R_VOFF 0x04004000 +#define FFB_DFB8G_VOFF 0x04404000 +#define FFB_DFB8B_VOFF 0x04804000 +#define FFB_DFB8X_VOFF 0x04c04000 +#define FFB_DFB24_VOFF 0x05004000 +#define FFB_DFB32_VOFF 0x06004000 +#define FFB_DFB422A_VOFF 0x07004000 /* DFB 422 mode write to A */ +#define FFB_DFB422AD_VOFF 0x07804000 /* DFB 422 mode with line doubling */ +#define FFB_DFB24B_VOFF 0x08004000 /* DFB 24bit mode write to B */ +#define FFB_DFB422B_VOFF 0x09004000 /* DFB 422 mode write to B */ +#define FFB_DFB422BD_VOFF 0x09804000 /* DFB 422 mode with line doubling */ +#define FFB_SFB16Z_VOFF 0x0a004000 /* 16bit mode Z planes */ +#define FFB_SFB8Z_VOFF 0x0a404000 /* 8bit mode Z planes */ +#define FFB_SFB422_VOFF 0x0ac04000 /* SFB 422 mode write to A/B */ +#define FFB_SFB422D_VOFF 0x0b404000 /* SFB 422 mode with line doubling */ +#define FFB_FBC_KREGS_VOFF 0x0bc04000 +#define FFB_DAC_VOFF 0x0bc06000 +#define FFB_PROM_VOFF 0x0bc08000 +#define FFB_EXP_VOFF 0x0bc18000 + +#define FFB_SFB8R_POFF 0x04000000 +#define FFB_SFB8G_POFF 0x04400000 +#define FFB_SFB8B_POFF 0x04800000 +#define FFB_SFB8X_POFF 0x04c00000 +#define FFB_SFB32_POFF 0x05000000 +#define FFB_SFB64_POFF 0x06000000 +#define FFB_FBC_REGS_POFF 0x00600000 +#define FFB_BM_FBC_REGS_POFF 0x00600000 +#define FFB_DFB8R_POFF 0x01000000 +#define FFB_DFB8G_POFF 0x01400000 +#define FFB_DFB8B_POFF 0x01800000 +#define FFB_DFB8X_POFF 0x01c00000 +#define FFB_DFB24_POFF 0x02000000 +#define FFB_DFB32_POFF 0x03000000 +#define FFB_FBC_KREGS_POFF 0x00610000 +#define FFB_DAC_POFF 0x00400000 +#define FFB_PROM_POFF 0x00000000 +#define FFB_EXP_POFF 0x00200000 + +#define FFB_Y_BYTE_ADDR_SHIFT 11 +#define FFB_Y_ADDR_SHIFT 13 + +#define FFB_PPC_ACE_DISABLE 1 +#define FFB_PPC_ACE_AUX_ADD 3 +#define FFB_PPC_ACE_SHIFT 18 +#define FFB_PPC_DCE_DISABLE 2 +#define FFB_PPC_DCE_SHIFT 16 +#define FFB_PPC_ABE_DISABLE 2 +#define FFB_PPC_ABE_SHIFT 14 +#define FFB_PPC_VCE_DISABLE 1 +#define FFB_PPC_VCE_2D 2 +#define FFB_PPC_VCE_SHIFT 12 +#define FFB_PPC_APE_DISABLE 2 +#define FFB_PPC_APE_SHIFT 10 +#define FFB_PPC_CS_VARIABLE 2 +#define FFB_PPC_CS_SHIFT 0 + +#define FFB_FBC_WB_A 1 +#define FFB_FBC_WB_SHIFT 29 +#define FFB_FBC_PGE_MASK 3 +#define FFB_FBC_BE_SHIFT 4 +#define FFB_FBC_GE_SHIFT 2 +#define FFB_FBC_RE_SHIFT 0 + +#define FFB_ROP_NEW 0x83 +#define FFB_ROP_RGB_SHIFT 0 + +#define FFB_UCSR_FIFO_MASK 0x00000fff +#define FFB_UCSR_RP_BUSY 0x02000000 + +struct ffb_fbc { + u8 xxx1[0x60]; + volatile u32 by; + volatile u32 bx; + u32 xxx2; + u32 xxx3; + volatile u32 bh; + volatile u32 bw; + u8 xxx4[0x188]; + volatile u32 ppc; + u32 xxx5; + volatile u32 fg; + volatile u32 bg; + u8 xxx6[0x44]; + volatile u32 fbc; + volatile u32 rop; + u8 xxx7[0x34]; + volatile u32 pmask; + u8 xxx8[12]; + volatile u32 clip0min; + volatile u32 clip0max; + volatile u32 clip1min; + volatile u32 clip1max; + volatile u32 clip2min; + volatile u32 clip2max; + volatile u32 clip3min; + volatile u32 clip3max; + u8 xxx9[0x3c]; + volatile u32 unk1; + volatile u32 unk2; + u8 xxx10[0x10]; + volatile u32 fontxy; + volatile u32 fontw; + volatile u32 fontinc; + volatile u32 font; + u8 xxx11[0x4dc]; + volatile u32 unk3; + u8 xxx12[0xfc]; + volatile u32 ucsr; +}; + +struct ffb_dac { + volatile u32 type; + volatile u32 value; + volatile u32 type2; + volatile u32 value2; +}; + +static struct sbus_mmap_map ffb_mmap_map[] = { + { FFB_SFB8R_VOFF, FFB_SFB8R_POFF, 0x0400000 }, + { FFB_SFB8G_VOFF, FFB_SFB8G_POFF, 0x0400000 }, + { FFB_SFB8B_VOFF, FFB_SFB8B_POFF, 0x0400000 }, + { FFB_SFB8X_VOFF, FFB_SFB8X_POFF, 0x0400000 }, + { FFB_SFB32_VOFF, FFB_SFB32_POFF, 0x1000000 }, + { FFB_SFB64_VOFF, FFB_SFB64_POFF, 0x2000000 }, + { FFB_FBC_REGS_VOFF, FFB_FBC_REGS_POFF, 0x0002000 }, + { FFB_BM_FBC_REGS_VOFF, FFB_BM_FBC_REGS_POFF, 0x0002000 }, + { FFB_DFB8R_VOFF, FFB_DFB8R_POFF, 0x0400000 }, + { FFB_DFB8G_VOFF, FFB_DFB8G_POFF, 0x0400000 }, + { FFB_DFB8B_VOFF, FFB_DFB8B_POFF, 0x0400000 }, + { FFB_DFB8X_VOFF, FFB_DFB8X_POFF, 0x0400000 }, + { FFB_DFB24_VOFF, FFB_DFB24_POFF, 0x1000000 }, + { FFB_DFB32_VOFF, FFB_DFB32_POFF, 0x1000000 }, + { FFB_FBC_KREGS_VOFF, FFB_FBC_KREGS_POFF, 0x0002000 }, + { FFB_DAC_VOFF, FFB_DAC_POFF, 0x0002000 }, + { FFB_PROM_VOFF, FFB_PROM_POFF, 0x0010000 }, + { FFB_EXP_VOFF, FFB_EXP_POFF, 0x0002000 }, + { 0, 0, 0 } +}; + +static u32 ffb_cmap[16]; + +static void ffb_setup(struct display *p) +{ + p->next_line = 8192; + p->next_plane = 0; +} + +static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx, + int height, int width) +{ + struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; + register struct ffb_fbc *fbc = fb->s.ffb.fbc; + int x, y, w, h; + + fbc->ppc = 0x1803; + fbc->fg = ffb_cmap[attr_bgcol_ec(p,conp)]; + fbc->fbc = 0x2000707f; + fbc->rop = 0x83; + fbc->pmask = 0xffffffff; + fbc->unk2 = 8; + + if (p->fontheightlog) { + y = sy << p->fontheightlog; h = height << p->fontheightlog; + } else { + y = sy * p->fontheight; h = height * p->fontheight; + } + if (p->fontwidthlog) { + x = sx << p->fontwidthlog; w = width << p->fontwidthlog; + } else { + x = sx * p->fontwidth; w = width * p->fontwidth; + } + fbc->by = y + fb->y_margin; + fbc->bx = x + fb->x_margin; + fbc->bh = h; + fbc->bw = w; +} + +static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s, + int count, unsigned short *boxes) +{ + register struct ffb_fbc *fbc = fb->s.ffb.fbc; + + fbc->ppc = 0x1803; + fbc->fg = ffb_cmap[attr_bgcol(p,s)]; + fbc->fbc = 0x2000707f; + fbc->rop = 0x83; + fbc->pmask = 0xffffffff; + fbc->unk2 = 8; + while (count-- > 0) { + fbc->by = boxes[1]; + fbc->bx = boxes[0]; + fbc->bh = boxes[3] - boxes[1]; + fbc->bw = boxes[2] - boxes[0]; + boxes += 4; + } +} + +static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) +{ + struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; + register struct ffb_fbc *fbc = fb->s.ffb.fbc; + int i, xy; + u8 *fd; + + if (p->fontheightlog) { + xy = (yy << (16 + p->fontheightlog)); + i = ((c & p->charmask) << p->fontheightlog); + } else { + xy = ((yy * p->fontheight) << 16); + i = (c & p->charmask) * p->fontheight; + } +#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY + fd = p->fontdata + i; + xy += (xx * 8) + fb->s.ffb.xy_margin; +#else + if (p->fontwidth <= 8) + fd = p->fontdata + i; + else + fd = p->fontdata + (i << 1); + if (p->fontwidthlog) + xy += (xx << p->fontwidthlog) + fb->s.ffb.xy_margin; + else + xy += (xx * p->fontwidth) + fb->s.ffb.xy_margin; +#endif + fbc->ppc = 0x203; + fbc->fg = ffb_cmap[attr_fgcol(p,c)]; + fbc->fbc = 0x2000707f; + fbc->rop = 0x83; + fbc->pmask = 0xffffffff; + fbc->bg = ffb_cmap[attr_bgcol(p,c)]; + fbc->fontw = p->fontwidth; + fbc->fontinc = 0x10000; + fbc->fontxy = xy; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth <= 8) { +#endif + for (i = 0; i < p->fontheight; i++) + fbc->font = *fd++ << 24; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + } else { + for (i = 0; i < p->fontheight; i++) { + fbc->font = *(u16 *)fd << 16; + fd += 2; + } + } +#endif +} + +static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, + int count, int yy, int xx) +{ + struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; + register struct ffb_fbc *fbc = fb->s.ffb.fbc; + int i, xy; + u8 *fd1, *fd2, *fd3, *fd4; + + fbc->ppc = 0x203; + fbc->fg = ffb_cmap[attr_fgcol(p,*s)]; + fbc->fbc = 0x2000707f; + fbc->rop = 0x83; + fbc->pmask = 0xffffffff; + fbc->bg = ffb_cmap[attr_bgcol(p,*s)]; + xy = fb->s.ffb.xy_margin; +#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY + xy += xx * 8; +#else + if (p->fontwidthlog) + xy += (xx << p->fontwidthlog); + else + xy += xx * p->fontwidth; +#endif + if (p->fontheightlog) + xy += (yy << (16 + p->fontheightlog)); + else + xy += ((yy * p->fontheight) << 16); +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth <= 8) { +#endif + while (count >= 4) { + count -= 4; + fbc->fontw = 4 * p->fontwidth; + fbc->fontinc = 0x10000; + fbc->fontxy = xy; + if (p->fontheightlog) { + fd1 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog); + fd2 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog); + fd3 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog); + fd4 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog); + } else { + fd1 = p->fontdata + ((*s++ & p->charmask) * p->fontheight); + fd2 = p->fontdata + ((*s++ & p->charmask) * p->fontheight); + fd3 = p->fontdata + ((*s++ & p->charmask) * p->fontheight); + fd4 = p->fontdata + ((*s++ & p->charmask) * p->fontheight); + } +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth == 8) { +#endif + for (i = 0; i < p->fontheight; i++) + fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) + << 8)) << 8)) << 8); + xy += 32; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + } else { + for (i = 0; i < p->fontheight; i++) + fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) + << p->fontwidth)) << p->fontwidth)) << p->fontwidth)) << (24 - 3 * p->fontwidth); + xy += 4 * p->fontwidth; + } + } + } else { + while (count >= 2) { + count -= 2; + fbc->fontw = 2 * p->fontwidth; + fbc->fontinc = 0x10000; + fbc->fontxy = xy; + if (p->fontheightlog) { + fd1 = p->fontdata + ((*s++ & p->charmask) << (p->fontheightlog + 1)); + fd2 = p->fontdata + ((*s++ & p->charmask) << (p->fontheightlog + 1)); + } else { + fd1 = p->fontdata + (((*s++ & p->charmask) * p->fontheight) << 1); + fd2 = p->fontdata + (((*s++ & p->charmask) * p->fontheight) << 1); + } + for (i = 0; i < p->fontheight; i++) { + fbc->font = ((((u32)*(u16 *)fd1) << p->fontwidth) | ((u32)*(u16 *)fd2)) << (16 - p->fontwidth); + fd1 += 2; fd2 += 2; + } + xy += 2 * p->fontwidth; + } +#endif + } + while (count) { + count--; + fbc->fontw = p->fontwidth; + fbc->fontinc = 0x10000; + fbc->fontxy = xy; + if (p->fontheightlog) + i = ((*s++ & p->charmask) << p->fontheightlog); + else + i = ((*s++ & p->charmask) * p->fontheight); +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth <= 8) { +#endif + fd1 = p->fontdata + i; + for (i = 0; i < p->fontheight; i++) + fbc->font = *fd1++ << 24; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + } else { + fd1 = p->fontdata + (i << 1); + for (i = 0; i < p->fontheight; i++) { + fbc->font = *(u16 *)fd1 << 16; + fd1 += 2; + } + } +#endif + xy += p->fontwidth; + } +} + +static void ffb_revc(struct display *p, int xx, int yy) +{ + /* Not used if hw cursor */ +} + +static void ffb_loadcmap (struct fb_info_sbusfb *fb, int index, int count) +{ + struct ffb_dac *dac = fb->s.ffb.dac; + int i, j = count; + + dac->type = 0x2000 | index; + for (i = index; j--; i++) + /* Feed the colors in :)) */ + dac->value = ((fb->color_map CM(i,0))) | + ((fb->color_map CM(i,1)) << 8) | + ((fb->color_map CM(i,2)) << 16); + for (i = index, j = count; i < 16 && j--; i++) + ffb_cmap[i] = ((fb->color_map CM(i,0))) | + ((fb->color_map CM(i,1)) << 8) | + ((fb->color_map CM(i,2)) << 16); +} + +static struct display_switch ffb_dispsw __initdata = { + ffb_setup, fbcon_redraw_bmove, ffb_clear, ffb_putc, ffb_putcs, ffb_revc, + NULL, NULL, NULL, FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */ +}; + +static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) +{ + fb->s.ffb.xy_margin = (y_margin << 16) + x_margin; + p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin); +} + +static inline void ffb_curs_enable (struct fb_info_sbusfb *fb, int enable) +{ + struct ffb_dac *dac = fb->s.ffb.dac; + + dac->type2 = 0x100; + if (fb->s.ffb.dac_rev <= 2) + dac->value2 = enable ? 3 : 0; + else + dac->value2 = enable ? 0 : 3; +} + +static void ffb_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) +{ + struct ffb_dac *dac = fb->s.ffb.dac; + + ffb_curs_enable (fb, 0); + dac->type2 = 0x102; + dac->value2 = (red[0] | (green[0]<<8) | (blue[0]<<16)); + dac->value2 = (red[1] | (green[1]<<8) | (blue[1]<<16)); +} + +/* Set cursor shape */ +static void ffb_setcurshape (struct fb_info_sbusfb *fb) +{ + struct ffb_dac *dac = fb->s.ffb.dac; + int i, j; + + ffb_curs_enable (fb, 0); + for (j = 0; j < 2; j++) { + dac->type2 = j ? 0 : 0x80; + for (i = 0; i < 0x40; i++) { + if (fb->cursor.size.fbx <= 32) { + dac->value2 = fb->cursor.bits [j][i]; + dac->value2 = 0; + } else { + dac->value2 = fb->cursor.bits [j][2*i]; + dac->value2 = fb->cursor.bits [j][2*i+1]; + } + } + } +} + +/* Load cursor information */ +static void ffb_setcursor (struct fb_info_sbusfb *fb) +{ + struct ffb_dac *dac = fb->s.ffb.dac; + struct cg_cursor *c = &fb->cursor; + + dac->type2 = 0x104; + /* Should this be just 0x7ff?? + Should I do some margin handling and setcurshape in that case? */ + dac->value2 = (((c->cpos.fby - c->chot.fby) & 0xffff) << 16) + |((c->cpos.fbx - c->chot.fbx) & 0xffff); + ffb_curs_enable (fb, fb->cursor.enable); +} + +static char idstring[60] __initdata = { 0 }; + +__initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb)) +{ + struct fb_fix_screeninfo *fix = &fb->fix; + struct fb_var_screeninfo *var = &fb->var; + struct display *disp = &fb->disp; + struct fbtype *type = &fb->type; + struct linux_prom64_registers regs[2*PROMREG_MAX]; + int i; + + if (prom_getproperty(fb->prom_node, "reg", (void *) regs, sizeof(regs)) <= 0) + return NULL; + + strcpy(fb->info.modename, "Creator"); + + strcpy(fix->id, "Creator"); + fix->visual = FB_VISUAL_DIRECTCOLOR; + fix->line_length = 8192; + fix->accel = FB_ACCEL_SUN_CREATOR; + + var->bits_per_pixel = 32; + var->green.offset = 8; + var->blue.offset = 16; + var->accel_flags = FB_ACCELF_TEXT; + + disp->scrollmode = SCROLL_YREDRAW; + disp->screen_base = (char *)__va(regs[0].phys_addr) + FFB_DFB24_POFF + 8192 * fb->y_margin + 4 * fb->x_margin; + fb->s.ffb.xy_margin = (fb->y_margin << 16) + fb->x_margin; + fb->s.ffb.fbc = (struct ffb_fbc *)((char *)__va(regs[0].phys_addr) + FFB_FBC_REGS_POFF); + fb->s.ffb.dac = (struct ffb_dac *)((char *)__va(regs[0].phys_addr) + FFB_DAC_POFF); + fb->dispsw = ffb_dispsw; + + fb->margins = ffb_margins; + fb->loadcmap = ffb_loadcmap; + fb->setcursor = ffb_setcursor; + fb->setcursormap = ffb_setcursormap; + fb->setcurshape = ffb_setcurshape; + fb->fill = ffb_fill; + + fb->physbase = regs[0].phys_addr; + fb->mmap_map = ffb_mmap_map; + + fb->cursor.hwsize.fbx = 64; + fb->cursor.hwsize.fby = 64; + + type->fb_depth = 24; + + fb->s.ffb.dac->type = 0x8000; + fb->s.ffb.dac_rev = (fb->s.ffb.dac->value >> 0x1c); + + i = prom_getintdefault (fb->prom_node, "board_type", 8); + + sprintf(idstring, "Creator at %016lx type %d DAC %d", regs[0].phys_addr, i, fb->s.ffb.dac_rev); + + return idstring; +} diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c index c0767a0f0..ebf72f0bd 100644 --- a/drivers/video/cyberfb.c +++ b/drivers/video/cyberfb.c @@ -20,7 +20,6 @@ * for more details. */ -#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -61,6 +60,7 @@ struct cyberfb_par { int xres; int yres; int bpp; + int accel; }; static struct cyberfb_par current_par; @@ -133,49 +133,49 @@ 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, + 0, 0, -1, -1, FB_ACCELF_TEXT, 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, + 0, 0, -1, -1, FB_ACCELF_TEXT, 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, + 0, 0, -1, -1, FB_ACCELF_TEXT, 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, + 0, 0, -1, -1, FB_ACCELF_TEXT, 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, + 0, 0, -1, -1, FB_ACCELF_TEXT, 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, + 0, 0, -1, -1, FB_ACCELF_TEXT, 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, + 0, 0, -1, -1, FB_ACCELF_TEXT, CYBER16_PIXCLOCK, 64, 96, 35, 12, 112, 2, FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED } } @@ -207,8 +207,8 @@ static struct fb_var_screeninfo cyberfb_default; 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_open(struct fb_info *info, int user); +static int cyberfb_release(struct fb_info *info, int user); 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 @@ -229,7 +229,7 @@ static int cyberfb_ioctl(struct inode *inode, struct file *file, u_int cmd, * Interface to the low level console driver */ -unsigned long cyberfb_init(unsigned long mem_start); +void cyberfb_init(void); 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); @@ -239,7 +239,7 @@ static void Cyberfb_blank(int blank, struct fb_info *info); * Text console acceleration */ -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 static struct display_switch fbcon_cyber8; #endif @@ -371,12 +371,11 @@ static int Cyber_init(void) static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, struct cyberfb_par *par) { - int i; - + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, cyberfb_name); - fix->smem_start = (caddr_t)CyberMem; + fix->smem_start = (char *)CyberMem; fix->smem_len = CyberSize; - fix->mmio_start = (unsigned char *)CyberRegs; + fix->mmio_start = (char *)CyberRegs; fix->mmio_len = 0x10000; fix->type = FB_TYPE_PACKED_PIXELS; @@ -390,9 +389,7 @@ static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, fix->ypanstep = 0; fix->ywrapstep = 0; fix->line_length = 0; - - for (i = 0; i < arraysize(fix->reserved); i++) - fix->reserved[i] = 0; + fix->accel = FB_ACCEL_S3_TRIO64; return(0); } @@ -410,6 +407,10 @@ static int Cyber_decode_var(struct fb_var_screeninfo *var, par->xres = var->xres; par->yres = var->yres; par->bpp = var->bits_per_pixel; + if (var->accel_flags & FB_ACCELF_TEXT) + par->accel = FB_ACCELF_TEXT; + else + par->accel = 0; #else if (Cyberfb_Cyber8) { par->xres = CYBER8_WIDTH; @@ -433,8 +434,6 @@ static int Cyber_decode_var(struct fb_var_screeninfo *var, static int Cyber_encode_var(struct fb_var_screeninfo *var, struct cyberfb_par *par) { - int i; - var->xres = par->xres; var->yres = par->yres; var->xres_virtual = par->xres; @@ -471,8 +470,7 @@ 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->accel_flags = (par->accel && par->bpp == 8) ? FB_ACCELF_TEXT : 0; var->vmode = FB_VMODE_NONINTERLACED; @@ -490,9 +488,6 @@ static int Cyber_encode_var(struct fb_var_screeninfo *var, var->hsync_len = 112; var->vsync_len = 2; - for (i = 0; i < arraysize(var->reserved); i++) - var->reserved[i] = 0; - return(0); } @@ -774,7 +769,7 @@ static void do_install_cmap(int con, struct fb_info *info) * Open/Release the frame buffer device */ -static int cyberfb_open(struct fb_info *info) +static int cyberfb_open(struct fb_info *info, int user) { /* * Nothing, only a usage count for the moment @@ -784,7 +779,7 @@ static int cyberfb_open(struct fb_info *info) return(0); } -static int cyberfb_release(struct fb_info *info) +static int cyberfb_release(struct fb_info *info, int user) { MOD_DEC_USE_COUNT; return(0); @@ -847,7 +842,7 @@ static void cyberfb_set_disp(int con, struct fb_info *info) cyberfb_get_fix(&fix, con, info); if (con == -1) con = 0; - display->screen_base = (u_char *)fix.smem_start; + display->screen_base = fix.smem_start; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; @@ -856,12 +851,16 @@ static void cyberfb_set_disp(int con, struct fb_info *info) display->can_soft_blank = 1; display->inverse = Cyberfb_inverse; switch (display->var.bits_per_pixel) { -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 case 8: - display->dispsw = &fbcon_cyber8; + if (display->var.accel_flags & FB_ACCELF_TEXT) { + display->dispsw = &fbcon_cyber8; +#warning FIXME: We should reinit the graphics engine here + } else + display->dispsw = &fbcon_cfb8; break; #endif -#ifdef CONFIG_FBCON_CFB16 +#ifdef FBCON_HAS_CFB16 case 16: display->dispsw = &fbcon_cfb16; break; @@ -880,7 +879,7 @@ static void cyberfb_set_disp(int con, struct fb_info *info) static int cyberfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) { - int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp; + int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel; if ((err = do_fb_set_var(var, con == currcon))) return(err); @@ -890,11 +889,13 @@ static int cyberfb_set_var(struct fb_var_screeninfo *var, int con, oldvxres = fb_display[con].var.xres_virtual; oldvyres = fb_display[con].var.yres_virtual; oldbpp = fb_display[con].var.bits_per_pixel; + oldaccel = fb_display[con].var.accel_flags; 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) { + oldbpp != var->bits_per_pixel || + oldaccel != var->accel_flags) { cyberfb_set_disp(con, info); (*fb_info.changevar)(con); fb_alloc_cmap(&fb_display[con].cmap, 0, 0); @@ -975,7 +976,7 @@ static int cyberfb_ioctl(struct inode *inode, struct file *file, 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 + cyberfb_pan_display, cyberfb_ioctl }; @@ -1013,15 +1014,14 @@ __initfunc(void cyberfb_setup(char *options, int *ints)) * Initialization */ -__initfunc(unsigned long cyberfb_init(unsigned long mem_start)) +__initfunc(void cyberfb_init(void)) { - int err; struct cyberfb_par par; unsigned long board_addr; const struct ConfigDev *cd; if (!(CyberKey = zorro_find(ZORRO_PROD_PHASE5_CYBERVISION64, 0, 0))) - return mem_start; + return; cd = zorro_get_board (CyberKey); zorro_config_board (CyberKey, 0); @@ -1029,7 +1029,7 @@ __initfunc(unsigned long cyberfb_init(unsigned long mem_start)) /* This includes the video memory as well as the S3 register set */ CyberMem = kernel_map (board_addr + 0x01400000, 0x01000000, - KERNELMAP_NOCACHE_SER, &mem_start); + KERNELMAP_NOCACHE_SER, NULL); CyberRegs = (char*) (CyberMem + 0x00c00000); fbhw = &Cyber_switch; @@ -1043,10 +1043,6 @@ __initfunc(unsigned long cyberfb_init(unsigned long mem_start)) 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(&cyberfb_default, &par); fbhw->encode_var(&cyberfb_default, &par); @@ -1056,13 +1052,14 @@ __initfunc(unsigned long cyberfb_init(unsigned long mem_start)) cyberfb_set_disp(-1, &fb_info); do_install_cmap(0, &fb_info); + if (register_framebuffer(&fb_info) < 0) + return; + 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; } @@ -1128,7 +1125,7 @@ __initfunc(static int get_video_mode(const char *name)) * Text console acceleration */ -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 static void fbcon_cyber8_bmove(struct display *p, int sy, int sx, int dy, int dx, int height, int width) { @@ -1161,7 +1158,7 @@ static void fbcon_cyber8_putc(struct vc_data *conp, struct display *p, int c, } static void fbcon_cyber8_putcs(struct vc_data *conp, struct display *p, - const char *s, int count, int yy, int xx) + const unsigned short *s, int count, int yy, int xx) { Cyber_WaitBlit(); fbcon_cfb8_putcs(conp, p, s, count, yy, xx); @@ -1175,7 +1172,8 @@ static void fbcon_cyber8_revc(struct display *p, int xx, int 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 + fbcon_cyber8_putcs, fbcon_cyber8_revc, NULL, NULL, fbcon_cfb8_clear_margins, + FONTWIDTH(8) }; #endif @@ -1183,7 +1181,8 @@ static struct display_switch fbcon_cyber8 = { #ifdef MODULE int init_module(void) { - return(cyberfb_init(NULL)); + cyberfb_init(); + return 0; } void cleanup_module(void) diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c index db0a6172f..906554641 100644 --- a/drivers/video/dnfb.c +++ b/drivers/video/dnfb.c @@ -5,7 +5,6 @@ #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> @@ -114,8 +113,8 @@ /* frame buffer operations */ -static int dnfb_open(struct fb_info *info); -static int dnfb_release(struct fb_info *info); +static int dnfb_open(struct fb_info *info, int user); +static int dnfb_release(struct fb_info *info, int user); 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, @@ -142,14 +141,14 @@ static struct display disp[MAX_NR_CONSOLES]; static struct fb_info fb_info; 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 + dnfb_get_cmap, dnfb_set_cmap, dnfb_pan_display, dnfb_ioctl }; static int currcon=0; static char dnfb_name[]="Apollo"; -static int dnfb_open(struct fb_info *info) +static int dnfb_open(struct fb_info *info, int user) { /* * Nothing, only a usage count for the moment @@ -159,7 +158,7 @@ static int dnfb_open(struct fb_info *info) return(0); } -static int dnfb_release(struct fb_info *info) +static int dnfb_release(struct fb_info *info, int user) { MOD_DEC_USE_COUNT; return(0); @@ -187,6 +186,7 @@ static int dnfb_get_fix(struct fb_fix_screeninfo *fix, int con, static int dnfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) { + memset(var, 0, sizeof(struct fb_var_screeninfo)); var->xres=1280; var->yres=1024; var->xres_virtual=2048; @@ -206,7 +206,6 @@ static int dnfb_get_var(struct fb_var_screeninfo *var, int con, var->vsync_len=0; var->sync=0; var->vmode=FB_VMODE_NONINTERLACED; - var->accel=FB_ACCEL_NONE; return 0; @@ -249,8 +248,6 @@ static int dnfb_set_var(struct fb_var_screeninfo *var, int con, return -EINVAL; if(var->vmode!=FB_VMODE_NONINTERLACED) return -EINVAL; - if(var->accel!=FB_ACCEL_NONE) - return -EINVAL; return 0; @@ -297,7 +294,7 @@ static void dnfb_set_disp(int con, struct fb_info *info) if(con==-1) con=0; - disp[con].screen_base = (u_char *)fix.smem_start; + disp[con].screen_base = fix.smem_start; disp[con].visual = fix.visual; disp[con].type = fix.type; disp[con].type_aux = fix.type_aux; @@ -306,17 +303,15 @@ static void dnfb_set_disp(int con, struct fb_info *info) disp[con].can_soft_blank = 1; disp[con].inverse = 0; disp[con].line_length = fix.line_length; -#ifdef CONFIG_FBCON_MFB +#ifdef FBCON_HAS_MFB disp[con].dispsw = &fbcon_mfb; #else disp[con].dispsw = NULL; #endif } -unsigned long dnfb_init(unsigned long mem_start) +void dnfb_init(void) { - int err; - fb_info.changevar=NULL; strcpy(&fb_info.modename[0],dnfb_name); fb_info.fontname[0]=0; @@ -327,13 +322,6 @@ unsigned long dnfb_init(unsigned long mem_start) fb_info.node = -1; fb_info.fbops = &dnfb_ops; - err=register_framebuffer(&fb_info); - if(err < 0) { - panic("unable to register apollo frame buffer\n"); - } - - /* now we have registered we can safely setup the hardware */ - outb(RESET_CREG, AP_CONTROL_3A); outw(0x0, AP_WRITE_ENABLE); outb(NORMAL_MODE,AP_CONTROL_0); @@ -341,16 +329,14 @@ unsigned long dnfb_init(unsigned long mem_start) outb(S_DATA_PLN, AP_CONTROL_2); outw(SWAP(0x3),AP_ROP_1); - printk("fb%d: apollo frame buffer alive and kicking !\n", - GET_FB_IDX(fb_info.node)); - - dnfb_get_var(&disp[0].var, 0, &fb_info); - dnfb_set_disp(-1, &fb_info); - return mem_start; - + if (register_framebuffer(&fb_info) < 0) + panic("unable to register apollo frame buffer\n"); + + printk("fb%d: apollo frame buffer alive and kicking !\n", + GET_FB_IDX(fb_info.node)); } diff --git a/drivers/video/dummycon.c b/drivers/video/dummycon.c new file mode 100644 index 000000000..4202a5a7d --- /dev/null +++ b/drivers/video/dummycon.c @@ -0,0 +1,71 @@ +/* + * linux/drivers/video/dummycon.c -- A dummy console driver + * + * To be used if there's no other console driver (e.g. for plain VGA text) + * available, usually until fbcon takes console over. + */ + +#include <linux/config.h> +#include <linux/types.h> +#include <linux/kdev_t.h> +#include <linux/tty.h> +#include <linux/console.h> +#include <linux/console_struct.h> +#include <linux/vt_kern.h> +#include <linux/init.h> + +/* + * Dummy console driver + */ + +#if defined(CONFIG_ARM) +#define DUMMY_COLUMNS ORIG_VIDEO_COLS +#define DUMMY_ROWS ORIG_VIDEO_LINES +#else +#define DUMMY_COLUMNS 80 +#define DUMMY_ROWS 25 +#endif + +__initfunc(static const char *dummycon_startup(void)) +{ + return "dummy device"; +} + +static void dummycon_init(struct vc_data *conp, int init) +{ + conp->vc_can_do_color = 1; + if (init) { + conp->vc_cols = DUMMY_COLUMNS; + conp->vc_rows = DUMMY_ROWS; + } else + vc_resize_con(DUMMY_ROWS, DUMMY_COLUMNS, conp->vc_num); +} + +static int dummycon_dummy(void) +{ + return 0; +} + +/* + * The console `switch' structure for the dummy console + * + * Most of the operations are dummies. + */ + +struct consw dummy_con = { + dummycon_startup, dummycon_init, + (void *)dummycon_dummy, /* con_deinit */ + (void *)dummycon_dummy, /* con_clear */ + (void *)dummycon_dummy, /* con_putc */ + (void *)dummycon_dummy, /* con_putcs */ + (void *)dummycon_dummy, /* con_cursor */ + (void *)dummycon_dummy, /* con_scroll */ + (void *)dummycon_dummy, /* con_bmove */ + (void *)dummycon_dummy, /* con_switch */ + (void *)dummycon_dummy, /* con_blank */ + (void *)dummycon_dummy, /* con_font_op */ + (void *)dummycon_dummy, /* con_set_palette */ + (void *)dummycon_dummy, /* con_scrolldelta */ + NULL, /* con_set_origin */ + NULL, /* con_save_screen */ +}; diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index bbf06d89b..d3e339e4f 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c @@ -59,7 +59,7 @@ static u16 red8[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa }; static u16 green8[] = { - 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0xaaaa, 0xaaaa + 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa }; static u16 blue8[] = { 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa @@ -70,7 +70,7 @@ static u16 red16[] = { 0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff }; static u16 green16[] = { - 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0xaaaa, 0xaaaa, + 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa, 0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff }; static u16 blue16[] = { diff --git a/drivers/video/fbcon-afb.c b/drivers/video/fbcon-afb.c index efe9833cb..a8c01d6a0 100644 --- a/drivers/video/fbcon-afb.c +++ b/drivers/video/fbcon-afb.c @@ -250,12 +250,10 @@ void fbcon_afb_putc(struct vc_data *conp, struct display *p, int c, int yy, u_short i, j; int fg, bg; - c &= 0xff; - dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx; - cdat0 = p->fontdata+c*p->fontheight; - fg = attr_fgcol(p,conp); - bg = attr_bgcol(p,conp); + cdat0 = p->fontdata+(c&p->charmask)*p->fontheight; + fg = attr_fgcol(p,c); + bg = attr_bgcol(p,c); i = p->var.bits_per_pixel; do { @@ -282,22 +280,22 @@ void fbcon_afb_putc(struct vc_data *conp, struct display *p, int c, int yy, * (cfr. fbcon_putcs_ilbm()) */ -void fbcon_afb_putcs(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 unsigned short *s, int count, int yy, int xx) { u8 *dest, *dest0, *dest1, *expand; u8 *cdat1, *cdat2, *cdat3, *cdat4, *cdat10, *cdat20, *cdat30, *cdat40; u_short i, j; - u8 c1, c2, c3, c4; + u16 c1, c2, c3, c4; int fg0, bg0, fg, bg; dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx; - fg0 = attr_fgcol(p,conp); - bg0 = attr_bgcol(p,conp); + fg0 = attr_fgcol(p,*s); + bg0 = attr_bgcol(p,*s); while (count--) if (xx&3 || count < 3) { /* Slow version */ - c1 = *s++; + c1 = *s++ & p->charmask; dest1 = dest0++; xx++; @@ -324,10 +322,10 @@ void fbcon_afb_putcs(struct vc_data *conp, struct display *p, const char *s, dest1 += p->next_plane; } while (--i); } else { /* Fast version */ - c1 = s[0]; - c2 = s[1]; - c3 = s[2]; - c4 = s[3]; + c1 = s[0] & p->charmask; + c2 = s[1] & p->charmask; + c3 = s[2] & p->charmask; + c4 = s[3] & p->charmask; dest1 = dest0; cdat10 = p->fontdata+c1*p->fontheight; @@ -414,10 +412,21 @@ void fbcon_afb_revc(struct display *p, int xx, int yy) struct display_switch fbcon_afb = { fbcon_afb_setup, fbcon_afb_bmove, fbcon_afb_clear, fbcon_afb_putc, - fbcon_afb_putcs, fbcon_afb_revc + fbcon_afb_putcs, fbcon_afb_revc, NULL, NULL, NULL, FONTWIDTH(8) }; +#ifdef MODULE +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{} +#endif /* MODULE */ + + /* * Visible symbols for modules */ diff --git a/drivers/video/fbcon-afb.h b/drivers/video/fbcon-afb.h index 537b3bdd7..c82d98c41 100644 --- a/drivers/video/fbcon-afb.h +++ b/drivers/video/fbcon-afb.h @@ -2,6 +2,18 @@ * Amiga bitplanes (afb) */ +#include <linux/config.h> + +#ifdef MODULE +#if defined(CONFIG_FBCON_AFB) || defined(CONFIG_FBCON_AFB_MODULE) +#define FBCON_HAS_AFB +#endif +#else +#if defined(CONFIG_FBCON_AFB) +#define FBCON_HAS_AFB +#endif +#endif + 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, @@ -11,5 +23,5 @@ extern void fbcon_afb_clear(struct vc_data *conp, struct display *p, int sy, 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); + const unsigned short *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 475095988..221fbc572 100644 --- a/drivers/video/fbcon-cfb16.c +++ b/drivers/video/fbcon-cfb16.c @@ -9,6 +9,7 @@ * more details. */ +#include <linux/config.h> #include <linux/module.h> #include <linux/tty.h> #include <linux/console.h> @@ -37,7 +38,7 @@ static u32 tab_cfb16[] = { void fbcon_cfb16_setup(struct display *p) { - p->next_line = p->var.xres_virtual<<1; + p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<1; p->next_plane = 0; } @@ -47,23 +48,34 @@ void fbcon_cfb16_bmove(struct display *p, int sy, int sx, int dy, int dx, int bytes = p->next_line, linesize = bytes * p->fontheight, rows; u8 *src, *dst; - if (sx == 0 && dx == 0 && width * 16 == bytes) + if (sx == 0 && dx == 0 && width * p->fontwidth * 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 * 16; - dst = p->screen_base + dy * linesize + dx * 16; - for (rows = height * p->fontheight ; rows-- ;) { - mymemmove(dst, src, width * 16); + return; + } + if (p->fontwidthlog) { + sx <<= p->fontwidthlog+1; + dx <<= p->fontwidthlog+1; + width <<= p->fontwidthlog+1; + } else { + sx *= p->fontwidth*2; + dx *= p->fontwidth*2; + width *= p->fontwidth*2; + } + if (dy < sy || (dy == sy && dx < sx)) { + src = p->screen_base + sy * linesize + sx; + dst = p->screen_base + dy * linesize + dx; + for (rows = height * p->fontheight; rows--;) { + mymemmove(dst, src, width); src += bytes; dst += bytes; } } else { - src = p->screen_base + (sy+height) * linesize + sx * 16 - bytes; - dst = p->screen_base + (dy+height) * linesize + dx * 16 - bytes; - for (rows = height * p->fontheight ; rows-- ;) { - mymemmove(dst, src, width * 16); + src = p->screen_base + (sy+height) * linesize + sx - bytes; + dst = p->screen_base + (dy+height) * linesize + dx - bytes; + for (rows = height * p->fontheight; rows--;) { + mymemmove(dst, src, width); src -= bytes; dst -= bytes; } @@ -77,29 +89,26 @@ void fbcon_cfb16_clear(struct vc_data *conp, struct display *p, int sy, int sx, int bytes = p->next_line, lines = height * p->fontheight, rows, i; u32 bgx; - dest = p->screen_base + sy * p->fontheight * bytes + sx * 16; + dest = p->screen_base + sy * p->fontheight * bytes + sx * p->fontwidth * 2; 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++) { + width *= p->fontwidth/4; + if (sx == 0 && width * 8 == bytes) + for (i = 0; i < lines * width; i++) { ((u32 *)dest)[0] = bgx; ((u32 *)dest)[1] = bgx; - ((u32 *)dest)[2] = bgx; - ((u32 *)dest)[3] = bgx; - dest += 16; + dest += 8; } else { dest0 = dest; - for (rows = lines; rows-- ; dest0 += bytes) { + for (rows = lines; rows--; dest0 += bytes) { dest = dest0; - for (i = 0 ; i < width ; i++) { + for (i = 0; i < width; i++) { ((u32 *)dest)[0] = bgx; ((u32 *)dest)[1] = bgx; - ((u32 *)dest)[2] = bgx; - ((u32 *)dest)[3] = bgx; - dest += 16; + dest += 8; } } } @@ -108,56 +117,124 @@ void fbcon_cfb16_clear(struct vc_data *conp, struct display *p, int sy, int sx, void fbcon_cfb16_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) { - u8 *dest, *cdat; + u8 *dest, *cdat, bits; int bytes = p->next_line, rows; u32 eorx, fgx, bgx; - c &= 0xff; + dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 2; - dest = p->screen_base + yy * p->fontheight * bytes + xx * 16; - cdat = p->fontdata + c * p->fontheight; - - fgx = fbcon_cfb16_cmap[attr_fgcol(p, conp)]; - bgx = fbcon_cfb16_cmap[attr_bgcol(p, conp)]; + fgx = fbcon_cfb16_cmap[attr_fgcol(p, c)]; + bgx = fbcon_cfb16_cmap[attr_bgcol(p, c)]; fgx |= (fgx << 16); bgx |= (bgx << 16); eorx = fgx ^ bgx; - for (rows = p->fontheight ; rows-- ; dest += bytes) { - 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; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + switch (p->fontwidth) { + case 4: + case 8: +#endif + cdat = p->fontdata + (c & p->charmask) * p->fontheight; + for (rows = p->fontheight; rows--; dest += bytes) { + bits = *cdat++; + ((u32 *)dest)[0] = (tab_cfb16[bits >> 6] & eorx) ^ bgx; + ((u32 *)dest)[1] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth == 8) +#endif + { + ((u32 *)dest)[2] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx; + ((u32 *)dest)[3] = (tab_cfb16[bits & 3] & eorx) ^ bgx; + } + } +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + break; + case 12: + case 16: + cdat = p->fontdata + ((c & p->charmask) * p->fontheight << 1); + for (rows = p->fontheight; rows--; dest += bytes) { + 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; + bits = *cdat++; + ((u32 *)dest)[4] = (tab_cfb16[bits >> 6] & eorx) ^ bgx; + ((u32 *)dest)[5] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx; + if (p->fontwidth == 16) { + ((u32 *)dest)[6] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx; + ((u32 *)dest)[7] = (tab_cfb16[bits & 3] & eorx) ^ bgx; + } + } + break; } +#endif } -void fbcon_cfb16_putcs(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 unsigned short *s, int count, int yy, int xx) { - u8 *cdat, c, *dest, *dest0; + u8 *cdat, *dest, *dest0; + u16 c; int rows, bytes = p->next_line; u32 eorx, fgx, bgx; - dest0 = p->screen_base + yy * p->fontheight * bytes + xx * 16; - fgx = fbcon_cfb16_cmap[attr_fgcol(p, conp)]; - bgx = fbcon_cfb16_cmap[attr_bgcol(p, conp)]; + dest0 = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 2; + fgx = fbcon_cfb16_cmap[attr_fgcol(p, *s)]; + bgx = fbcon_cfb16_cmap[attr_bgcol(p, *s)]; fgx |= (fgx << 16); 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) { - 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; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + switch (p->fontwidth) { + case 4: + case 8: +#endif + while (count--) { + c = *s++ & p->charmask; + cdat = p->fontdata + c * p->fontheight; + for (rows = p->fontheight, dest = dest0; rows--; dest += bytes) { + u8 bits = *cdat++; + ((u32 *)dest)[0] = (tab_cfb16[bits >> 6] & eorx) ^ bgx; + ((u32 *)dest)[1] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth == 8) +#endif + { + + ((u32 *)dest)[2] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx; + ((u32 *)dest)[3] = (tab_cfb16[bits & 3] & eorx) ^ bgx; + } + } + dest0 += p->fontwidth*2;; } - dest0 += 16; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + break; + case 12: + case 16: + while (count--) { + c = *s++ & p->charmask; + cdat = p->fontdata + (c * p->fontheight << 1); + for (rows = p->fontheight, dest = dest0; rows--; dest += bytes) { + 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; + bits = *cdat++; + ((u32 *)dest)[4] = (tab_cfb16[bits >> 6] & eorx) ^ bgx; + ((u32 *)dest)[5] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx; + if (p->fontwidth == 16) { + ((u32 *)dest)[6] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx; + ((u32 *)dest)[7] = (tab_cfb16[bits & 3] & eorx) ^ bgx; + } + } + dest0 += p->fontwidth*2; + } + break; } +#endif } void fbcon_cfb16_revc(struct display *p, int xx, int yy) @@ -165,12 +242,60 @@ void fbcon_cfb16_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 * 16; - for (rows = p->fontheight ; rows-- ; dest += bytes) { - ((u32 *)dest)[0] ^= 0xffffffff; - ((u32 *)dest)[1] ^= 0xffffffff; - ((u32 *)dest)[2] ^= 0xffffffff; - ((u32 *)dest)[3] ^= 0xffffffff; + dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth*2; + for (rows = p->fontheight; rows--; dest += bytes) { +#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY + ((u32 *)dest)[2] ^= 0xffffffff; ((u32 *)dest)[3] ^= 0xffffffff; + ((u32 *)dest)[0] ^= 0xffffffff; ((u32 *)dest)[1] ^= 0xffffffff; +#else + switch (p->fontwidth) { + case 16: + ((u32 *)dest)[6] ^= 0xffffffff; ((u32 *)dest)[7] ^= 0xffffffff; + /* FALL THROUGH */ + case 12: + ((u32 *)dest)[4] ^= 0xffffffff; ((u32 *)dest)[5] ^= 0xffffffff; + /* FALL THROUGH */ + case 8: + ((u32 *)dest)[2] ^= 0xffffffff; ((u32 *)dest)[3] ^= 0xffffffff; + /* FALL THROUGH */ + case 4: + ((u32 *)dest)[0] ^= 0xffffffff; ((u32 *)dest)[1] ^= 0xffffffff; + } +#endif + } +} + +void fbcon_cfb16_clear_margins(struct vc_data *conp, struct display *p) +{ + u8 *dest0; + u32 *dest; + int bytes = p->next_line; + u32 bgx; + int i, j; + + unsigned int right_start = conp->vc_cols*p->fontwidth; + unsigned int right_width = p->var.xres_virtual-right_start; + unsigned int bottom_start = conp->vc_rows*p->fontheight; + unsigned int bottom_width = p->var.yres_virtual-bottom_start; + + bgx = fbcon_cfb16_cmap[attr_bgcol_ec(p, conp)]; + bgx |= (bgx << 16); + + if (right_width) { + dest0 = p->screen_base+right_start*2; + for (i = 0; i < bottom_start; i++, dest0 += bytes) { + for (j = 0, dest = (u32 *)dest0; j < right_width/2; j++) + *dest++ = bgx; + if (right_width & 1) + *(u16 *)dest = bgx; + } + } + if (bottom_width) { + dest = (u32 *)(p->screen_base+bottom_start*bytes); + for (i = 0; i < bytes*bottom_width/4; i++) + *dest++ = bgx; + if ((bytes*bottom_width) & 2) + *(u16 *)dest = bgx; } } @@ -181,10 +306,22 @@ void fbcon_cfb16_revc(struct display *p, int xx, int yy) struct display_switch fbcon_cfb16 = { fbcon_cfb16_setup, fbcon_cfb16_bmove, fbcon_cfb16_clear, fbcon_cfb16_putc, - fbcon_cfb16_putcs, fbcon_cfb16_revc + fbcon_cfb16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins, + FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; +#ifdef MODULE +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{} +#endif /* MODULE */ + + /* * Visible symbols for modules */ diff --git a/drivers/video/fbcon-cfb16.h b/drivers/video/fbcon-cfb16.h index 905d6329a..ebff9bcb9 100644 --- a/drivers/video/fbcon-cfb16.h +++ b/drivers/video/fbcon-cfb16.h @@ -2,6 +2,18 @@ * 16 bpp packed pixel (cfb16) */ +#include <linux/config.h> + +#ifdef MODULE +#if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB16_MODULE) +#define FBCON_HAS_CFB16 +#endif +#else +#if defined(CONFIG_FBCON_CFB16) +#define FBCON_HAS_CFB16 +#endif +#endif + extern struct display_switch fbcon_cfb16; extern u16 fbcon_cfb16_cmap[16]; extern void fbcon_cfb16_setup(struct display *p); @@ -12,5 +24,6 @@ extern void fbcon_cfb16_clear(struct vc_data *conp, struct display *p, int sy, 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); + const unsigned short *s, int count, int yy, int xx); extern void fbcon_cfb16_revc(struct display *p, int xx, int yy); +extern void fbcon_cfb16_clear_margins(struct vc_data *conp, struct display *p); diff --git a/drivers/video/fbcon-cfb2.c b/drivers/video/fbcon-cfb2.c index 6ed68e89d..60bed6275 100644 --- a/drivers/video/fbcon-cfb2.c +++ b/drivers/video/fbcon-cfb2.c @@ -32,10 +32,19 @@ */ static u_char nibbletab_cfb2[]={ +#if defined(__BIG_ENDIAN) 0x00,0x03,0x0c,0x0f, 0x30,0x33,0x3c,0x3f, 0xc0,0xc3,0xcc,0xcf, 0xf0,0xf3,0xfc,0xff +#elif defined(__LITTLE_ENDIAN) + 0x00,0xc0,0x30,0xf0, + 0x0c,0xcc,0x3c,0xfc, + 0x03,0xc3,0x33,0xf3, + 0x0f,0xcf,0x3f,0xff +#else +#error FIXME: No endianness?? +#endif }; @@ -119,13 +128,11 @@ void fbcon_cfb2_putc(struct vc_data *conp, struct display *p, int c, int yy, 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; + cdat = p->fontdata + (c & p->charmask) * p->fontheight; - fgx=3;/*attr_fgcol(p,conp)&0x0F;*/ - bgx=attr_bgcol(p,conp)&0x0F; + fgx=3;/*attr_fgcol(p,c);*/ + bgx=attr_bgcol(p,c); fgx |= (fgx << 2); /* expand color to 8 bits */ fgx |= (fgx << 4); bgx |= (bgx << 2); @@ -140,23 +147,24 @@ void fbcon_cfb2_putc(struct vc_data *conp, struct display *p, int c, int yy, } } -void fbcon_cfb2_putcs(struct vc_data *conp, struct display *p, const char *s, +void fbcon_cfb2_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, int count, int yy, int xx) { - u8 *cdat, c, *dest, *dest0; + u8 *cdat, *dest, *dest0; + u16 c; 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=3/*attr_fgcol(p,*s)*/; + bgx=attr_bgcol(p,*s); fgx |= (fgx << 2); fgx |= (fgx << 4); bgx |= (bgx << 2); bgx |= (bgx << 4); eorx = fgx ^ bgx; while (count--) { - c = *s++; + c = *s++ & p->charmask; cdat = p->fontdata + c * p->fontheight; for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { @@ -187,10 +195,21 @@ void fbcon_cfb2_revc(struct display *p, int xx, int yy) struct display_switch fbcon_cfb2 = { fbcon_cfb2_setup, fbcon_cfb2_bmove, fbcon_cfb2_clear, fbcon_cfb2_putc, - fbcon_cfb2_putcs, fbcon_cfb2_revc + fbcon_cfb2_putcs, fbcon_cfb2_revc, NULL, NULL, NULL, FONTWIDTH(8) }; +#ifdef MODULE +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{} +#endif /* MODULE */ + + /* * Visible symbols for modules */ diff --git a/drivers/video/fbcon-cfb2.h b/drivers/video/fbcon-cfb2.h index 4fb3bb13a..1cb29c5a9 100644 --- a/drivers/video/fbcon-cfb2.h +++ b/drivers/video/fbcon-cfb2.h @@ -2,6 +2,18 @@ * 2 bpp packed pixel (cfb2) */ +#include <linux/config.h> + +#ifdef MODULE +#if defined(CONFIG_FBCON_CFB2) || defined(CONFIG_FBCON_CFB2_MODULE) +#define FBCON_HAS_CFB2 +#endif +#else +#if defined(CONFIG_FBCON_CFB2) +#define FBCON_HAS_CFB2 +#endif +#endif + 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, @@ -11,5 +23,5 @@ extern void fbcon_cfb2_clear(struct vc_data *conp, struct display *p, int sy, 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); + const unsigned short *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 index 2a95a28cf..49c023ef3 100644 --- a/drivers/video/fbcon-cfb24.c +++ b/drivers/video/fbcon-cfb24.c @@ -9,6 +9,7 @@ * more details. */ +#include <linux/config.h> #include <linux/module.h> #include <linux/tty.h> #include <linux/console.h> @@ -19,9 +20,6 @@ #include "fbcon-cfb24.h" -#warning Remove this warning after the test cycle was finalized - - /* * 24 bpp packed pixels */ @@ -40,29 +38,56 @@ void fbcon_cfb24_bmove(struct display *p, int sy, int sx, int dy, int dx, int bytes = p->next_line, linesize = bytes * p->fontheight, rows; u8 *src, *dst; - if (sx == 0 && dx == 0 && width * 24 == bytes) + if (sx == 0 && dx == 0 && width * p->fontwidth * 3 == 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); + return; + } + if (p->fontwidthlog) { + sx <<= p->fontwidthlog; + dx <<= p->fontwidthlog; + width <<= p->fontwidthlog; + } else { + sx *= p->fontwidth; + dx *= p->fontwidth; + width *= p->fontwidth; + } + sx *= 3; dx *= 3; width *= 3; + if (dy < sy || (dy == sy && dx < sx)) { + src = p->screen_base + sy * linesize + sx; + dst = p->screen_base + dy * linesize + dx; + for (rows = height * p->fontheight; rows--;) { + mymemmove(dst, src, width); 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 = p->screen_base + (sy+height) * linesize + sx - bytes; + dst = p->screen_base + (dy+height) * linesize + dx - bytes; + for (rows = height * p->fontheight; rows--;) { + mymemmove(dst, src, width); src -= bytes; dst -= bytes; } } } +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) + *dest++ = (d1<<8) | (d2>>16); + *dest++ = (d2<<16) | (d3>>8); + *dest++ = (d3<<24) | d4; +#else +#error FIXME: No endianness?? +#endif +} + void fbcon_cfb24_clear(struct vc_data *conp, struct display *p, int sy, int sx, int height, int width) { @@ -70,112 +95,139 @@ void fbcon_cfb24_clear(struct vc_data *conp, struct display *p, int sy, int sx, int bytes = p->next_line, lines = height * p->fontheight, rows, i; u32 bgx; - dest = p->screen_base + sy * p->fontheight * bytes + sx * 24; + dest = p->screen_base + sy * p->fontheight * bytes + sx * p->fontwidth * 3; 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; + width *= p->fontwidth/4; + if (sx == 0 && width * 12 == bytes) + for (i = 0; i < lines * width; i++) { + store4pixels(bgx, bgx, bgx, bgx, (u32 *)dest); + dest += 12; } else { dest0 = dest; - for (rows = lines; rows-- ; dest0 += bytes) { + 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; + for (i = 0; i < width; i++) { + store4pixels(bgx, bgx, bgx, bgx, (u32 *)dest); + dest += 12; } } } } -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; + u8 *dest, *cdat, bits; int bytes = p->next_line, rows; - u32 eorx, fgx, bgx; - - c &= 0xff; + u32 eorx, fgx, bgx, d1, d2, d3, d4; - dest = p->screen_base + yy * p->fontheight * bytes + xx * 24; - cdat = p->fontdata + c * p->fontheight; + dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 3; + if (p->fontwidth <= 8) + cdat = p->fontdata + (c & p->charmask) * p->fontheight; + else + cdat = p->fontdata + ((c & p->charmask) * p->fontheight << 1); - fgx = fbcon_cfb24_cmap[attr_fgcol(p, conp)]; - bgx = fbcon_cfb24_cmap[attr_bgcol(p, conp)]; + fgx = fbcon_cfb24_cmap[attr_fgcol(p, c)]; + bgx = fbcon_cfb24_cmap[attr_bgcol(p, c)]; eorx = fgx ^ bgx; - for (rows = p->fontheight ; rows-- ; dest += bytes) { - u8 bits = *cdat++; - u32 d1, d2, d3, d4; + for (rows = p->fontheight; rows--; dest += bytes) { + bits = *cdat++; 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); +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth < 8) + continue; +#endif 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)); +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth < 12) + continue; + bits = *cdat++; + 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+24)); + if (p->fontwidth < 16) + continue; + 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+32)); +#endif } } -void fbcon_cfb24_putcs(struct vc_data *conp, struct display *p, const char *s, - int count, int yy, int xx) +void fbcon_cfb24_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int yy, int xx) { - u8 *cdat, c, *dest, *dest0; + u8 *cdat, *dest, *dest0, bits; + u16 c; int rows, bytes = p->next_line; - u32 eorx, fgx, bgx; + u32 eorx, fgx, bgx, d1, d2, d3, d4; - 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)]; + dest0 = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 3; + fgx = fbcon_cfb24_cmap[attr_fgcol(p, *s)]; + bgx = fbcon_cfb24_cmap[attr_bgcol(p, *s)]; eorx = fgx ^ bgx; while (count--) { - c = *s++; + c = *s++ & p->charmask; +#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY cdat = p->fontdata + c * p->fontheight; - - for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { - u8 bits = *cdat++; - u32 d1, d2, d3, d4; +#else + if (p->fontwidth <= 8) + cdat = p->fontdata + c * p->fontheight; + + else + cdat = p->fontdata + (c * p->fontheight << 1); +#endif + for (rows = p->fontheight, dest = dest0; rows--; dest += bytes) { + bits = *cdat++; 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); +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth < 8) + continue; +#endif 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)); +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth < 12) + continue; + bits = *cdat++; + 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+24)); + if (p->fontwidth < 16) + continue; + 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+32)); +#endif } - dest0 += 24; + dest0 += p->fontwidth*3; } } @@ -184,14 +236,60 @@ 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; + dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 3; + for (rows = p->fontheight; rows--; dest += bytes) { +#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY + ((u32 *)dest)[3] ^= 0xffffffff; ((u32 *)dest)[4] ^= 0xffffffff; ((u32 *)dest)[5] ^= 0xffffffff; + ((u32 *)dest)[0] ^= 0xffffffff; ((u32 *)dest)[1] ^= 0xffffffff; + ((u32 *)dest)[2] ^= 0xffffffff; +#else + switch (p->fontwidth) { + case 16: + ((u32 *)dest)[9] ^= 0xffffffff; ((u32 *)dest)[10] ^= 0xffffffff; + ((u32 *)dest)[11] ^= 0xffffffff; /* FALL THROUGH */ + case 12: + ((u32 *)dest)[6] ^= 0xffffffff; ((u32 *)dest)[7] ^= 0xffffffff; + ((u32 *)dest)[8] ^= 0xffffffff; /* FALL THROUGH */ + case 8: + ((u32 *)dest)[3] ^= 0xffffffff; ((u32 *)dest)[4] ^= 0xffffffff; + ((u32 *)dest)[5] ^= 0xffffffff; /* FALL THROUGH */ + case 4: + ((u32 *)dest)[0] ^= 0xffffffff; ((u32 *)dest)[1] ^= 0xffffffff; + ((u32 *)dest)[2] ^= 0xffffffff; + } +#endif + } +} + +void fbcon_cfb24_clear_margins(struct vc_data *conp, struct display *p) +{ + u8 *dest0, *dest; + int bytes = p->next_line; + u32 bgx; + int i, j; + + unsigned int right_start = conp->vc_cols*p->fontwidth; + unsigned int right_width = p->var.xres_virtual-right_start; + unsigned int bottom_start = conp->vc_rows*p->fontheight; + unsigned int bottom_width = p->var.yres_virtual-bottom_start; + + bgx = fbcon_cfb24_cmap[attr_bgcol_ec(p, conp)]; + + if (right_width) { + dest0 = p->screen_base+right_start*3; + for (i = 0; i < bottom_start; i++, dest0 += bytes) + for (j = 0, dest = dest0; j < right_width/4; j++) { + store4pixels(bgx, bgx, bgx, bgx, (u32 *)dest); + dest += 12; + } + } + if (bottom_width) { + dest = p->screen_base+bottom_start*bytes; + for (i = 0; i < bytes*bottom_width/12; i++) { + store4pixels(bgx, bgx, bgx, bgx, (u32 *)dest); + dest += 12; + } } } @@ -202,10 +300,22 @@ void fbcon_cfb24_revc(struct display *p, int xx, int yy) struct display_switch fbcon_cfb24 = { fbcon_cfb24_setup, fbcon_cfb24_bmove, fbcon_cfb24_clear, fbcon_cfb24_putc, - fbcon_cfb24_putcs, fbcon_cfb24_revc + fbcon_cfb24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_cfb24_clear_margins, + FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; +#ifdef MODULE +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{} +#endif /* MODULE */ + + /* * Visible symbols for modules */ diff --git a/drivers/video/fbcon-cfb24.h b/drivers/video/fbcon-cfb24.h index bd672ab20..83cee1209 100644 --- a/drivers/video/fbcon-cfb24.h +++ b/drivers/video/fbcon-cfb24.h @@ -2,6 +2,18 @@ * 24 bpp packed pixel (cfb24) */ +#include <linux/config.h> + +#ifdef MODULE +#if defined(CONFIG_FBCON_CFB24) || defined(CONFIG_FBCON_CFB24_MODULE) +#define FBCON_HAS_CFB24 +#endif +#else +#if defined(CONFIG_FBCON_CFB24) +#define FBCON_HAS_CFB24 +#endif +#endif + extern struct display_switch fbcon_cfb24; extern u32 fbcon_cfb24_cmap[16]; extern void fbcon_cfb24_setup(struct display *p); @@ -12,5 +24,6 @@ extern void fbcon_cfb24_clear(struct vc_data *conp, struct display *p, int sy, 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); + const unsigned short *s, int count, int yy, int xx); extern void fbcon_cfb24_revc(struct display *p, int xx, int yy); +extern void fbcon_cfb24_clear_margins(struct vc_data *conp, struct display *p); diff --git a/drivers/video/fbcon-cfb32.c b/drivers/video/fbcon-cfb32.c index cedc04814..1a1c48bcf 100644 --- a/drivers/video/fbcon-cfb32.c +++ b/drivers/video/fbcon-cfb32.c @@ -9,6 +9,7 @@ * more details. */ +#include <linux/config.h> #include <linux/module.h> #include <linux/tty.h> #include <linux/console.h> @@ -37,23 +38,34 @@ void fbcon_cfb32_bmove(struct display *p, int sy, int sx, int dy, int dx, int bytes = p->next_line, linesize = bytes * p->fontheight, rows; u8 *src, *dst; - if (sx == 0 && dx == 0 && width * 32 == bytes) + if (sx == 0 && dx == 0 && width * p->fontwidth * 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 * 32; - dst = p->screen_base + dy * linesize + dx * 32; - for (rows = height * p->fontheight ; rows-- ;) { - mymemmove(dst, src, width * 32); + return; + } + if (p->fontwidthlog) { + sx <<= p->fontwidthlog+2; + dx <<= p->fontwidthlog+2; + width <<= p->fontwidthlog+2; + } else { + sx *= p->fontwidth*4; + dx *= p->fontwidth*4; + width *= p->fontwidth*4; + } + if (dy < sy || (dy == sy && dx < sx)) { + src = p->screen_base + sy * linesize + sx; + dst = p->screen_base + dy * linesize + dx; + for (rows = height * p->fontheight; rows--;) { + mymemmove(dst, src, width); 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 = p->screen_base + (sy+height) * linesize + sx - bytes; + dst = p->screen_base + (dy+height) * linesize + dx - bytes; + for (rows = height * p->fontheight; rows--;) { + mymemmove(dst, src, width); src -= bytes; dst -= bytes; } @@ -67,36 +79,29 @@ void fbcon_cfb32_clear(struct vc_data *conp, struct display *p, int sy, int sx, int bytes = p->next_line, lines = height * p->fontheight, rows, i; u32 bgx; - dest = p->screen_base + sy * p->fontheight * bytes + sx * 32; + dest = p->screen_base + sy * p->fontheight * bytes + sx * p->fontwidth * 4; bgx = fbcon_cfb32_cmap[attr_bgcol_ec(p, conp)]; - if (sx == 0 && width * 32 == bytes) - for (i = 0 ; i < lines * width ; i++) { + width *= p->fontwidth/4; + if (sx == 0 && width * 16 == 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; + dest += 16; } else { dest0 = dest; - for (rows = lines; rows-- ; dest0 += bytes) { + for (rows = lines; rows--; dest0 += bytes) { dest = dest0; - for (i = 0 ; i < width ; i++) { + 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; + dest += 16; } } } @@ -105,59 +110,108 @@ void fbcon_cfb32_clear(struct vc_data *conp, struct display *p, int sy, int sx, void fbcon_cfb32_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) { - u8 *dest, *cdat; + u8 *dest, *cdat, bits; 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)]; + dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 4; +#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY + cdat = p->fontdata + (c & p->charmask) * p->fontheight; +#else + if (p->fontwidth <= 8) + cdat = p->fontdata + (c & p->charmask) * p->fontheight; + else + cdat = p->fontdata + ((c & p->charmask) * p->fontheight << 1); +#endif + fgx = fbcon_cfb32_cmap[attr_fgcol(p, c)]; + bgx = fbcon_cfb32_cmap[attr_bgcol(p, c)]; eorx = fgx ^ bgx; - for (rows = p->fontheight ; rows-- ; dest += bytes) { - u8 bits = *cdat++; + for (rows = p->fontheight; rows--; dest += bytes) { + 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; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth < 8) + continue; +#endif ((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; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth < 12) + continue; + bits = *cdat++; + ((u32 *)dest)[8] = (-(bits >> 7) & eorx) ^ bgx; + ((u32 *)dest)[9] = (-(bits >> 6 & 1) & eorx) ^ bgx; + ((u32 *)dest)[10] = (-(bits >> 5 & 1) & eorx) ^ bgx; + ((u32 *)dest)[11] = (-(bits >> 4 & 1) & eorx) ^ bgx; + if (p->fontwidth < 16) + continue; + ((u32 *)dest)[12] = (-(bits >> 3 & 1) & eorx) ^ bgx; + ((u32 *)dest)[13] = (-(bits >> 2 & 1) & eorx) ^ bgx; + ((u32 *)dest)[14] = (-(bits >> 1 & 1) & eorx) ^ bgx; + ((u32 *)dest)[15] = (-(bits & 1) & eorx) ^ bgx; +#endif } } -void fbcon_cfb32_putcs(struct vc_data *conp, struct display *p, const char *s, - int count, int yy, int xx) +void fbcon_cfb32_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int yy, int xx) { - u8 *cdat, c, *dest, *dest0; + u8 *cdat, *dest, *dest0, bits; + u16 c; 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)]; + dest0 = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 4; + fgx = fbcon_cfb32_cmap[attr_fgcol(p, *s)]; + bgx = fbcon_cfb32_cmap[attr_bgcol(p, *s)]; eorx = fgx ^ bgx; while (count--) { - c = *s++; + c = *s++ & p->charmask; +#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY cdat = p->fontdata + c * p->fontheight; - - for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { - u8 bits = *cdat++; +#else + if (p->fontwidth <= 8) + cdat = p->fontdata + c * p->fontheight; + else + cdat = p->fontdata + (c * p->fontheight << 1); +#endif + for (rows = p->fontheight, dest = dest0; rows--; dest += bytes) { + 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; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth < 8) + continue; +#endif ((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; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth < 12) + continue; + bits = *cdat++; + ((u32 *)dest)[8] = (-(bits >> 7) & eorx) ^ bgx; + ((u32 *)dest)[9] = (-(bits >> 6 & 1) & eorx) ^ bgx; + ((u32 *)dest)[10] = (-(bits >> 5 & 1) & eorx) ^ bgx; + ((u32 *)dest)[11] = (-(bits >> 4 & 1) & eorx) ^ bgx; + if (p->fontwidth < 16) + continue; + ((u32 *)dest)[12] = (-(bits >> 3 & 1) & eorx) ^ bgx; + ((u32 *)dest)[13] = (-(bits >> 2 & 1) & eorx) ^ bgx; + ((u32 *)dest)[14] = (-(bits >> 1 & 1) & eorx) ^ bgx; + ((u32 *)dest)[15] = (-(bits & 1) & eorx) ^ bgx; +#endif } - dest0 += 32; + dest0 += p->fontwidth*4; } } @@ -166,16 +220,61 @@ 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; + dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 4; + for (rows = p->fontheight; rows--; dest += bytes) { +#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY + ((u32 *)dest)[4] ^= 0xffffffff; ((u32 *)dest)[5] ^= 0xffffffff; + ((u32 *)dest)[6] ^= 0xffffffff; ((u32 *)dest)[7] ^= 0xffffffff; + ((u32 *)dest)[0] ^= 0xffffffff; ((u32 *)dest)[1] ^= 0xffffffff; + ((u32 *)dest)[2] ^= 0xffffffff; ((u32 *)dest)[3] ^= 0xffffffff; +#else + switch (p->fontwidth) { + case 16: + ((u32 *)dest)[12] ^= 0xffffffff; ((u32 *)dest)[13] ^= 0xffffffff; + ((u32 *)dest)[14] ^= 0xffffffff; ((u32 *)dest)[15] ^= 0xffffffff; + /* FALL THROUGH */ + case 12: + ((u32 *)dest)[8] ^= 0xffffffff; ((u32 *)dest)[9] ^= 0xffffffff; + ((u32 *)dest)[10] ^= 0xffffffff; ((u32 *)dest)[11] ^= 0xffffffff; + /* FALL THROUGH */ + case 8: + ((u32 *)dest)[4] ^= 0xffffffff; ((u32 *)dest)[5] ^= 0xffffffff; + ((u32 *)dest)[6] ^= 0xffffffff; ((u32 *)dest)[7] ^= 0xffffffff; + /* FALL THROUGH */ + case 4: + ((u32 *)dest)[0] ^= 0xffffffff; ((u32 *)dest)[1] ^= 0xffffffff; + ((u32 *)dest)[2] ^= 0xffffffff; ((u32 *)dest)[3] ^= 0xffffffff; + /* FALL THROUGH */ + } +#endif + } +} + +void fbcon_cfb32_clear_margins(struct vc_data *conp, struct display *p) +{ + u8 *dest0; + u32 *dest; + int bytes = p->next_line; + u32 bgx; + int i, j; + + unsigned int right_start = conp->vc_cols*p->fontwidth; + unsigned int right_width = p->var.xres_virtual-right_start; + unsigned int bottom_start = conp->vc_rows*p->fontheight; + unsigned int bottom_width = p->var.yres_virtual-bottom_start; + + bgx = fbcon_cfb32_cmap[attr_bgcol_ec(p, conp)]; + + if (right_width) { + dest0 = p->screen_base+right_start*4; + for (i = 0; i < bottom_start; i++, dest0 += bytes) + for (j = 0, dest = (u32 *)dest0; j < right_width; j++) + *dest++ = bgx; + } + if (bottom_width) { + dest = (u32 *)(p->screen_base+bottom_start*bytes); + for (i = 0; i < bytes*bottom_width/4; i++) + *dest++ = bgx; } } @@ -186,10 +285,22 @@ void fbcon_cfb32_revc(struct display *p, int xx, int yy) struct display_switch fbcon_cfb32 = { fbcon_cfb32_setup, fbcon_cfb32_bmove, fbcon_cfb32_clear, fbcon_cfb32_putc, - fbcon_cfb32_putcs, fbcon_cfb32_revc + fbcon_cfb32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_cfb32_clear_margins, + FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; +#ifdef MODULE +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{} +#endif /* MODULE */ + + /* * Visible symbols for modules */ diff --git a/drivers/video/fbcon-cfb32.h b/drivers/video/fbcon-cfb32.h index 1f74141c2..500528b04 100644 --- a/drivers/video/fbcon-cfb32.h +++ b/drivers/video/fbcon-cfb32.h @@ -2,6 +2,18 @@ * 32 bpp packed pixel (cfb32) */ +#include <linux/config.h> + +#ifdef MODULE +#if defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FBCON_CFB32_MODULE) +#define FBCON_HAS_CFB32 +#endif +#else +#if defined(CONFIG_FBCON_CFB32) +#define FBCON_HAS_CFB32 +#endif +#endif + extern struct display_switch fbcon_cfb32; extern u32 fbcon_cfb32_cmap[16]; extern void fbcon_cfb32_setup(struct display *p); @@ -12,5 +24,6 @@ extern void fbcon_cfb32_clear(struct vc_data *conp, struct display *p, int sy, 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); + const unsigned short *s, int count, int yy, int xx); extern void fbcon_cfb32_revc(struct display *p, int xx, int yy); +extern void fbcon_cfb32_clear_margins(struct vc_data *conp, struct display *p); diff --git a/drivers/video/fbcon-cfb4.c b/drivers/video/fbcon-cfb4.c index 8df065695..4d3f196bf 100644 --- a/drivers/video/fbcon-cfb4.c +++ b/drivers/video/fbcon-cfb4.c @@ -32,10 +32,20 @@ */ static u16 nibbletab_cfb4[] = { +#if defined(__BIG_ENDIAN) 0x0000,0x000f,0x00f0,0x00ff, 0x0f00,0x0f0f,0x0ff0,0x0fff, 0xf000,0xf00f,0xf0f0,0xf0ff, 0xff00,0xff0f,0xfff0,0xffff +#elif defined(__LITTLE_ENDIAN) + 0x0000,0xf000,0x0f00,0xff00, + 0x00f0,0xf0f0,0x0ff0,0xfff0, + 0x000f,0xf00f,0x0f0f,0xff0f, + 0x00ff,0xf0ff,0x0fff,0xffff +#else +#error FIXME: No endianness?? +#endif + }; void fbcon_cfb4_setup(struct display *p) @@ -120,13 +130,11 @@ void fbcon_cfb4_putc(struct vc_data *conp, struct display *p, int c, int yy, 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; + cdat = p->fontdata + (c & p->charmask) * p->fontheight; - fgx=15;/*attr_fgcol(p,conp)&0x0F;*/ - bgx=attr_bgcol(p,conp)&0x0F; + fgx=15;/*attr_fgcol(p,c);*/ + bgx=attr_bgcol(p,c); fgx |= (fgx << 4); fgx |= (fgx << 8); bgx |= (bgx << 4); @@ -141,16 +149,17 @@ void fbcon_cfb4_putc(struct vc_data *conp, struct display *p, int c, int yy, } } -void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p, const char *s, - int count, int yy, int xx) +void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int yy, int xx) { - u8 *cdat, c, *dest, *dest0; + u8 *cdat, *dest, *dest0; + u16 c; 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=15/*attr_fgcol(p,*s)*/; + bgx=attr_bgcol(p,*s); fgx |= (fgx << 4); fgx |= (fgx << 8); fgx |= (fgx << 16); @@ -159,7 +168,7 @@ void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p, const char *s, bgx |= (bgx << 16); eorx = fgx ^ bgx; while (count--) { - c = *s++; + c = *s++ & p->charmask; cdat = p->fontdata + c * p->fontheight; for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { @@ -190,10 +199,21 @@ void fbcon_cfb4_revc(struct display *p, int xx, int yy) struct display_switch fbcon_cfb4 = { fbcon_cfb4_setup, fbcon_cfb4_bmove, fbcon_cfb4_clear, fbcon_cfb4_putc, - fbcon_cfb4_putcs, fbcon_cfb4_revc + fbcon_cfb4_putcs, fbcon_cfb4_revc, NULL, NULL, NULL, FONTWIDTH(8) }; +#ifdef MODULE +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{} +#endif /* MODULE */ + + /* * Visible symbols for modules */ diff --git a/drivers/video/fbcon-cfb4.h b/drivers/video/fbcon-cfb4.h index 6fe3bc5a4..df08288cd 100644 --- a/drivers/video/fbcon-cfb4.h +++ b/drivers/video/fbcon-cfb4.h @@ -2,6 +2,18 @@ * 4 bpp packed pixel (cfb4) */ +#include <linux/config.h> + +#ifdef MODULE +#if defined(CONFIG_FBCON_CFB4) || defined(CONFIG_FBCON_CFB4_MODULE) +#define FBCON_HAS_CFB4 +#endif +#else +#if defined(CONFIG_FBCON_CFB4) +#define FBCON_HAS_CFB4 +#endif +#endif + 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, @@ -11,5 +23,5 @@ extern void fbcon_cfb4_clear(struct vc_data *conp, struct display *p, int sy, 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); + const unsigned short *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 dcd3ebd97..b4de49b3b 100644 --- a/drivers/video/fbcon-cfb8.c +++ b/drivers/video/fbcon-cfb8.c @@ -9,6 +9,7 @@ * more details. */ +#include <linux/config.h> #include <linux/module.h> #include <linux/tty.h> #include <linux/console.h> @@ -41,7 +42,7 @@ static u32 nibbletab_cfb8[] = { void fbcon_cfb8_setup(struct display *p) { - p->next_line = p->var.xres_virtual; + p->next_line = p->line_length ? p->line_length : p->var.xres_virtual; p->next_plane = 0; } @@ -51,23 +52,30 @@ void fbcon_cfb8_bmove(struct display *p, int sy, int sx, int dy, int dx, int bytes = p->next_line, linesize = bytes * p->fontheight, rows; u8 *src,*dst; - if (sx == 0 && dx == 0 && width * 8 == bytes) + if (sx == 0 && dx == 0 && width * p->fontwidth == 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 * 8; - dst = p->screen_base + dy * linesize + dx * 8; + return; + } + if (p->fontwidthlog) { + sx <<= p->fontwidthlog; dx <<= p->fontwidthlog; width <<= p->fontwidthlog; + } else { + sx *= p->fontwidth; dx *= p->fontwidth; width *= p->fontwidth; + } + if (dy < sy || (dy == sy && dx < sx)) { + src = p->screen_base + sy * linesize + sx; + dst = p->screen_base + dy * linesize + dx; for (rows = height * p->fontheight ; rows-- ;) { - mymemmove(dst, src, width * 8); + mymemmove(dst, src, width); src += bytes; dst += bytes; } } else { - src = p->screen_base + (sy+height) * linesize + sx * 8 - bytes; - dst = p->screen_base + (dy+height) * linesize + dx * 8 - bytes; + src = p->screen_base + (sy+height) * linesize + sx - bytes; + dst = p->screen_base + (dy+height) * linesize + dx - bytes; for (rows = height * p->fontheight ; rows-- ;) { - mymemmove(dst, src, width * 8); + mymemmove(dst, src, width); src -= bytes; dst -= bytes; } @@ -77,32 +85,20 @@ void fbcon_cfb8_bmove(struct display *p, int sy, int sx, int dy, int dx, void fbcon_cfb8_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; + u8 *dest; + int bytes=p->next_line,lines=height * p->fontheight, rows; + u8 bgx; - dest = p->screen_base + sy * p->fontheight * bytes + sx * 8; + dest = p->screen_base + sy * p->fontheight * bytes + sx * p->fontwidth; bgx=attr_bgcol_ec(p,conp); - bgx |= (bgx << 8); - bgx |= (bgx << 16); - if (sx == 0 && width * 8 == bytes) - for (i = 0 ; i < lines * width ; i++) { - ((u32 *)dest)[0]=bgx; - ((u32 *)dest)[1]=bgx; - dest+=8; - } + if (sx == 0 && p->fontwidth == 8 && width * 8 == bytes) + memset(dest, bgx, lines * width * p->fontwidth); 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; - dest+=8; - } - } + width *= p->fontwidth; + for (rows = lines; rows-- ; dest += bytes) + memset(dest, bgx, width); } } @@ -113,50 +109,110 @@ void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c, int yy, int bytes=p->next_line,rows; u32 eorx,fgx,bgx; - c &= 0xff; - - dest = p->screen_base + yy * p->fontheight * bytes + xx * 8; - cdat = p->fontdata + c * p->fontheight; + dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth; + if (p->fontwidth <= 8) + cdat = p->fontdata + (c & p->charmask) * p->fontheight; + else + cdat = p->fontdata + ((c & p->charmask) * p->fontheight << 1); - fgx=attr_fgcol(p,conp); - bgx=attr_bgcol(p,conp); + fgx=attr_fgcol(p,c); + bgx=attr_bgcol(p,c); fgx |= (fgx << 8); fgx |= (fgx << 16); bgx |= (bgx << 8); bgx |= (bgx << 16); eorx = fgx ^ bgx; - for (rows = p->fontheight ; rows-- ; dest += bytes) { - ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx; - ((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + switch (p->fontwidth) { + case 4: + for (rows = p->fontheight ; rows-- ; dest += bytes) + ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat++ >> 4] & eorx) ^ bgx; + break; + case 8: +#endif + for (rows = p->fontheight ; rows-- ; dest += bytes) { + ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx; + ((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx; + } +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + break; + case 12: + case 16: + for (rows = p->fontheight ; rows-- ; dest += bytes) { + ((u32 *)dest)[0]= (nibbletab_cfb8[*(u16 *)cdat >> 12] & eorx) ^ bgx; + ((u32 *)dest)[1]= (nibbletab_cfb8[(*(u16 *)cdat >> 8) & 0xf] & eorx) ^ bgx; + ((u32 *)dest)[2]= (nibbletab_cfb8[(*(u16 *)cdat >> 4) & 0xf] & eorx) ^ bgx; + if (p->fontwidth == 16) + ((u32 *)dest)[3]= (nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx; + cdat += 2; + } + break; } +#endif } -void fbcon_cfb8_putcs(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 unsigned short *s, int count, int yy, int xx) { - u8 *cdat, c, *dest, *dest0; + u8 *cdat, *dest, *dest0; + u16 c; int rows,bytes=p->next_line; u32 eorx, fgx, bgx; - dest0 = p->screen_base + yy * p->fontheight * bytes + xx * 8; - fgx=attr_fgcol(p,conp); - bgx=attr_bgcol(p,conp); + dest0 = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth; + fgx=attr_fgcol(p,*s); + bgx=attr_bgcol(p,*s); fgx |= (fgx << 8); fgx |= (fgx << 16); bgx |= (bgx << 8); bgx |= (bgx << 16); eorx = fgx ^ bgx; - while (count--) { - c = *s++; - cdat = p->fontdata + c * p->fontheight; +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + switch (p->fontwidth) { + case 4: + while (count--) { + c = *s++ & p->charmask; + cdat = p->fontdata + c * p->fontheight; - for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { - ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx; - ((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx; - } - dest0+=8; + for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) + ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat++ >> 4] & eorx) ^ bgx; + dest0+=4; + } + break; + case 8: +#endif + while (count--) { + c = *s++ & p->charmask; + cdat = p->fontdata + c * p->fontheight; + + for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { + ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx; + ((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx; + } + dest0+=8; + } +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + break; + case 12: + case 16: + while (count--) { + c = *s++ & p->charmask; + cdat = p->fontdata + (c * p->fontheight << 1); + + for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { + ((u32 *)dest)[0]= (nibbletab_cfb8[*(u16 *)cdat >> 12] & eorx) ^ bgx; + ((u32 *)dest)[1]= (nibbletab_cfb8[(*(u16 *)cdat >> 8) & 0xf] & eorx) ^ bgx; + ((u32 *)dest)[2]= (nibbletab_cfb8[(*(u16 *)cdat >> 4) & 0xf] & eorx) ^ bgx; + if (p->fontwidth == 16) + ((u32 *)dest)[3]= (nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx; + cdat += 2; + } + dest0+=p->fontwidth; + } + break; } +#endif } void fbcon_cfb8_revc(struct display *p, int xx, int yy) @@ -164,11 +220,44 @@ void fbcon_cfb8_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 * 8; + dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth; for (rows = p->fontheight ; rows-- ; dest += bytes) { - ((u32 *)dest)[0] ^= 0x0f0f0f0f; - ((u32 *)dest)[1] ^= 0x0f0f0f0f; +#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY + ((u32 *)dest)[1] ^= 0x0f0f0f0f; + ((u32 *)dest)[0] ^= 0x0f0f0f0f; +#else + switch (p->fontwidth) { + case 16: ((u32 *)dest)[3] ^= 0x0f0f0f0f; /* FALL THROUGH */ + case 12: ((u32 *)dest)[2] ^= 0x0f0f0f0f; /* FALL THROUGH */ + case 8: ((u32 *)dest)[1] ^= 0x0f0f0f0f; /* FALL THROUGH */ + case 4: ((u32 *)dest)[0] ^= 0x0f0f0f0f; /* FALL THROUGH */ + default: break; + } +#endif + } +} + +void fbcon_cfb8_clear_margins(struct vc_data *conp, struct display *p) +{ + u8 *dest; + int bytes=p->next_line; + u8 bgx; + int i; + + unsigned int right_start = conp->vc_cols*p->fontwidth; + unsigned int right_width = p->var.xres_virtual-right_start; + unsigned int bottom_start = conp->vc_rows*p->fontheight; + unsigned int bottom_width = p->var.yres_virtual-bottom_start; + + bgx=attr_bgcol_ec(p,conp); + + if (right_width) { + dest = p->screen_base+right_start; + for (i = 0; i < bottom_start; i++, dest += bytes) + memset(dest, bgx, right_width); } + if (bottom_width) + memset(p->screen_base+bottom_start*bytes, bgx, bytes*bottom_width); } @@ -178,10 +267,22 @@ void fbcon_cfb8_revc(struct display *p, int xx, int yy) struct display_switch fbcon_cfb8 = { fbcon_cfb8_setup, fbcon_cfb8_bmove, fbcon_cfb8_clear, fbcon_cfb8_putc, - fbcon_cfb8_putcs, fbcon_cfb8_revc + fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins, + FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) }; +#ifdef MODULE +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{} +#endif /* MODULE */ + + /* * Visible symbols for modules */ diff --git a/drivers/video/fbcon-cfb8.h b/drivers/video/fbcon-cfb8.h index 4c0ffec99..e1d8170ed 100644 --- a/drivers/video/fbcon-cfb8.h +++ b/drivers/video/fbcon-cfb8.h @@ -2,6 +2,18 @@ * 8 bpp packed pixel (cfb8) */ +#include <linux/config.h> + +#ifdef MODULE +#if defined(CONFIG_FBCON_CFB8) || defined(CONFIG_FBCON_CFB8_MODULE) +#define FBCON_HAS_CFB8 +#endif +#else +#if defined(CONFIG_FBCON_CFB8) +#define FBCON_HAS_CFB8 +#endif +#endif + 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, @@ -11,5 +23,6 @@ extern void fbcon_cfb8_clear(struct vc_data *conp, struct display *p, int sy, 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); + const unsigned short *s, int count, int yy, int xx); extern void fbcon_cfb8_revc(struct display *p, int xx, int yy); +extern void fbcon_cfb8_clear_margins(struct vc_data *conp, struct display *p); diff --git a/drivers/video/fbcon-ilbm.c b/drivers/video/fbcon-ilbm.c index 82f9982f6..b87a1d10c 100644 --- a/drivers/video/fbcon-ilbm.c +++ b/drivers/video/fbcon-ilbm.c @@ -102,12 +102,10 @@ void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c, int yy, u8 d; int fg0, bg0, fg, bg; - c &= 0xff; - dest = p->screen_base+yy*p->fontheight*p->next_line+xx; - cdat = p->fontdata+c*p->fontheight; - fg0 = attr_fgcol(p,conp); - bg0 = attr_bgcol(p,conp); + cdat = p->fontdata+(c&p->charmask)*p->fontheight; + fg0 = attr_fgcol(p,c); + bg0 = attr_bgcol(p,c); for (rows = p->fontheight; rows--;) { d = *cdat++; @@ -146,22 +144,22 @@ void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c, int yy, * -- Geert */ -void fbcon_ilbm_putcs(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 unsigned short *s, int count, int yy, int xx) { u8 *dest0, *dest, *cdat1, *cdat2, *cdat3, *cdat4; u_int rows, i; - u8 c1, c2, c3, c4; + u16 c1, c2, c3, c4; u32 d; int fg0, bg0, fg, bg; dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx; - fg0 = attr_fgcol(p,conp); - bg0 = attr_bgcol(p,conp); + fg0 = attr_fgcol(p,*s); + bg0 = attr_bgcol(p,*s); while (count--) if (xx&3 || count < 3) { /* Slow version */ - c1 = *s++; + c1 = *s++ & p->charmask; dest = dest0++; xx++; @@ -187,10 +185,10 @@ void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p, const char *s, } } } else { /* Fast version */ - c1 = s[0]; - c2 = s[1]; - c3 = s[2]; - c4 = s[3]; + c1 = s[0] & p->charmask; + c2 = s[1] & p->charmask; + c3 = s[2] & p->charmask; + c4 = s[3] & p->charmask; dest = dest0; cdat1 = p->fontdata+c1*p->fontheight; @@ -201,7 +199,7 @@ void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p, const char *s, #if defined(__BIG_ENDIAN) d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++; #elif defined(__LITTLE_ENDIAN) - d = *cdat1++ | *cdat2++<<8 | *cdat3++<<16 | *cdat4++<<32); + d = *cdat1++ | *cdat2++<<8 | *cdat3++<<16 | *cdat4++<<24; #else #error FIXME: No endianness?? #endif @@ -262,10 +260,21 @@ void fbcon_ilbm_revc(struct display *p, int xx, int yy) struct display_switch fbcon_ilbm = { fbcon_ilbm_setup, fbcon_ilbm_bmove, fbcon_ilbm_clear, fbcon_ilbm_putc, - fbcon_ilbm_putcs, fbcon_ilbm_revc + fbcon_ilbm_putcs, fbcon_ilbm_revc, NULL, NULL, NULL, FONTWIDTH(8) }; +#ifdef MODULE +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{} +#endif /* MODULE */ + + /* * Visible symbols for modules */ diff --git a/drivers/video/fbcon-ilbm.h b/drivers/video/fbcon-ilbm.h index e2434c7d1..13292f287 100644 --- a/drivers/video/fbcon-ilbm.h +++ b/drivers/video/fbcon-ilbm.h @@ -2,6 +2,18 @@ * Amiga interleaved bitplanes (ilbm) */ +#include <linux/config.h> + +#ifdef MODULE +#if defined(CONFIG_FBCON_ILBM) || defined(CONFIG_FBCON_ILBM_MODULE) +#define FBCON_HAS_ILBM +#endif +#else +#if defined(CONFIG_FBCON_ILBM) +#define FBCON_HAS_ILBM +#endif +#endif + 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, @@ -11,5 +23,5 @@ extern void fbcon_ilbm_clear(struct vc_data *conp, struct display *p, int sy, 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); + const unsigned short *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 adef5819d..3cd8ab81e 100644 --- a/drivers/video/fbcon-iplan2p2.c +++ b/drivers/video/fbcon-iplan2p2.c @@ -1,7 +1,7 @@ /* - * linux/drivers/video/iplan2p2.c -- Low level frame buffer operations for - * interleaved bitplanes à la Atari (2 - * planes, 2 bytes interleave) + * linux/drivers/video/fbcon-iplan2p2.c -- Low level frame buffer operations + * for interleaved bitplanes à la Atari (2 + * planes, 2 bytes interleave) * * Created 5 Apr 1997 by Geert Uytterhoeven * @@ -10,11 +10,11 @@ * more details. */ +#include <linux/config.h> #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 <asm/byteorder.h> @@ -52,7 +52,7 @@ static inline void movepw(u8 *d, u16 val) } /* 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 + * val for a 2 plane screen. The bits of the color in 'color' are * moved (8 times) to the respective bytes. This means: * * for(h times; d += bpr) @@ -306,13 +306,11 @@ void fbcon_iplan2p2_putc(struct vc_data *conp, struct display *p, int c, int bytes = p->next_line; u16 eorx, fgx, bgx, fdx; - c &= 0xff; - dest = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*4 + (xx & 1); - cdat = p->fontdata + (c * p->fontheight); + cdat = p->fontdata + (c & p->charmask) * p->fontheight; - fgx = expand2w(COLOR_2P(attr_fgcol(p,conp))); - bgx = expand2w(COLOR_2P(attr_bgcol(p,conp))); + fgx = expand2w(COLOR_2P(attr_fgcol(p,c))); + bgx = expand2w(COLOR_2P(attr_bgcol(p,c))); eorx = fgx ^ bgx; for (rows = p->fontheight ; rows-- ; dest += bytes) { @@ -322,22 +320,23 @@ void fbcon_iplan2p2_putc(struct vc_data *conp, struct display *p, int c, } void fbcon_iplan2p2_putcs(struct vc_data *conp, struct display *p, - const char *s, int count, int yy, int xx) + const unsigned short *s, int count, int yy, int xx) { u8 *dest, *dest0; - u8 *cdat, c; + u8 *cdat; + u16 c; int rows; int bytes; u16 eorx, fgx, bgx, fdx; bytes = p->next_line; dest0 = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*4 + (xx & 1); - fgx = expand2w(COLOR_2P(attr_fgcol(p,conp))); - bgx = expand2w(COLOR_2P(attr_bgcol(p,conp))); + fgx = expand2w(COLOR_2P(attr_fgcol(p,*s))); + bgx = expand2w(COLOR_2P(attr_bgcol(p,*s))); eorx = fgx ^ bgx; while (count--) { - c = *s++; + c = *s++ & p->charmask; cdat = p->fontdata + (c * p->fontheight); for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { @@ -376,10 +375,22 @@ void fbcon_iplan2p2_revc(struct display *p, int xx, int yy) struct display_switch fbcon_iplan2p2 = { fbcon_iplan2p2_setup, fbcon_iplan2p2_bmove, fbcon_iplan2p2_clear, - fbcon_iplan2p2_putc, fbcon_iplan2p2_putcs, fbcon_iplan2p2_revc + fbcon_iplan2p2_putc, fbcon_iplan2p2_putcs, fbcon_iplan2p2_revc, NULL, + NULL, NULL, FONTWIDTH(8) }; +#ifdef MODULE +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{} +#endif /* MODULE */ + + /* * Visible symbols for modules */ diff --git a/drivers/video/fbcon-iplan2p2.h b/drivers/video/fbcon-iplan2p2.h index ae18a1b32..07b5a0d31 100644 --- a/drivers/video/fbcon-iplan2p2.h +++ b/drivers/video/fbcon-iplan2p2.h @@ -2,6 +2,18 @@ * Atari interleaved bitplanes (2 planes) (iplan2p2) */ +#include <linux/config.h> + +#ifdef MODULE +#if defined(CONFIG_FBCON_IPLAN2P2) || defined(CONFIG_FBCON_IPLAN2P2_MODULE) +#define FBCON_HAS_IPLAN2P2 +#endif +#else +#if defined(CONFIG_FBCON_IPLAN2P2) +#define FBCON_HAS_IPLAN2P2 +#endif +#endif + 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, @@ -11,5 +23,5 @@ extern void fbcon_iplan2p2_clear(struct vc_data *conp, struct display *p, 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); + const unsigned short *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 b299701c4..4bd21c366 100644 --- a/drivers/video/fbcon-iplan2p4.c +++ b/drivers/video/fbcon-iplan2p4.c @@ -1,7 +1,7 @@ /* - * linux/drivers/video/iplan2p4.c -- Low level frame buffer operations for - * interleaved bitplanes à la Atari (4 - * planes, 2 bytes interleave) + * linux/drivers/video/fbcon-iplan2p4.c -- Low level frame buffer operations + * for interleaved bitplanes à la Atari (4 + * planes, 2 bytes interleave) * * Created 5 Apr 1997 by Geert Uytterhoeven * @@ -10,11 +10,11 @@ * more details. */ +#include <linux/config.h> #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 <asm/byteorder.h> @@ -46,7 +46,7 @@ static inline void movepl(u8 *d, u32 val) } /* 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 + * val for a 4 plane screen. The bits of the color in 'color' are * moved (8 times) to the respective bytes. This means: * * for(h times; d += bpr) @@ -316,13 +316,11 @@ void fbcon_iplan2p4_putc(struct vc_data *conp, struct display *p, int c, int bytes = p->next_line; u32 eorx, fgx, bgx, fdx; - c &= 0xff; - dest = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*8 + (xx & 1); - cdat = p->fontdata + (c * p->fontheight); + cdat = p->fontdata + (c & p->charmask) * p->fontheight; - fgx = expand4l(attr_fgcol(p,conp)); - bgx = expand4l(attr_bgcol(p,conp)); + fgx = expand4l(attr_fgcol(p,c)); + bgx = expand4l(attr_bgcol(p,c)); eorx = fgx ^ bgx; for(rows = p->fontheight ; rows-- ; dest += bytes) { @@ -332,18 +330,19 @@ void fbcon_iplan2p4_putc(struct vc_data *conp, struct display *p, int c, } void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p, - const char *s, int count, int yy, int xx) + const unsigned short *s, int count, int yy, int xx) { u8 *dest, *dest0; - u8 *cdat, c; + u8 *cdat; + u16 c; int rows; int bytes; u32 eorx, fgx, bgx, fdx; bytes = p->next_line; dest0 = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*8 + (xx & 1); - fgx = expand4l(attr_fgcol(p,conp)); - bgx = expand4l(attr_bgcol(p,conp)); + fgx = expand4l(attr_fgcol(p,*s)); + bgx = expand4l(attr_bgcol(p,*s)); eorx = fgx ^ bgx; while (count--) { @@ -354,7 +353,7 @@ void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p, * cache :-( */ - c = *s++; + c = *s++ & p->charmask; cdat = p->fontdata + (c * p->fontheight); for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { @@ -396,10 +395,22 @@ void fbcon_iplan2p4_revc(struct display *p, int xx, int yy) struct display_switch fbcon_iplan2p4 = { fbcon_iplan2p4_setup, fbcon_iplan2p4_bmove, fbcon_iplan2p4_clear, - fbcon_iplan2p4_putc, fbcon_iplan2p4_putcs, fbcon_iplan2p4_revc + fbcon_iplan2p4_putc, fbcon_iplan2p4_putcs, fbcon_iplan2p4_revc, NULL, + NULL, NULL, FONTWIDTH(8) }; +#ifdef MODULE +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{} +#endif /* MODULE */ + + /* * Visible symbols for modules */ diff --git a/drivers/video/fbcon-iplan2p4.h b/drivers/video/fbcon-iplan2p4.h index ae3b38494..6d501a58e 100644 --- a/drivers/video/fbcon-iplan2p4.h +++ b/drivers/video/fbcon-iplan2p4.h @@ -2,6 +2,18 @@ * Atari interleaved bitplanes (4 planes) (iplan2p4) */ +#include <linux/config.h> + +#ifdef MODULE +#if defined(CONFIG_FBCON_IPLAN2P4) || defined(CONFIG_FBCON_IPLAN2P4_MODULE) +#define FBCON_HAS_IPLAN2P4 +#endif +#else +#if defined(CONFIG_FBCON_IPLAN2P4) +#define FBCON_HAS_IPLAN2P4 +#endif +#endif + 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, @@ -11,5 +23,5 @@ extern void fbcon_iplan2p4_clear(struct vc_data *conp, struct display *p, 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); + const unsigned short *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 5ea15c26b..aa2f4d2f1 100644 --- a/drivers/video/fbcon-iplan2p8.c +++ b/drivers/video/fbcon-iplan2p8.c @@ -10,11 +10,11 @@ * more details. */ +#include <linux/config.h> #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 <asm/byteorder.h> @@ -348,13 +348,11 @@ void fbcon_iplan2p8_putc(struct vc_data *conp, struct display *p, int c, int bytes = p->next_line; u32 eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx; - c &= 0xff; - dest = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*16 + (xx & 1); - cdat = p->fontdata + (c * p->fontheight); + cdat = p->fontdata + (c & p->charmask) * p->fontheight; - expand8dl(attr_fgcol(p,conp), &fgx1, &fgx2); - expand8dl(attr_bgcol(p,conp), &bgx1, &bgx2); + expand8dl(attr_fgcol(p,c), &fgx1, &fgx2); + expand8dl(attr_bgcol(p,c), &bgx1, &bgx2); eorx1 = fgx1 ^ bgx1; eorx2 = fgx2 ^ bgx2; for(rows = p->fontheight ; rows-- ; dest += bytes) { @@ -364,10 +362,11 @@ void fbcon_iplan2p8_putc(struct vc_data *conp, struct display *p, int c, } void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p, - const char *s, int count, int yy, int xx) + const unsigned short *s, int count, int yy, int xx) { u8 *dest, *dest0; - u8 *cdat, c; + u8 *cdat; + u16 c; int rows; int bytes; u32 eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx; @@ -376,8 +375,8 @@ void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p, dest0 = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*16 + (xx & 1); - expand8dl(attr_fgcol(p,conp), &fgx1, &fgx2); - expand8dl(attr_bgcol(p,conp), &bgx1, &bgx2); + expand8dl(attr_fgcol(p,*s), &fgx1, &fgx2); + expand8dl(attr_bgcol(p,*s), &bgx1, &bgx2); eorx1 = fgx1 ^ bgx1; eorx2 = fgx2 ^ bgx2; while (count--) { @@ -389,7 +388,7 @@ void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p, * cache :-( */ - c = *s++; + c = *s++ & p->charmask; cdat = p->fontdata + (c * p->fontheight); for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { @@ -433,10 +432,22 @@ void fbcon_iplan2p8_revc(struct display *p, int xx, int yy) struct display_switch fbcon_iplan2p8 = { fbcon_iplan2p8_setup, fbcon_iplan2p8_bmove, fbcon_iplan2p8_clear, - fbcon_iplan2p8_putc, fbcon_iplan2p8_putcs, fbcon_iplan2p8_revc + fbcon_iplan2p8_putc, fbcon_iplan2p8_putcs, fbcon_iplan2p8_revc, NULL, + NULL, NULL, FONTWIDTH(8) }; +#ifdef MODULE +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{} +#endif /* MODULE */ + + /* * Visible symbols for modules */ diff --git a/drivers/video/fbcon-iplan2p8.h b/drivers/video/fbcon-iplan2p8.h index f2c46e229..ba298f84c 100644 --- a/drivers/video/fbcon-iplan2p8.h +++ b/drivers/video/fbcon-iplan2p8.h @@ -2,6 +2,18 @@ * Atari interleaved bitplanes (8 planes) (iplan2p8) */ +#include <linux/config.h> + +#ifdef MODULE +#if defined(CONFIG_FBCON_IPLAN2P8) || defined(CONFIG_FBCON_IPLAN2P8_MODULE) +#define FBCON_HAS_IPLAN2P8 +#endif +#else +#if defined(CONFIG_FBCON_IPLAN2P8) +#define FBCON_HAS_IPLAN2P8 +#endif +#endif + 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, @@ -11,5 +23,5 @@ extern void fbcon_iplan2p8_clear(struct vc_data *conp, struct display *p, 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); + const unsigned short *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 index 5518e5def..a4bac8fae 100644 --- a/drivers/video/fbcon-mac.c +++ b/drivers/video/fbcon-mac.c @@ -90,11 +90,15 @@ void fbcon_mac_bmove(struct display *p, int sy, int sx, int dy, int dx, w = (r&~7) - ((l+7)&~7); dw = (dr&~7) - ((dl+7)&~7); if (lo != dlo) { - char err_str[256]; - unsigned long cnt; + unsigned char err_str[128]; + unsigned short err_buf[256]; + unsigned long cnt, len; 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); + len = strlen(err_str); + for (cnt = 0; cnt < len; cnt++) + err_buf[cnt] = 0x700 | err_str[cnt]; + fbcon_mac_putcs(p->conp, p, err_buf, len, 0, 0); /* pause for the user */ for(cnt = 0; cnt < 50000; cnt++) udelay(100); @@ -191,7 +195,7 @@ void fbcon_mac_clear(struct vc_data *conp, struct display *p, int sy, int sx, u8 *dest; int l,r,t,b,w,lo,s; - inverse = attr_reverse(p,conp); + inverse = attr_reverse(p,conp->vc_attr); pixel = inverse ? PIXEL_WHITE_MAC : PIXEL_BLACK_MAC; dest = (u8 *) (p->screen_base + sy * p->fontheight * p->next_line); @@ -268,12 +272,10 @@ void fbcon_mac_putc(struct vc_data *conp, struct display *p, int c, int yy, 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); + cdat = p->fontdata+(c&p->charmask)*p->fontheight; + bold = attr_bold(p,c); + ch_reverse = attr_reverse(p,c); + ch_underline = attr_underline(p,c); for (rows = 0; rows < p->fontheight; rows++) { d = *cdat++; @@ -293,10 +295,10 @@ void fbcon_mac_putc(struct vc_data *conp, struct display *p, int c, int yy, } -void fbcon_mac_putcs(struct vc_data *conp, struct display *p, const char *s, - int count, int yy, int xx) +void fbcon_mac_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int yy, int xx) { - u8 c; + u16 c; while (count--) { c = *s++; @@ -495,10 +497,21 @@ static int get_pixel_mac(struct display *p, int pixel_x, int pixel_y) struct display_switch fbcon_mac = { fbcon_mac_setup, fbcon_mac_bmove, fbcon_mac_clear, fbcon_mac_putc, - fbcon_mac_putcs, fbcon_mac_revc + fbcon_mac_putcs, fbcon_mac_revc, NULL, NULL, NULL, FONTWIDTHRANGE(1,8) }; +#ifdef MODULE +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{} +#endif /* MODULE */ + + /* * Visible symbols for modules */ diff --git a/drivers/video/fbcon-mac.h b/drivers/video/fbcon-mac.h index 7e807cce9..62d2ae6d3 100644 --- a/drivers/video/fbcon-mac.h +++ b/drivers/video/fbcon-mac.h @@ -2,6 +2,18 @@ * Mac variable bpp packed pixels (mac) */ +#include <linux/config.h> + +#ifdef MODULE +#if defined(CONFIG_FBCON_MAC) || defined(CONFIG_FBCON_MAC_MODULE) +#define FBCON_HAS_MAC +#endif +#else +#if defined(CONFIG_FBCON_MAC) +#define FBCON_HAS_MAC +#endif +#endif + 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, @@ -11,5 +23,5 @@ extern void fbcon_mac_clear(struct vc_data *conp, struct display *p, int sy, 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); + const unsigned short *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 60ef11221..b8f575859 100644 --- a/drivers/video/fbcon-mfb.c +++ b/drivers/video/fbcon-mfb.c @@ -70,13 +70,13 @@ void fbcon_mfb_clear(struct vc_data *conp, struct display *p, int sy, int sx, dest = p->screen_base+sy*p->fontheight*p->next_line+sx; if (sx == 0 && width == p->next_line) { - if (attr_reverse(p,conp)) + if (attr_reverse(p,conp->vc_attr)) mymemset(dest, height*p->fontheight*width); else mymemclear(dest, height*p->fontheight*width); } else for (rows = height*p->fontheight; rows--; dest += p->next_line) - if (attr_reverse(p,conp)) + if (attr_reverse(p,conp->vc_attr)) mymemset(dest, width); else mymemclear_small(dest, width); @@ -89,13 +89,11 @@ void fbcon_mfb_putc(struct vc_data *conp, struct display *p, int c, int yy, u_int rows, bold, revs, underl; u8 d; - c &= 0xff; - dest = p->screen_base+yy*p->fontheight*p->next_line+xx; - cdat = p->fontdata+c*p->fontheight; - bold = attr_bold(p,conp); - revs = attr_reverse(p,conp); - underl = attr_underline(p,conp); + cdat = p->fontdata+(c&p->charmask)*p->fontheight; + bold = attr_bold(p,c); + revs = attr_reverse(p,c); + underl = attr_underline(p,c); for (rows = p->fontheight; rows--; dest += p->next_line) { d = *cdat++; @@ -109,20 +107,21 @@ void fbcon_mfb_putc(struct vc_data *conp, struct display *p, int c, int yy, } } -void fbcon_mfb_putcs(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 unsigned short *s, int count, int yy, int xx) { u8 *dest, *dest0, *cdat; u_int rows, bold, revs, underl; - u8 c, d; + u8 d; + u16 c; dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx; - bold = attr_bold(p,conp); - revs = attr_reverse(p,conp); - underl = attr_underline(p,conp); + bold = attr_bold(p,*s); + revs = attr_reverse(p,*s); + underl = attr_underline(p,*s); while (count--) { - c = *s++; + c = *s++ & p->charmask; dest = dest0++; cdat = p->fontdata+c*p->fontheight; for (rows = p->fontheight; rows--; dest += p->next_line) { @@ -155,10 +154,21 @@ void fbcon_mfb_revc(struct display *p, int xx, int yy) struct display_switch fbcon_mfb = { fbcon_mfb_setup, fbcon_mfb_bmove, fbcon_mfb_clear, fbcon_mfb_putc, - fbcon_mfb_putcs, fbcon_mfb_revc + fbcon_mfb_putcs, fbcon_mfb_revc, NULL, NULL, NULL, FONTWIDTH(8) }; +#ifdef MODULE +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{} +#endif /* MODULE */ + + /* * Visible symbols for modules */ diff --git a/drivers/video/fbcon-mfb.h b/drivers/video/fbcon-mfb.h index b67d9f70e..77f312e31 100644 --- a/drivers/video/fbcon-mfb.h +++ b/drivers/video/fbcon-mfb.h @@ -2,6 +2,18 @@ * Monochrome (mfb) */ +#include <linux/config.h> + +#ifdef MODULE +#if defined(CONFIG_FBCON_MFB) || defined(CONFIG_FBCON_MFB_MODULE) +#define FBCON_HAS_MFB +#endif +#else +#if defined(CONFIG_FBCON_MFB) +#define FBCON_HAS_MFB +#endif +#endif + 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, @@ -11,5 +23,5 @@ extern void fbcon_mfb_clear(struct vc_data *conp, struct display *p, int sy, 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); + const unsigned short *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-vga.c b/drivers/video/fbcon-vga.c new file mode 100644 index 000000000..3ea8a5234 --- /dev/null +++ b/drivers/video/fbcon-vga.c @@ -0,0 +1,206 @@ +/* + * linux/drivers/video/fbcon-vga.c -- Low level frame buffer operations for + * VGA characters/attributes + * + * Created 28 Mar 1998 by Geert Uytterhoeven + * Monochrome attributes added May 1998 by Andrew Apted + * + * 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 <asm/io.h> + +#include "fbcon.h" +#include "fbcon-vga.h" + + + /* + * VGA screen access + */ + +static inline void vga_writew(u16 val, u16 *addr) +{ +#ifdef __powerpc__ + st_le16(addr, val); +#else + writew(val, (unsigned long)addr); +#endif /* !__powerpc__ */ +} + +static inline u16 vga_readw(u16 *addr) +{ +#ifdef __powerpc__ + return ld_le16(addr); +#else + return readw((unsigned long)addr); +#endif /* !__powerpc__ */ +} + +static inline void vga_memsetw(void *s, u16 c, unsigned int count) +{ + u16 *addr = (u16 *)s; + + while (count) { + count--; + vga_writew(c, addr++); + } +} + +static inline void vga_memmovew(u16 *to, u16 *from, unsigned int count) +{ + if (to < from) { + while (count) { + count--; + vga_writew(vga_readw(from++), to++); + } + } else { + from += count; + to += count; + while (count) { + count--; + vga_writew(vga_readw(--from), --to); + } + } +} + + + /* + * VGA characters/attributes + */ + +static inline u16 fbcon_vga_attr(struct display *p, + unsigned short s) +{ + /* Underline and reverse-video are mutually exclusive on MDA. + * Since reverse-video is used for cursors and selected areas, + * it takes precedence. + */ + + return (attr_reverse(p, s) ? 0x7000 : + (attr_underline(p, s) ? 0x0100 : 0x0700)) | + (attr_bold(p, s) ? 0x0800 : 0) | + (attr_blink(p, s) ? 0x8000 : 0); +} + +void fbcon_vga_setup(struct display *p) +{ + p->next_line = p->line_length; + p->next_plane = 0; +} + +void fbcon_vga_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) +{ + u16 *src, *dst; + int rows; + + if (sx == 0 && dx == 0 && width == p->next_line/2) { + src = (u16 *)(p->screen_base+sy*p->next_line); + dst = (u16 *)(p->screen_base+dy*p->next_line); + vga_memmovew(dst, src, height*width); + } else if (dy < sy || (dy == sy && dx < sx)) { + src = (u16 *)(p->screen_base+sy*p->next_line+sx*2); + dst = (u16 *)(p->screen_base+dy*p->next_line+dx*2); + for (rows = height; rows-- ;) { + vga_memmovew(dst, src, width); + src += p->next_line/2; + dst += p->next_line/2; + } + } else { + src = (u16 *)(p->screen_base+(sy+height-1)*p->next_line+sx*2); + dst = (u16 *)(p->screen_base+(dy+height-1)*p->next_line+dx*2); + for (rows = height; rows-- ;) { + vga_memmovew(dst, src, width); + src -= p->next_line/2; + dst -= p->next_line/2; + } + } +} + +void fbcon_vga_clear(struct vc_data *conp, struct display *p, int sy, int sx, + int height, int width) +{ + u16 *dest = (u16 *)(p->screen_base+sy*p->next_line+sx*2); + int rows; + + if (sx == 0 && width*2 == p->next_line) + vga_memsetw(dest, conp->vc_video_erase_char, height*width); + else + for (rows = height; rows-- ; dest += p->next_line/2) + vga_memsetw(dest, conp->vc_video_erase_char, width); +} + +void fbcon_vga_putc(struct vc_data *conp, struct display *p, int c, int y, + int x) +{ + u16 *dst = (u16 *)(p->screen_base+y*p->next_line+x*2); + if (conp->vc_can_do_color) + vga_writew(c, dst); + else + vga_writew(fbcon_vga_attr(p, c) | (c & 0xff), dst); +} + +void fbcon_vga_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int y, int x) +{ + u16 *dst = (u16 *)(p->screen_base+y*p->next_line+x*2); + u16 sattr; + if (conp->vc_can_do_color) + while (count--) + vga_writew(*s++, dst++); + else { + sattr = fbcon_vga_attr(p, *s); + while (count--) + vga_writew(sattr | ((int) (*s++) & 0xff), dst++); + } +} + +void fbcon_vga_revc(struct display *p, int x, int y) +{ + u16 *dst = (u16 *)(p->screen_base+y*p->next_line+x*2); + u16 val = vga_readw(dst); + val = (val & 0x88ff) | ((val<<4) & 0x7000) | ((val>>4) & 0x0700); + vga_writew(val, dst); +} + + + /* + * `switch' for the low level operations + */ + +struct display_switch fbcon_vga = { + fbcon_vga_setup, fbcon_vga_bmove, fbcon_vga_clear, fbcon_vga_putc, + fbcon_vga_putcs, fbcon_vga_revc, NULL, NULL, NULL, FONTWIDTH(8) +}; + + +#ifdef MODULE +int init_module(void) +{ + return 0; +} + +void cleanup_module(void) +{} +#endif /* MODULE */ + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(fbcon_vga); +EXPORT_SYMBOL(fbcon_vga_setup); +EXPORT_SYMBOL(fbcon_vga_bmove); +EXPORT_SYMBOL(fbcon_vga_clear); +EXPORT_SYMBOL(fbcon_vga_putc); +EXPORT_SYMBOL(fbcon_vga_putcs); +EXPORT_SYMBOL(fbcon_vga_revc); diff --git a/drivers/video/fbcon-vga.h b/drivers/video/fbcon-vga.h new file mode 100644 index 000000000..7d62e213c --- /dev/null +++ b/drivers/video/fbcon-vga.h @@ -0,0 +1,27 @@ + /* + * VGA characters/attributes + */ + +#include <linux/config.h> + +#ifdef MODULE +#if defined(CONFIG_FBCON_VGA) || defined(CONFIG_FBCON_VGA_MODULE) +#define FBCON_HAS_VGA +#endif +#else +#if defined(CONFIG_FBCON_VGA) +#define FBCON_HAS_VGA +#endif +#endif + +extern struct display_switch fbcon_vga; +extern void fbcon_vga_setup(struct display *p); +extern void fbcon_vga_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width); +extern void fbcon_vga_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width); +extern void fbcon_vga_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +extern void fbcon_vga_putcs(struct vc_data *conp, struct display *p, + const unsigned short *s, int count, int yy, int xx); +extern void fbcon_vga_revc(struct display *p, int xx, int yy); diff --git a/drivers/video/fbcon.c b/drivers/video/fbcon.c index a41bf081d..cdec5a29d 100644 --- a/drivers/video/fbcon.c +++ b/drivers/video/fbcon.c @@ -24,6 +24,11 @@ * Martin Schaller * Andreas Schwab * + * Hardware cursor support added by Emmanuel Marty (core@ggi-project.org) + * Smart redraw scrolling, arbitrary font width support, 512char font support + * added by + * Jakub Jelinek (jj@ultra.linux.cz) + * * * The low level operations for the various display memory organizations are * now in separate source files. @@ -35,11 +40,11 @@ * o ilbm Amiga interleaved bitplanes * o iplan2p[248] Atari interleaved bitplanes * o mfb Monochrome + * o vga VGA characters/attributes * * To do: * * - Implement 16 plane mode (iplan2p16) - * - Hardware cursor * * * This file is subject to the terms and conditions of the GNU General Public @@ -49,7 +54,6 @@ #undef FBCONDEBUG -#define SUPPORT_SCROLLBACK 0 #define FLASHING_CURSOR 1 #include <linux/config.h> @@ -67,6 +71,7 @@ #include <linux/fb.h> #include <linux/vt_kern.h> #include <linux/selection.h> +#include <linux/smp.h> #include <linux/init.h> #include <asm/irq.h> @@ -82,10 +87,11 @@ #ifdef CONFIG_MAC #include <asm/macints.h> #endif -#ifdef __mc68000__ +#if defined(__mc68000__) || defined(CONFIG_APUS) #include <asm/machdep.h> #include <asm/setup.h> #endif +#define INCLUDE_LINUX_LOGO_DATA #include <asm/linux_logo.h> #include "fbcon.h" @@ -98,11 +104,21 @@ # define DPRINTK(fmt, args...) #endif -struct display fb_display[MAX_NR_CONSOLES]; +#define LOGO_H 80 +#define LOGO_W 80 +#define LOGO_LINE (LOGO_W/8) +struct display fb_display[MAX_NR_CONSOLES]; +static int logo_lines; +static int logo_shown = -1; -/* ++Geert: Sorry, no hardware cursor support at the moment; - use Atari alike software cursor */ +/* + * Emmanuel: fbcon will now use a hardware cursor if the + * low-level driver provides a non-NULL dispsw->cursor pointer, + * in which case the hardware should do blinking, etc. + * + * if dispsw->cursor is NULL, use Atari alike software cursor + */ #if FLASHING_CURSOR static int cursor_drawn = 0; @@ -119,13 +135,10 @@ static int vbl_cursor_cnt = 0; static int cursor_on = 0; static int cursor_blink_rate; -static __inline__ int CURSOR_UNDRAWN(void) +static __inline__ void CURSOR_UNDRAWN(void) { - int cursor_was_drawn; vbl_cursor_cnt = 0; - cursor_was_drawn = cursor_drawn; cursor_drawn = 0; - return(cursor_was_drawn); } #endif @@ -133,10 +146,6 @@ static __inline__ int CURSOR_UNDRAWN(void) * Scroll Method */ -#define SCROLL_YWRAP (0) -#define SCROLL_YPAN (1) -#define SCROLL_YMOVE (2) - #define divides(a, b) ((!(a) || (b)%(a)) ? 0 : 1) @@ -144,49 +153,41 @@ static __inline__ int CURSOR_UNDRAWN(void) * Interface used by the world */ -static unsigned long fbcon_startup(unsigned long kmem_start, - const char **display_desc); -static void fbcon_init(struct vc_data *conp); +static const char *fbcon_startup(void); +static void fbcon_init(struct vc_data *conp, int init); static void fbcon_deinit(struct vc_data *conp); static int fbcon_changevar(int con); static void fbcon_clear(struct vc_data *conp, int sy, int sx, 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, +static void fbcon_putcs(struct vc_data *conp, const unsigned short *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, +static int 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_blank(struct vc_data *conp, int blank); +static int fbcon_font_op(struct vc_data *conp, struct console_font_op *op); static int fbcon_set_palette(struct vc_data *conp, unsigned char *table); -static int fbcon_scrolldelta(int lines); -static int fbcon_set_mode(struct vc_data *conp, int mode); +static int fbcon_scrolldelta(struct vc_data *conp, int lines); /* * Internal routines */ -static void fbcon_setup(int con, int setcol, int init); +static void fbcon_setup(int con, int init, int logo); static __inline__ int real_y(struct display *p, int ypos); #if FLASHING_CURSOR static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp); #endif static __inline__ void updatescrollmode(struct display *p); -#if SUPPORT_SCROLLBACK static __inline__ void ywrap_up(int unit, struct vc_data *conp, struct display *p, int count); static __inline__ void ywrap_down(int unit, struct vc_data *conp, struct display *p, int count); -#else -static __inline__ void ywrap_up(int unit, struct display *p, int count); -static __inline__ void ywrap_down(int unit, struct display *p, int count); -#endif static __inline__ void ypan_up(int unit, struct vc_data *conp, struct display *p, int count); static __inline__ void ypan_down(int unit, struct vc_data *conp, @@ -232,21 +233,21 @@ static void cursor_timer_handler(unsigned long dev_addr) static struct display_switch fbcon_dummy; +/* NOTE: fbcon cannot be __initfunc: it may be called from take_over_console later */ -__initfunc(static unsigned long fbcon_startup(unsigned long kmem_start, - const char **display_desc)) +static const char *fbcon_startup(void) { + const char *display_desc = "frame buffer device"; int irqres = 1; + static int done = 0; - /* Probe all frame buffer devices */ - kmem_start = probe_framebuffers(kmem_start); - - if (!num_registered_fb) { - DPRINTK("no framebuffer registered\n"); - return kmem_start; - } - - *display_desc = "frame buffer device"; + /* + * If num_registered_fb is zero, this is a call for the dummy part. + * The frame buffer devices weren't initialized yet. + */ + if (!num_registered_fb || done) + return display_desc; + done = 1; #ifdef CONFIG_AMIGA if (MACH_IS_AMIGA) { @@ -302,6 +303,11 @@ __initfunc(static unsigned long fbcon_startup(unsigned long kmem_start, } #endif /* CONFIG_MAC */ +#if defined(__arm__) && defined(IRQ_VSYNCPULSE) + irqres = request_irq(IRQ_VSYNCPULSE, fbcon_vbl_handler, SA_SHIRQ, + "console/cursor", fbcon_vbl_handler); +#endif + if (irqres) { cursor_blink_rate = DEFAULT_CURSOR_BLINK_RATE; cursor_timer.expires = jiffies+HZ/50; @@ -310,14 +316,11 @@ __initfunc(static unsigned long fbcon_startup(unsigned long kmem_start, add_timer(&cursor_timer); } - if (!console_show_logo) - console_show_logo = fbcon_show_logo; - - return kmem_start; + return display_desc; } -static void fbcon_init(struct vc_data *conp) +static void fbcon_init(struct vc_data *conp, int init) { int unit = conp->vc_num; struct fb_info *info; @@ -326,6 +329,9 @@ static void fbcon_init(struct vc_data *conp) info = registered_fb[(int)con2fb_map[unit]]; info->changevar = &fbcon_changevar; + conp->vc_display_fg = &info->display_fg; + if (!info->display_fg) + info->display_fg = conp; fb_display[unit] = *(info->disp); /* copy from default */ DPRINTK("mode: %s\n",info->modename); DPRINTK("visual: %d\n",fb_display[unit].visual); @@ -334,7 +340,7 @@ static void fbcon_init(struct vc_data *conp) fb_display[unit].var.bits_per_pixel); fb_display[unit].conp = conp; fb_display[unit].fb_info = info; - fbcon_setup(unit, 1, 1); + fbcon_setup(unit, init, !init); } @@ -351,13 +357,15 @@ static void fbcon_deinit(struct vc_data *conp) static int fbcon_changevar(int con) { if (fb_display[con].conp) - fbcon_setup(con, 1, 0); - return(0); + fbcon_setup(con, 0, 0); + return 0; } static __inline__ void updatescrollmode(struct display *p) { + if (p->scrollmode == SCROLL_YREDRAW) + return; if (divides(p->ywrapstep, p->fontheight) && divides(p->fontheight, p->var.yres_virtual)) p->scrollmode = SCROLL_YWRAP; @@ -368,21 +376,44 @@ static __inline__ void updatescrollmode(struct display *p) p->scrollmode = SCROLL_YMOVE; } +static void fbcon_font_widths(struct display *p) +{ + int i; + p->fontwidthlog = 0; + for (i = 2; i <= 6; i++) + if (p->fontwidth == (1 << i)) + p->fontwidthlog = i; + p->fontheightlog = 0; + for (i = 2; i <= 6; i++) + if (p->fontheight == (1 << i)) + p->fontheightlog = i; +} + +#define fontwidthvalid(p,w) ((p)->dispsw->fontwidthmask & FONTWIDTH(w)) -static void fbcon_setup(int con, int setcol, int init) +static void fbcon_setup(int con, int init, int logo) { struct display *p = &fb_display[con]; struct vc_data *conp = p->conp; int nr_rows, nr_cols; + int old_rows, old_cols; + unsigned short *save = NULL, *r, *q; + /* Only if not module */ + extern int initmem_freed; + struct fbcon_font_desc *font; + if (con != fg_console || initmem_freed || p->type == FB_TYPE_TEXT) + logo = 0; p->var.xoffset = p->var.yoffset = p->yscroll = 0; /* reset wrap/pan */ if (!p->fb_info->fontname[0] || - !findsoftfont(p->fb_info->fontname, &p->fontwidth, &p->fontheight, - &p->fontdata) || p->fontwidth != 8) - getdefaultfont(p->var.xres, p->var.yres, NULL, &p->fontwidth, - &p->fontheight, &p->fontdata); - if (p->fontwidth != 8) { + !(font = fbcon_find_font(p->fb_info->fontname))) + font = fbcon_get_default_font(p->var.xres, p->var.yres); + p->fontwidth = font->width; + p->fontheight = font->height; + p->fontdata = font->data; + fbcon_font_widths(p); + if (!fontwidthvalid(p,p->fontwidth)) { #ifdef CONFIG_MAC if (MACH_IS_MAC) /* ++Geert: hack to make 6x11 fonts work on mac */ @@ -391,14 +422,58 @@ static void fbcon_setup(int con, int setcol, int init) #endif { /* ++Geert: changed from panic() to `correct and continue' */ - printk(KERN_ERR "fbcon_setup: No support for fontwidth != 8"); + printk(KERN_ERR "fbcon_setup: No support for fontwidth %d\n", p->fontwidth); p->dispsw = &fbcon_dummy; } } + if (p->dispsw->set_font) + p->dispsw->set_font(p, p->fontwidth, p->fontheight); updatescrollmode(p); - + + old_cols = conp->vc_cols; + old_rows = conp->vc_rows; + nr_cols = p->var.xres/p->fontwidth; nr_rows = p->var.yres/p->fontheight; + + if (logo) { + /* Need to make room for the logo */ + int cnt; + int step; + + logo_lines = (LOGO_H + p->fontheight - 1) / p->fontheight; + q = (unsigned short *)(conp->vc_origin + conp->vc_size_row * old_rows); + step = logo_lines * old_cols; + for (r = q - logo_lines * old_cols; r < q; r++) + if (*r != conp->vc_video_erase_char) + break; + if (r != q && nr_rows >= old_rows + logo_lines) { + save = kmalloc(logo_lines * nr_cols * 2, GFP_KERNEL); + if (save) { + int i = old_cols < nr_cols ? old_cols : nr_cols; + scr_memsetw(save, conp->vc_video_erase_char, logo_lines * nr_cols * 2); + r = q - step; + for (cnt = 0; cnt < logo_lines; cnt++, r += i) + scr_memcpyw(save + cnt * nr_cols, r, 2 * i); + r = q; + } + } + if (r == q) { + /* We can scroll screen down */ + r = q - step - old_cols; + for (cnt = old_rows - logo_lines; cnt > 0; cnt--) { + scr_memcpyw(r + step, r, conp->vc_size_row); + r -= old_cols; + } + if (!save) { + conp->vc_y += logo_lines; + conp->vc_pos += logo_lines * conp->vc_size_row; + } + } + scr_memsetw((unsigned short *)conp->vc_origin, conp->vc_video_erase_char, + conp->vc_size_row * logo_lines); + } + /* * ++guenther: console.c:vc_allocate() relies on initializing * vc_{cols,rows}, but we must not set those if we are only @@ -410,6 +485,10 @@ 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; + p->fgshift = 8; + p->bgshift = 12; + p->charmask = 0xff; + conp->vc_hi_font_mask = 0; if (!p->dispsw) { printk(KERN_WARNING "fbcon_setup: type %d (aux %d, depth %d) not " @@ -418,13 +497,30 @@ static void fbcon_setup(int con, int setcol, int init) } p->dispsw->setup(p); - if (setcol) { - p->fgcol = p->var.bits_per_pixel > 2 ? 7 : (1<<p->var.bits_per_pixel)-1; - p->bgcol = 0; - } + p->fgcol = p->var.bits_per_pixel > 2 ? 7 : (1<<p->var.bits_per_pixel)-1; + p->bgcol = 0; - if (!init) + if (!init) { + if (con == fg_console) + set_palette(); /* Unlike vgacon, we have to set palette before resize on directcolor, + so that it is drawn with correct colors */ vc_resize_con(nr_rows, nr_cols, con); + if (save) { + q = (unsigned short *)(conp->vc_origin + conp->vc_size_row * old_rows); + scr_memcpyw(q, save, logo_lines * nr_cols * 2); + conp->vc_y += logo_lines; + conp->vc_pos += logo_lines * conp->vc_size_row; + kfree(save); + } + if (con == fg_console) + update_screen(con); /* So that we set origin correctly */ + } + + if (logo) { + logo_shown = fg_console; + fbcon_show_logo(); /* This is protected above by initmem_freed */ + conp->vc_top = logo_lines; + } } @@ -458,7 +554,7 @@ static __inline__ int real_y(struct display *p, int ypos) int rows = p->vrows; ypos += p->yscroll; - return(ypos < rows ? ypos : ypos-rows); + return ypos < rows ? ypos : ypos-rows; } @@ -468,6 +564,7 @@ static void fbcon_clear(struct vc_data *conp, int sy, int sx, int height, int unit = conp->vc_num; struct display *p = &fb_display[unit]; u_int y_break; + int redraw_cursor = 0; if (!p->can_soft_blank && console_blanked) return; @@ -476,8 +573,10 @@ static void fbcon_clear(struct vc_data *conp, int sy, int sx, int height, return; if ((sy <= p->cursor_y) && (p->cursor_y < sy+height) && - (sx <= p->cursor_x) && (p->cursor_x < sx+width)) + (sx <= p->cursor_x) && (p->cursor_x < sx+width)) { CURSOR_UNDRAWN(); + redraw_cursor = 1; + } /* Split blits that cross physical y_wrap boundary */ @@ -488,6 +587,9 @@ static void 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); + + if (redraw_cursor) + vbl_cursor_cnt = CURSOR_DRAW_DELAY; } @@ -495,30 +597,41 @@ 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]; + int redraw_cursor = 0; if (!p->can_soft_blank && console_blanked) return; - if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) + if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) { CURSOR_UNDRAWN(); + redraw_cursor = 1; + } p->dispsw->putc(conp, p, c, real_y(p, ypos), xpos); + + if (redraw_cursor) + vbl_cursor_cnt = CURSOR_DRAW_DELAY; } -static void fbcon_putcs(struct vc_data *conp, const char *s, int count, +static void fbcon_putcs(struct vc_data *conp, const unsigned short *s, int count, int ypos, int xpos) { int unit = conp->vc_num; struct display *p = &fb_display[unit]; + int redraw_cursor = 0; if (!p->can_soft_blank && console_blanked) return; if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) && - (p->cursor_x < (xpos + count))) + (p->cursor_x < (xpos + count))) { CURSOR_UNDRAWN(); + redraw_cursor = 1; + } p->dispsw->putcs(conp, p, s, count, real_y(p, ypos), xpos); + if (redraw_cursor) + vbl_cursor_cnt = CURSOR_DRAW_DELAY; } @@ -527,26 +640,38 @@ static void fbcon_cursor(struct vc_data *conp, int mode) int unit = conp->vc_num; struct display *p = &fb_display[unit]; + /* do we have a hardware cursor ? */ + if (p->dispsw->cursor) { + p->cursor_x = conp->vc_x; + p->cursor_y = conp->vc_y; + p->dispsw->cursor(p, mode, p->cursor_x, real_y(p, p->cursor_y)); + return; + } + /* 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; - if (CURSOR_UNDRAWN ()) - 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; - - switch (mode) { - case CM_ERASE: - cursor_on = 0; - break; - case CM_MOVE: - case CM_DRAW: - vbl_cursor_cnt = CURSOR_DRAW_DELAY; - cursor_on = 1; - break; - } + cursor_on = 0; + if (cursor_drawn) + 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; + + switch (mode) { + case CM_ERASE: + cursor_drawn = 0; + break; + case CM_MOVE: + case CM_DRAW: + if (cursor_drawn) + p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y)); + vbl_cursor_cnt = CURSOR_DRAW_DELAY; + cursor_on = 1; + break; + } } @@ -559,28 +684,21 @@ static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp) return; if (vbl_cursor_cnt && --vbl_cursor_cnt == 0) { - /* Here no check is possible for console changing. The console - * switching code should set vbl_cursor_cnt to an appropriate value. - */ p = &fb_display[fg_console]; - p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y)); + if (p->dispsw->revc) + p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y)); cursor_drawn ^= 1; vbl_cursor_cnt = cursor_blink_rate; } } #endif -#if SUPPORT_SCROLLBACK +static int scrollback_phys_max = 0; static int scrollback_max = 0; static int scrollback_current = 0; -#endif -#if SUPPORT_SCROLLBACK static __inline__ void ywrap_up(int unit, struct vc_data *conp, struct display *p, int count) -#else -static __inline__ void ywrap_up(int unit, struct display *p, int count) -#endif { p->yscroll += count; if (p->yscroll >= p->vrows) /* Deal with wrap */ @@ -589,21 +707,15 @@ static __inline__ void ywrap_up(int unit, struct display *p, int count) p->var.yoffset = p->yscroll*p->fontheight; p->var.vmode |= FB_VMODE_YWRAP; p->fb_info->updatevar(unit, p->fb_info); -#if SUPPORT_SCROLLBACK scrollback_max += count; - if (scrollback_max > p->vrows-conp->vc_rows) - scrollback_max = p->vrows-conp->vc_rows; + if (scrollback_max > scrollback_phys_max) + scrollback_max = scrollback_phys_max; scrollback_current = 0; -#endif } -#if SUPPORT_SCROLLBACK static __inline__ void ywrap_down(int unit, struct vc_data *conp, struct display *p, int count) -#else -static __inline__ void ywrap_down(int unit, struct display *p, int count) -#endif { p->yscroll -= count; if (p->yscroll < 0) /* Deal with wrap */ @@ -612,12 +724,10 @@ static __inline__ void ywrap_down(int unit, struct display *p, int count) p->var.yoffset = p->yscroll*p->fontheight; p->var.vmode |= FB_VMODE_YWRAP; p->fb_info->updatevar(unit, p->fb_info); -#if SUPPORT_SCROLLBACK scrollback_max -= count; if (scrollback_max < 0) scrollback_max = 0; scrollback_current = 0; -#endif } @@ -625,15 +735,19 @@ static __inline__ void ypan_up(int unit, struct vc_data *conp, struct display *p, int count) { p->yscroll += count; - if (p->yscroll+conp->vc_rows > p->vrows) { - p->dispsw->bmove(p, p->yscroll, 0, 0, 0, conp->vc_rows-count, - conp->vc_cols); - p->yscroll = 0; + if (p->yscroll > p->vrows-conp->vc_rows) { + p->dispsw->bmove(p, p->vrows-conp->vc_rows, 0, 0, 0, + conp->vc_rows, conp->vc_cols); + p->yscroll -= p->vrows-conp->vc_rows; } 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); + scrollback_max += count; + if (scrollback_max > scrollback_phys_max) + scrollback_max = scrollback_phys_max; + scrollback_current = 0; } @@ -642,33 +756,139 @@ static __inline__ void ypan_down(int unit, struct vc_data *conp, { p->yscroll -= count; if (p->yscroll < 0) { - p->yscroll = p->vrows-conp->vc_rows; - p->dispsw->bmove(p, 0, 0, p->yscroll+count, 0, conp->vc_rows-count, - conp->vc_cols); + p->dispsw->bmove(p, 0, 0, p->vrows-conp->vc_rows, 0, + conp->vc_rows, conp->vc_cols); + p->yscroll += p->vrows-conp->vc_rows; } 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); + scrollback_max -= count; + if (scrollback_max < 0) + scrollback_max = 0; + scrollback_current = 0; +} + + +static void fbcon_redraw(struct vc_data *conp, struct display *p, + int line, int count, int offset) +{ + unsigned short *d = (unsigned short *) + (conp->vc_origin + conp->vc_size_row * line); + unsigned short *s = d + offset; + while (count--) { + unsigned short *start = s; + unsigned short *le = (unsigned short *) + ((unsigned long)s + conp->vc_size_row); + unsigned short c; + int x = 0; + unsigned short attr = 1; + + do { + c = scr_readw(s); + if (attr != (c & 0xff00)) { + attr = c & 0xff00; + if (s > start) { + p->dispsw->putcs(conp, p, start, s - start, line, x); + x += s - start; + start = s; + } + } + if (c == scr_readw(d)) { + if (s > start) { + p->dispsw->putcs(conp, p, start, s - start, line, x); + x += s - start + 1; + start = s + 1; + } else { + x++; + start++; + } + } + scr_writew(c, d); + s++; + d++; + } while (s < le); + if (s > start) + p->dispsw->putcs(conp, p, start, s - start, line, x); + if (offset > 0) + line++; + else { + line--; + /* NOTE: We subtract two lines from these pointers */ + s -= conp->vc_size_row; + d -= conp->vc_size_row; + } + } } +/* This cannot be used together with ypan or ywrap */ +void fbcon_redraw_bmove(struct display *p, int sy, int sx, int dy, int dx, int h, int w) +{ + if (sy != dy) + panic("fbcon_redraw_bmove width sy != dy"); + /* h will be always 1, but it does not matter if we are more generic */ + while (h-- > 0) { + struct vc_data *conp = p->conp; + unsigned short *d = (unsigned short *) + (conp->vc_origin + conp->vc_size_row * dy + dx * 2); + unsigned short *s = d + (dx - sx); + unsigned short *start = d; + unsigned short *ls = d; + unsigned short *le = d + w; + unsigned short c; + int x = dx; + unsigned short attr = 1; + + do { + c = scr_readw(d); + if (attr != (c & 0xff00)) { + attr = c & 0xff00; + if (d > start) { + p->dispsw->putcs(conp, p, start, d - start, dy, x); + x += d - start; + start = d; + } + } + if (s >= ls && s < le && c == scr_readw(s)) { + if (d > start) { + p->dispsw->putcs(conp, p, start, d - start, dy, x); + x += d - start + 1; + start = d + 1; + } else { + x++; + start++; + } + } + s++; + d++; + } while (d < le); + if (d > start) + p->dispsw->putcs(conp, p, start, d - start, dy, x); + sy++; + dy++; + } +} -static void fbcon_scroll(struct vc_data *conp, int t, int b, int dir, - int count) +static int 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]; + int is_txt = (p->type == FB_TYPE_TEXT); if (!p->can_soft_blank && console_blanked) - return; + return 0; if (!count) - return; + return 0; fbcon_cursor(conp, CM_ERASE); /* * ++Geert: Only use ywrap/ypan if the console is in text mode + * ++Andrew: Only use ypan on hardware text mode when scrolling the + * whole screen (prevents flicker). */ switch (dir) { @@ -682,11 +902,7 @@ static void fbcon_scroll(struct vc_data *conp, int t, int b, int dir, if (t > 0) fbcon_bmove(conp, 0, 0, count, 0, t, conp->vc_cols); -#if SUPPORT_SCROLLBACK ywrap_up(unit, conp, p, count); -#else - ywrap_up(unit, p, count); -#endif if (conp->vc_rows-b > 0) fbcon_bmove(conp, b-count, 0, b, 0, conp->vc_rows-b, conp->vc_cols); @@ -697,7 +913,8 @@ static void fbcon_scroll(struct vc_data *conp, int t, int b, int dir, break; case SCROLL_YPAN: - if (b-t-count > 3*conp->vc_rows>>2) { + if (( is_txt && (b-t == conp->vc_rows)) || + (!is_txt && (b-t-count > 3*conp->vc_rows>>2))) { if (t > 0) fbcon_bmove(conp, 0, 0, count, 0, t, conp->vc_cols); @@ -717,6 +934,15 @@ static void fbcon_scroll(struct vc_data *conp, int t, int b, int dir, p->dispsw->clear(conp, p, b-count, 0, count, conp->vc_cols); break; + case SCROLL_YREDRAW: + fbcon_redraw(conp, p, t, b-t-count, count*conp->vc_cols); + p->dispsw->clear(conp, p, b-count, 0, count, + conp->vc_cols); + scr_memsetw((unsigned short *)(conp->vc_origin + + conp->vc_size_row * (b-count)), + conp->vc_video_erase_char, + conp->vc_size_row * count); + return 1; } else { fbcon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols); @@ -734,11 +960,7 @@ static void fbcon_scroll(struct vc_data *conp, int t, int b, int dir, if (conp->vc_rows-b > 0) fbcon_bmove(conp, b, 0, b-count, 0, conp->vc_rows-b, conp->vc_cols); -#if SUPPORT_SCROLLBACK ywrap_down(unit, conp, p, count); -#else - ywrap_down(unit, p, count); -#endif if (t > 0) fbcon_bmove(conp, count, 0, 0, 0, t, conp->vc_cols); @@ -749,7 +971,8 @@ static void fbcon_scroll(struct vc_data *conp, int t, int b, int dir, break; case SCROLL_YPAN: - if (b-t-count > 3*conp->vc_rows>>2) { + if (( is_txt && (b-t == conp->vc_rows)) || + (!is_txt && (b-t-count > 3*conp->vc_rows>>2))) { if (conp->vc_rows-b > 0) fbcon_bmove(conp, b, 0, b-count, 0, conp->vc_rows-b, conp->vc_cols); @@ -768,6 +991,15 @@ static void fbcon_scroll(struct vc_data *conp, int t, int b, int dir, conp->vc_cols); p->dispsw->clear(conp, p, t, 0, count, conp->vc_cols); break; + + case SCROLL_YREDRAW: + fbcon_redraw(conp, p, b - 1, b-t-count, -count*conp->vc_cols); + p->dispsw->clear(conp, p, t, 0, count, conp->vc_cols); + scr_memsetw((unsigned short *)(conp->vc_origin + + conp->vc_size_row * t), + conp->vc_video_erase_char, + conp->vc_size_row * count); + return 1; } else { /* @@ -791,6 +1023,7 @@ static void fbcon_scroll(struct vc_data *conp, int t, int b, int dir, fbcon_clear(conp, 0, t, conp->vc_rows, count); break; } + return 0; } @@ -799,7 +1032,7 @@ static void fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, { int unit = conp->vc_num; struct display *p = &fb_display[unit]; - + if (!p->can_soft_blank && console_blanked) return; @@ -807,9 +1040,9 @@ static void fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, return; if (((sy <= p->cursor_y) && (p->cursor_y < sy+height) && - (sx <= p->cursor_x) && (p->cursor_x < sx+width)) || - ((dy <= p->cursor_y) && (p->cursor_y < dy+height) && - (dx <= p->cursor_x) && (p->cursor_x < dx+width))) + (sx <= p->cursor_x) && (p->cursor_x < sx+width)) || + ((dy <= p->cursor_y) && (p->cursor_y < dy+height) && + (dx <= p->cursor_x) && (p->cursor_x < dx+width))) fbcon_cursor(conp, CM_ERASE); /* Split blits that cross physical y_wrap case. @@ -822,7 +1055,6 @@ static void fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, fbcon_bmove_rec(p, sy, sx, dy, dx, height, width, p->vrows-p->yscroll); } - static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx, int height, int width, u_int y_break) { @@ -861,158 +1093,186 @@ static int fbcon_switch(struct vc_data *conp) struct display *p = &fb_display[unit]; struct fb_info *info = p->fb_info; - if (info && info->switch_con) - (*info->switch_con)(conp->vc_num, info); -#if SUPPORT_SCROLLBACK + if (logo_shown >= 0) { + struct vc_data *conp2 = vc_cons[logo_shown].d; + + if (conp2->vc_top == logo_lines && conp2->vc_bottom == conp2->vc_rows) + conp2->vc_top = 0; + logo_shown = -1; + } + p->var.yoffset = p->yscroll*p->fontheight; + switch (p->scrollmode) { + case SCROLL_YWRAP: + scrollback_phys_max = p->vrows-conp->vc_rows; + break; + case SCROLL_YPAN: + scrollback_phys_max = p->vrows-2*conp->vc_rows; + if (scrollback_phys_max < 0) + scrollback_phys_max = 0; + break; + default: + scrollback_phys_max = 0; + break; + } scrollback_max = 0; scrollback_current = 0; -#endif - return(0); + + if (info && info->switch_con) + (*info->switch_con)(conp->vc_num, info); + if (p->dispsw && p->dispsw->clear_margins) + p->dispsw->clear_margins(conp, p); + return 1; } -static int fbcon_blank(int blank) +static int fbcon_blank(struct vc_data *conp, int blank) { - struct display *p = &fb_display[fg_console]; + struct display *p = &fb_display[conp->vc_num]; struct fb_info *info = p->fb_info; + if (blank < 0) /* Entering graphics mode */ + return 0; + 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 + if (MACH_IS_MAC) { + if (p->screen_base) + 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* - p->var.bits_per_pixel>>3); - else - mymemclear(p->screen_base, - p->var.xres_virtual*p->var.yres_virtual* - p->var.bits_per_pixel>>3); - return(0); + if (p->visual == FB_VISUAL_MONO01) { + if (p->screen_base) + mymemset(p->screen_base, + p->var.xres_virtual*p->var.yres_virtual* + p->var.bits_per_pixel>>3); + } else + p->dispsw->clear(conp, p, 0, 0, p->conp->vc_rows, p->conp->vc_cols); + return 0; } else { /* Tell console.c that it has to restore the screen itself */ - return(1); + return 1; } } (*info->blank)(blank, info); - return(0); + return 0; } -static int fbcon_get_font(struct vc_data *conp, int *w, int *h, char *data) +static inline int fbcon_get_font(int unit, struct console_font_op *op) { - int unit = conp->vc_num; struct display *p = &fb_display[unit]; - int i, j, size, alloc; - - size = (p->fontwidth+7)/8 * p->fontheight * 256; - alloc = (*w+7)/8 * *h * 256; - *w = p->fontwidth; - *h = p->fontheight; + u8 *data = op->data; + int i, j; - if (alloc < size) - /* allocation length not sufficient */ - return( -ENAMETOOLONG ); - - for (i = 0; i < 256; i++) - for (j = 0; j < p->fontheight; j++) - data[i*32+j] = p->fontdata[i*p->fontheight+j]; - return( 0 ); +#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY + if (p->fontwidth != 8) return -EINVAL; +#endif + op->width = p->fontwidth; + op->height = p->fontheight; + op->charcount = (p->charmask == 0x1ff) ? 512 : 256; + if (!op->data) return 0; + + if (op->width <= 8) { + for (i = 0; i < op->charcount; i++) { + for (j = 0; j < p->fontheight; j++) + *data++ = p->fontdata[i*p->fontheight+j]; + data += 32 - p->fontheight; + } + } +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + else if (op->width <= 16) { + for (i = 0; i < op->charcount; i++) { + for (j = 0; j < p->fontheight; j++) { + *data++ = ((u16 *)p->fontdata)[i*p->fontheight+j] >> 8; + *data++ = ((u16 *)p->fontdata)[i*p->fontheight+j]; + } + data += 2 * (32 - p->fontheight); + } + } else if (op->width <= 24) { + for (i = 0; i < op->charcount; i++) { + for (j = 0; j < p->fontheight; j++) { + *data++ = ((u32 *)p->fontdata)[i*p->fontheight+j] >> 24; + *data++ = ((u32 *)p->fontdata)[i*p->fontheight+j] >> 16; + *data++ = ((u32 *)p->fontdata)[i*p->fontheight+j] >> 8; + } + data += 3 * (32 - p->fontheight); + } + } else { + for (i = 0; i < op->charcount; i++) { + for (j = 0; j < p->fontheight; j++) { + *data++ = ((u32 *)p->fontdata)[i*p->fontheight+j] >> 24; + *data++ = ((u32 *)p->fontdata)[i*p->fontheight+j] >> 16; + *data++ = ((u32 *)p->fontdata)[i*p->fontheight+j] >> 8; + *data++ = ((u32 *)p->fontdata)[i*p->fontheight+j]; + } + data += 4 * (32 - p->fontheight); + } + } +#endif + return 0; } #define REFCOUNT(fd) (((int *)(fd))[-1]) +#define FNTSIZE(fd) (((int *)(fd))[-2]) +#define FNTCHARCNT(fd) (((int *)(fd))[-3]) +#define FNTSUM(fd) (((int *)(fd))[-4]) -static int fbcon_set_font(struct vc_data *conp, int w, int h, char *data) +static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int userfont) { - int unit = conp->vc_num; struct display *p = &fb_display[unit]; - int i, j, size, userspace = 1, resize; - char *old_data = NULL, *new_data; - - if (w < 0) - w = p->fontwidth; - if (h < 0) - h = p->fontheight; - - if (w == 0) { - /* engage predefined font, name in 'data' */ - char name[MAX_FONT_NAME+1]; - - if ((i = verify_area( VERIFY_READ, (void *)data, MAX_FONT_NAME ))) - return i; - copy_from_user( name, data, MAX_FONT_NAME ); - name[sizeof(name)-1] = 0; - - if (!findsoftfont( name, &w, &h, (u8 **)&data )) - return( -ENOENT ); - userspace = 0; - } else if (w == 1) { - /* copy font from some other console in 'h'*/ - struct display *op; - - if (h < 0 || !vc_cons_allocated( h )) - return( -ENOTTY ); - if (h == unit) - return( 0 ); /* nothing to do */ - op = &fb_display[h]; - if (op->fontdata == p->fontdata) - return( 0 ); /* already the same font... */ - - resize = (op->fontwidth != p->fontwidth) || - (op->fontheight != p->fontheight); - if (p->userfont) - old_data = p->fontdata; - p->fontdata = op->fontdata; - w = p->fontwidth = op->fontwidth; - h = p->fontheight = op->fontheight; - if ((p->userfont = op->userfont)) - REFCOUNT(p->fontdata)++; /* increment usage counter */ - goto activate; + int resize; + int w = op->width; + int h = op->height; + int cnt; + char *old_data = NULL; + + if (!fontwidthvalid(p,w)) { + if (userfont) + kfree(data); + return -ENXIO; } - if (w != 8) - /* Currently only fontwidth == 8 supported */ - return( -ENXIO ); - resize = (w != p->fontwidth) || (h != p->fontheight); - size = (w+7)/8 * h * 256; - if (p->userfont) - old_data = p->fontdata; - - if (userspace) { - if (!(new_data = kmalloc( sizeof(int)+size, GFP_USER ))) - return( -ENOMEM ); - new_data += sizeof(int); - REFCOUNT(new_data) = 1; /* usage counter */ - - for (i = 0; i < 256; i++) - for (j = 0; j < h; j++) - new_data[i*h+j] = data[i*32+j]; - - p->fontdata = new_data; - p->userfont = 1; - } else { - p->fontdata = data; - p->userfont = 0; - } + old_data = p->fontdata; + if (userfont) + cnt = FNTCHARCNT(data); + else + cnt = 256; + p->fontdata = data; + if ((p->userfont = userfont)) + REFCOUNT(data)++; p->fontwidth = w; p->fontheight = h; + if (p->conp->vc_hi_font_mask && cnt == 256) { + p->conp->vc_hi_font_mask = 0; + p->conp->vc_complement_mask >>= 1; + p->fgshift--; + p->bgshift--; + p->charmask = 0xff; + } else if (!p->conp->vc_hi_font_mask && cnt == 512) { + p->conp->vc_hi_font_mask = 0x100; + p->conp->vc_complement_mask <<= 1; + p->fgshift++; + p->bgshift++; + p->charmask = 0x1ff; + } + fbcon_font_widths(p); -activate: if (resize) { /* reset wrap/pan */ p->var.xoffset = p->var.yoffset = p->yscroll = 0; - /* Adjust the virtual screen-size to fontheight*rows */ - p->var.yres_virtual = (p->var.yres/h)*h; + if (!p->dispsw->set_font || + !p->dispsw->set_font(p, p->fontwidth, p->fontheight)) { + /* Adjust the virtual screen-size to fontheight*rows */ + p->var.yres_virtual = (p->var.yres/h)*h; + } p->vrows = p->var.yres_virtual/h; updatescrollmode(p); vc_resize_con( p->var.yres/h, p->var.xres/w, unit ); @@ -1020,9 +1280,159 @@ activate: update_screen( unit ); if (old_data && (--REFCOUNT(old_data) == 0)) - kfree( old_data - sizeof(int) ); + kfree( old_data - 4*sizeof(int) ); - return( 0 ); + return 0; +} + +static inline int fbcon_copy_font(int unit, struct console_font_op *op) +{ + struct display *od, *p = &fb_display[unit]; + int h = op->height; + + if (h < 0 || !vc_cons_allocated( h )) + return -ENOTTY; + if (h == unit) + return 0; /* nothing to do */ + od = &fb_display[h]; + if (od->fontdata == p->fontdata) + return 0; /* already the same font... */ + op->width = od->fontwidth; + op->height = od->fontheight; + return fbcon_do_set_font(unit, op, od->fontdata, od->userfont); +} + +static inline int fbcon_set_font(int unit, struct console_font_op *op) +{ + int w = op->width; + int h = op->height; + int size = h; + int i, j, k; + u8 *new_data, *data = op->data, c, *p; + u32 d; + +#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY + if (w != 8) + return -EINVAL; +#endif + + if (w > 32 || (op->charcount != 256 && op->charcount != 512)) + return -EINVAL; + + if (w > 8) { + if (w <= 16) + size *= 2; + else + size *= 4; + } + size *= op->charcount; + + if (!(new_data = kmalloc( 4*sizeof(int)+size, GFP_USER ))) + return -ENOMEM; + new_data += 4*sizeof(int); + FNTSIZE(new_data) = size; + FNTCHARCNT(new_data) = op->charcount; + REFCOUNT(new_data) = 0; /* usage counter */ + k = 0; + p = data; + if (w <= 8) { + for (i = 0; i < op->charcount; i++) { + for (j = 0; j < h; j++) { + c = *p++; + k += c; + new_data[i*h+j] = c; + } + p += 32 - h; + } + } +#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY + else if (w <= 16) { + for (i = 0; i < op->charcount; i++) { + for (j = 0; j < h; j++) { + d = (p[0] << 8) | p[1]; + p += 2; + k += d; + ((u16 *)new_data)[i*h+j] = d; + } + p += 2*(32 - h); + } + } else { + for (i = 0; i < op->charcount; i++) { + for (j = 0; j < h; j++) { + if (w <= 24) { + d = (p[0] << 24) | + (p[1] << 16) | + (p[2] << 8); + p += 3; + } else { + d = (p[0] << 24) | + (p[1] << 16) | + (p[2] << 8) | + p[3]; + p += 4; + } + k += d; + ((u32 *)new_data)[i*h+j] = d; + } + if (w <= 24) + p += 3*(32 - h); + else + p += 4*(32 - h); + } + } +#endif + FNTSUM(new_data) = k; + /* Check if the same font is on some other console already */ + for (i = 0; i < MAX_NR_CONSOLES; i++) { + if (fb_display[i].userfont && + fb_display[i].fontdata && + FNTSUM(fb_display[i].fontdata) == k && + FNTSIZE(fb_display[i].fontdata) == size && + !memcmp(fb_display[i].fontdata, new_data, size)) { + kfree(new_data - 4*sizeof(int)); + new_data = fb_display[i].fontdata; + break; + } + } + return fbcon_do_set_font(unit, op, new_data, 1); +} + +static inline int fbcon_set_def_font(int unit, struct console_font_op *op) +{ + char name[MAX_FONT_NAME]; + struct fbcon_font_desc *f; + struct display *p = &fb_display[unit]; + + if (!op->data) + f = fbcon_get_default_font(p->var.xres, p->var.yres); + else if (strncpy_from_user(name, op->data, MAX_FONT_NAME-1) < 0) + return -EFAULT; + else { + name[MAX_FONT_NAME-1] = 0; + if (!(f = fbcon_find_font(name))) + return -ENOENT; + } + op->width = f->width; + op->height = f->height; + return fbcon_do_set_font(unit, op, f->data, 0); +} + +static int fbcon_font_op(struct vc_data *conp, struct console_font_op *op) +{ + int unit = conp->vc_num; + + switch (op->op) { + case KD_FONT_OP_SET: + return fbcon_set_font(unit, op); + case KD_FONT_OP_GET: + return fbcon_get_font(unit, op); + case KD_FONT_OP_SET_DEFAULT: + return fbcon_set_def_font(unit, op); + case KD_FONT_OP_COPY: + return fbcon_copy_font(unit, op); + default: + return -ENOSYS; + } } static u16 palette_red[16]; @@ -1041,7 +1451,7 @@ static int fbcon_set_palette(struct vc_data *conp, unsigned char *table) u8 val; if (!conp->vc_can_do_color || (!p->can_soft_blank && console_blanked)) - return(-EINVAL); + return -EINVAL; for (i = j = 0; i < 16; i++) { k = table[i]; val = conp->vc_palette[j++]; @@ -1051,65 +1461,61 @@ static int fbcon_set_palette(struct vc_data *conp, unsigned char *table) val = conp->vc_palette[j++]; palette_blue[k] = (val<<8)|val; } - palette_cmap.len = 1<<p->var.bits_per_pixel; - if (palette_cmap.len > 16) + if (p->var.bits_per_pixel <= 4) + palette_cmap.len = 1<<p->var.bits_per_pixel; + else palette_cmap.len = 16; + palette_cmap.start = 0; return p->fb_info->fbops->fb_set_cmap(&palette_cmap, 1, unit, p->fb_info); } -static int fbcon_scrolldelta(int lines) +static int fbcon_scrolldelta(struct vc_data *conp, int lines) { -#if SUPPORT_SCROLLBACK - int unit = fg_console; /* xxx */ - struct display *p = &fb_display[unit]; - int offset; - - if (!p->can_soft_blank && console_blanked || - vt_cons[unit]->vc_mode != KD_TEXT || !lines || - p->scrollmode != SCROLL_YWRAP) - return 0; + int unit, offset, limit, scrollback_old; + struct display *p; - fbcon_cursor(conp, CM_ERASE); + if (!scrollback_phys_max) + return -ENOSYS; + scrollback_old = scrollback_current; scrollback_current -= lines; if (scrollback_current < 0) scrollback_current = 0; else if (scrollback_current > scrollback_max) scrollback_current = scrollback_max; + if (scrollback_current == scrollback_old) + return 0; + + unit = fg_console; + p = &fb_display[unit]; + if (!p->can_soft_blank && + (console_blanked || vt_cons[unit]->vc_mode != KD_TEXT || !lines)) + return 0; + fbcon_cursor(conp, CM_ERASE); offset = p->yscroll-scrollback_current; + limit = p->vrows; + switch (p->scrollmode) { + case SCROLL_YWRAP: + p->var.vmode |= FB_VMODE_YWRAP; + break; + case SCROLL_YPAN: + limit -= conp->vc_rows; + p->var.vmode &= ~FB_VMODE_YWRAP; + break; + } if (offset < 0) - offset += p->vrows; - else if (offset > p->vrows) - offset -= p->vrows; - p->var.vmode |= FB_VMODE_YWRAP; + offset += limit; + else if (offset >= limit) + offset -= limit; p->var.xoffset = 0; p->var.yoffset = offset*p->fontheight; 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; + if (!offset) + fbcon_cursor(conp, CM_DRAW); + return 0; } - -#define LOGO_H 80 -#define LOGO_W 80 -#define LOGO_LINE (LOGO_W/8) - __initfunc(static int fbcon_show_logo( void )) { struct display *p = &fb_display[fg_console]; /* draw to vt in foreground */ @@ -1118,17 +1524,25 @@ __initfunc(static int fbcon_show_logo( void )) unsigned char *fb = p->screen_base; unsigned char *logo; unsigned char *dst, *src; - int i, j, n, x1, y1; + int i, j, n, x1, y1, x; int logo_depth, done = 0; - - /* Set colors if visual is PSEUDOCOLOR and we have enough colors */ - if (p->visual == FB_VISUAL_PSEUDOCOLOR && depth >= 4) { - int first_col = depth >= 8 ? 32 : depth > 4 ? 16 : 0; - int num_cols = depth >= 8 ? LINUX_LOGO_COLORS : 16; + + /* Return if the frame buffer is not mapped */ + if (!fb) + return 0; + + /* Set colors if visual is PSEUDOCOLOR and we have enough colors, or for + * TRUECOLOR */ + if ((p->visual == FB_VISUAL_PSEUDOCOLOR && depth >= 4) || + p->visual == FB_VISUAL_TRUECOLOR) { + int is_truecolor = (p->visual == FB_VISUAL_TRUECOLOR); + int use_256 = (!is_truecolor && depth >= 8) || + (is_truecolor && depth >= 24); + int first_col = use_256 ? 32 : depth > 4 ? 16 : 0; + int num_cols = use_256 ? LINUX_LOGO_COLORS : 16; unsigned char *red, *green, *blue; - int old_cmap_len; - if (depth >= 8) { + if (use_256) { red = linux_logo_red; green = linux_logo_green; blue = linux_logo_blue; @@ -1139,11 +1553,6 @@ __initfunc(static int fbcon_show_logo( void )) blue = linux_logo16_blue; } - /* dirty trick to avoid setcmap calling kmalloc which isn't - * initialized yet... */ - old_cmap_len = fb_display[fg_console].cmap.len; - fb_display[fg_console].cmap.len = 1 << depth; - for( i = 0; i < num_cols; i += n ) { n = num_cols - i; if (n > 16) @@ -1159,9 +1568,8 @@ __initfunc(static int fbcon_show_logo( void )) p->fb_info->fbops->fb_set_cmap(&palette_cmap, 1, fg_console, p->fb_info); } - fb_display[fg_console].cmap.len = old_cmap_len; } - + if (depth >= 8) { logo = linux_logo; logo_depth = 8; @@ -1175,191 +1583,215 @@ __initfunc(static int fbcon_show_logo( void )) logo_depth = 1; } + for (x = 0; x < smp_num_cpus * (LOGO_W + 8) && + x < p->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) { + #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; + defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS) + 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; + /* 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 + x*bdepth; + for( x1 = 0; x1 < LOGO_W; x1++, src++ ) { + val = (*src << redshift) | + (*src << greenshift) | + (*src << blueshift); +#ifdef __LITTLE_ENDIAN + for( i = 0; i < bdepth; ++i ) +#else + for( i = bdepth-1; i >= 0; --i ) +#endif + *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 + x*bdepth; + 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) || defined(CONFIG_FB_SBUS) + if ((depth % 8 == 0) && (p->visual == FB_VISUAL_DIRECTCOLOR)) { + /* Modes without color mapping, needs special data transformation... */ + 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; + int redshift, greenshift, blueshift; + + /* Bug: Doesn't obey msb_right ... (who needs that?) */ + redmask = mask[p->var.red.length < 8 ? p->var.red.length : 8]; + greenmask = mask[p->var.green.length < 8 ? p->var.green.length : 8]; + bluemask = mask[p->var.blue.length < 8 ? p->var.blue.length : 8]; + redshift = p->var.red.offset - (8-p->var.red.length); + greenshift = p->var.green.offset - (8-p->var.green.length); + blueshift = p->var.blue.offset - (8-p->var.blue.length); - 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; + dst = fb + y1*line + x*bdepth; 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); + val = ((linux_logo_red[*src-32] & redmask) << redshift) | + ((linux_logo_green[*src-32] & greenmask) << greenshift) | + ((linux_logo_blue[*src-32] & bluemask) << blueshift); +#ifdef __LITTLE_ENDIAN for( i = 0; i < bdepth; ++i ) - *dst++ = val >> (i*8); - pix = (*src & 0x0f) | 0x10; /* lower nibble */ - val = (pix << redshift) | - (pix << greenshift) | - (pix << blueshift); +#else for( i = bdepth-1; i >= 0; --i ) +#endif *dst++ = val >> (i*8); } } + done = 1; } - - 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 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; - int redshift, greenshift, blueshift; - - /* Bug: Doesn't obey msb_right ... (who needs that?) */ - redmask = mask[p->var.red.length < 8 ? p->var.red.length : 8]; - greenmask = mask[p->var.green.length < 8 ? p->var.green.length : 8]; - bluemask = mask[p->var.blue.length < 8 ? p->var.blue.length : 8]; - redshift = p->var.red.offset - (8-p->var.red.length); - greenshift = p->var.green.offset - (8-p->var.green.length); - blueshift = p->var.blue.offset - (8-p->var.blue.length); - - src = logo; - 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 = 0; i < bdepth; ++i ) - *dst++ = val >> (i*8); - } - } +#if defined(CONFIG_FBCON_CFB8) || defined(CONFIG_FB_SBUS) + if (depth == 8 && p->type == FB_TYPE_PACKED_PIXELS) { + /* depth 8 or more, packed, with color registers */ - done = 1; - } -#endif -#if defined(CONFIG_FBCON_CFB8) - if (depth == 8 && p->type == FB_TYPE_PACKED_PIXELS) { - /* depth 8 or more, packed, with color registers */ - - src = logo; - for( y1 = 0; y1 < LOGO_H; y1++ ) { - dst = fb + y1*line; - for( x1 = 0; x1 < LOGO_W; x1++ ) { - *dst++ = *src++; + src = logo; + for( y1 = 0; y1 < LOGO_H; y1++ ) { + dst = fb + y1*line + x; + for( x1 = 0; x1 < LOGO_W; x1++ ) + *dst++ = *src++; } + done = 1; } - - done = 1; - } #endif #if defined(CONFIG_FBCON_AFB) || defined(CONFIG_FBCON_ILBM) || \ defined(CONFIG_FBCON_IPLAN2P2) || defined(CONFIG_FBCON_IPLAN2P4) || \ defined(CONFIG_FBCON_IPLAN2P8) - if (depth >= 2 && (p->type == FB_TYPE_PLANES || - p->type == FB_TYPE_INTERLEAVED_PLANES)) { - /* planes (normal or interleaved), with color registers */ - int bit; - unsigned char val, mask; - int plane = p->next_plane; - - /* for support of Atari interleaved planes */ + if (depth >= 2 && (p->type == FB_TYPE_PLANES || + p->type == FB_TYPE_INTERLEAVED_PLANES)) { + /* planes (normal or interleaved), with color registers */ + int bit; + unsigned char val, mask; + int plane = p->next_plane; + + /* for support of Atari interleaved planes */ #define MAP_X(x) (plane > line ? x : (x & ~1)*depth + (x & 1)) - /* extract a bit from the source image */ + /* extract a bit from the source image */ #define BIT(p,pix,bit) (p[pix*logo_depth/8] & \ (1 << ((8-((pix*logo_depth)&7)-logo_depth) + bit))) - src = logo; - for( y1 = 0; y1 < LOGO_H; y1++ ) { - for( x1 = 0; x1 < LOGO_LINE; x1++, src += logo_depth ) { - dst = fb + y1*line + MAP_X(x1); - for( bit = 0; bit < logo_depth; bit++ ) { - val = 0; - for( mask = 0x80, i = 0; i < 8; mask >>= 1, i++ ) { - if (BIT( src, i, bit )) - val |= mask; + src = logo; + for( y1 = 0; y1 < LOGO_H; y1++ ) { + for( x1 = 0; x1 < LOGO_LINE; x1++, src += logo_depth ) { + dst = fb + y1*line + MAP_X(x1); + for( bit = 0; bit < logo_depth; bit++ ) { + val = 0; + for( mask = 0x80, i = 0; i < 8; mask >>= 1, i++ ) { + if (BIT( src, i, bit )) + val |= mask; + } + *dst = val; + dst += plane; } - *dst = val; - dst += plane; } } - } - /* fill remaining planes - * special case for logo_depth == 4: we used color registers 16..31, - * so fill plane 4 with 1 bits instead of 0 */ - if (depth > logo_depth) { - for( y1 = 0; y1 < LOGO_H; y1++ ) { - for( x1 = 0; x1 < LOGO_LINE; x1++ ) { - dst = fb + y1*line + MAP_X(x1) + logo_depth*plane; - for( i = logo_depth; i < depth; i++, dst += plane ) - *dst = (i == logo_depth && logo_depth == 4) - ? 0xff : 0x00; + /* fill remaining planes + * special case for logo_depth == 4: we used color registers 16..31, + * so fill plane 4 with 1 bits instead of 0 */ + if (depth > logo_depth) { + for( y1 = 0; y1 < LOGO_H; y1++ ) { + for( x1 = 0; x1 < LOGO_LINE; x1++ ) { + dst = fb + y1*line + MAP_X(x1) + logo_depth*plane; + for( i = logo_depth; i < depth; i++, dst += plane ) + *dst = (i == logo_depth && logo_depth == 4) + ? 0xff : 0x00; + } } } + done = 1; + break; } - - done = 1; - } #endif #if defined(CONFIG_FBCON_MFB) || defined(CONFIG_FBCON_AFB) || \ defined(CONFIG_FBCON_ILBM) - if (depth == 1) { - /* monochrome */ - unsigned char inverse = p->inverse ? 0x00 : 0xff; - - /* can't use simply memcpy because need to apply inverse */ - for( y1 = 0; y1 < LOGO_H; y1++ ) { - src = logo + y1*LOGO_LINE; - dst = fb + y1*line; - for( x1 = 0; x1 < LOGO_LINE; ++x1 ) - *dst++ = *src++ ^ inverse; - } - done = 1; - } + if (depth == 1 && (p->type == FB_TYPE_PACKED_PIXELS || + p->type == FB_TYPE_PLANES || + p->type == FB_TYPE_INTERLEAVED_PLANES)) { + + /* monochrome */ + unsigned char inverse = p->inverse ? 0x00 : 0xff; + + /* can't use simply memcpy because need to apply inverse */ + for( y1 = 0; y1 < LOGO_H; y1++ ) { + src = logo + y1*LOGO_LINE + x/8; + dst = fb + y1*line; + for( x1 = 0; x1 < LOGO_LINE; ++x1 ) + *dst++ = *src++ ^ inverse; + } + done = 1; + } #endif + } + /* Modes not yet supported: packed pixels with depth != 8 (does such a * thing exist in reality?) */ - return( done ? LOGO_H/p->fontheight + 1 : 0 ); + return done ? (LOGO_H + p->fontheight - 1) / p->fontheight : 0 ; } - - /* * The console `switch' structure for the frame buffer based console */ - + 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_set_mode + con_startup: fbcon_startup, + con_init: fbcon_init, + con_deinit: fbcon_deinit, + con_clear: fbcon_clear, + con_putc: fbcon_putc, + con_putcs: fbcon_putcs, + con_cursor: fbcon_cursor, + con_scroll: fbcon_scroll, + con_bmove: fbcon_bmove, + con_switch: fbcon_switch, + con_blank: fbcon_blank, + con_font_op: fbcon_font_op, + con_set_palette: fbcon_set_palette, + con_scrolldelta: fbcon_scrolldelta, + con_set_origin: NULL, + con_save_screen: NULL, + con_build_attr: NULL, + con_invert_region: NULL, }; @@ -1376,6 +1808,7 @@ static struct display_switch fbcon_dummy = { (void *)fbcon_dummy_op, /* fbcon_dummy_putc */ (void *)fbcon_dummy_op, /* fbcon_dummy_putcs */ (void *)fbcon_dummy_op, /* fbcon_dummy_revc */ + NULL, /* fbcon_dummy_cursor */ }; @@ -1384,3 +1817,4 @@ static struct display_switch fbcon_dummy = { */ EXPORT_SYMBOL(fb_display); +EXPORT_SYMBOL(fbcon_redraw_bmove); diff --git a/drivers/video/fbcon.h b/drivers/video/fbcon.h index 4868b7730..98091ba0c 100644 --- a/drivers/video/fbcon.h +++ b/drivers/video/fbcon.h @@ -11,6 +11,7 @@ #ifndef __VIDEO_FBCON_H #define __VIDEO_FBCON_H +#include <linux/config.h> #include <linux/console_struct.h> @@ -26,31 +27,63 @@ struct display_switch { int height, int width); void (*putc)(struct vc_data *conp, struct display *p, int c, int yy, int xx); - void (*putcs)(struct vc_data *conp, struct display *p, const char *s, + void (*putcs)(struct vc_data *conp, struct display *p, const unsigned short *s, int count, int yy, int xx); void (*revc)(struct display *p, int xx, int yy); + void (*cursor)(struct display *p, int mode, int xx, int yy); + int (*set_font)(struct display *p, int width, int height); + void (*clear_margins)(struct vc_data *conp, struct display *p); + unsigned int fontwidthmask; /* 1 at (1 << (width - 1)) if width is supported */ }; +#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY + +/* fontwidth w is supported by dispsw */ +#define FONTWIDTH(w) (1 << ((8) - 1)) +/* fontwidths w1-w2 inclusive are supported by dispsw */ +#define FONTWIDTHRANGE(w1,w2) FONTWIDTH(8) + +#else + +/* fontwidth w is supported by dispsw */ +#define FONTWIDTH(w) (1 << ((w) - 1)) +/* fontwidths w1-w2 inclusive are supported by dispsw */ +#define FONTWIDTHRANGE(w1,w2) (FONTWIDTH(w2+1) - FONTWIDTH(w1)) + +#endif /* * Attribute Decoding */ /* Color */ -#define attr_fgcol(p,conp) \ - (((conp)->vc_attr >> ((p)->inverse ? 4 : 0)) & 0x0f) -#define attr_bgcol(p,conp) \ - (((conp)->vc_attr >> ((p)->inverse ? 0 : 4)) & 0x0f) +#define attr_fgcol(p,s) \ + (((s) >> ((p)->fgshift)) & 0x0f) +#define attr_bgcol(p,s) \ + (((s) >> ((p)->bgshift)) & 0x0f) #define attr_bgcol_ec(p,conp) \ - (((conp)->vc_video_erase_char >> ((p)->inverse ? 8 : 12)) & 0x0f) + (((conp)->vc_video_erase_char >> ((p)->bgshift)) & 0x0f) /* Monochrome */ -#define attr_bold(p,conp) \ - (((conp)->vc_attr & 3) == 2) -#define attr_reverse(p,conp) \ - (((conp)->vc_attr & 8) ^ ((p)->inverse ? 8 : 0)) -#define attr_underline(p,conp) \ - (((conp)->vc_attr) & 4) +#define attr_bold(p,s) \ + ((s) & 0x200) +#define attr_reverse(p,s) \ + (((s) & 0x800) ^ ((p)->inverse ? 0x800 : 0)) +#define attr_underline(p,s) \ + ((s) & 0x400) +#define attr_blink(p,s) \ + ((s) & 0x8000) + + /* + * Scroll Method + */ + +#define SCROLL_YWRAP (0) +#define SCROLL_YPAN (1) +#define SCROLL_YMOVE (2) +#define SCROLL_YREDRAW (3) + +extern void fbcon_redraw_bmove(struct display *, int, int, int, int, int, int); /* ================================================================= */ @@ -317,6 +350,54 @@ static __inline__ void *mymemset(void *s, size_t count) return(memset(s, 255, count)); } +#ifdef __i386__ +static __inline__ void fast_memmove(void *d, const void *s, size_t count) +{ + if (d < s) { +__asm__ __volatile__ ( + "cld\n\t" + "shrl $1,%%ecx\n\t" + "jnc 1f\n\t" + "movsb\n" + "1:\tshrl $1,%%ecx\n\t" + "jnc 2f\n\t" + "movsw\n" + "2:\trep\n\t" + "movsl" + : /* no output */ + :"c"(count),"D"((long)d),"S"((long)s) + :"cx","di","si","memory"); + } else { +__asm__ __volatile__ ( + "std\n\t" + "shrl $1,%%ecx\n\t" + "jnc 1f\n\t" + "movb 3(%%esi),%%al\n\t" + "movb %%al,3(%%edi)\n\t" + "decl %%esi\n\t" + "decl %%edi\n" + "1:\tshrl $1,%%ecx\n\t" + "jnc 2f\n\t" + "movw 2(%%esi),%%ax\n\t" + "movw %%ax,2(%%edi)\n\t" + "decl %%esi\n\t" + "decl %%edi\n\t" + "decl %%esi\n\t" + "decl %%edi\n" + "2:\trep\n\t" + "movsl" + : /* no output */ + :"c"(count),"D"(count-4+(long)d),"S"(count-4+(long)s) + :"ax","cx","di","si","memory"); + } +} + +static __inline__ void *mymemmove(char *dst, const char *src, size_t size) +{ + fast_memmove(dst, src, size); + return dst; +} +#else static __inline__ void *mymemmove(void *d, const void *s, size_t count) { return(memmove(d, s, count)); @@ -326,6 +407,7 @@ static __inline__ void fast_memmove(char *dst, const char *src, size_t size) { memmove(dst, src, size); } +#endif /* !i386 */ #endif /* !m68k */ diff --git a/drivers/video/fbgen.c b/drivers/video/fbgen.c index 730438d16..3ff647980 100644 --- a/drivers/video/fbgen.c +++ b/drivers/video/fbgen.c @@ -17,45 +17,8 @@ #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 ----------- */ @@ -156,9 +119,10 @@ int fbgen_get_cmap(struct fb_cmap *cmap, int kspc, int con, 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); + else { + int size = fb_display[con].var.bits_per_pixel == 16 ? 64 : 256; + fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2); + } return 0; } @@ -175,8 +139,8 @@ int fbgen_set_cmap(struct fb_cmap *cmap, int kspc, int con, 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))) + int size = fb_display[con].var.bits_per_pixel == 16 ? 64 : 256; + if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0))) return err; } if (con == currcon) /* current console ? */ @@ -272,7 +236,7 @@ void fbgen_set_disp(int con, struct fb_info_gen *info) if (con >= 0) display = &fb_display[con]; else - display = &disp; /* used during initialization */ + display = info->info.disp; /* used during initialization */ if (con == -1) fbhw->get_par(&par, info); @@ -314,9 +278,11 @@ void fbgen_install_cmap(int con, struct fb_info_gen *info) 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); + else { + int size = fb_display[con].var.bits_per_pixel == 16 ? 64 : 256; + fb_set_cmap(fb_default_cmap(size), &fb_display[con].var, 1, + fbhw->setcolreg, &info->info); + } } diff --git a/drivers/video/font.h b/drivers/video/font.h index b020fcdc9..ab4385b17 100644 --- a/drivers/video/font.h +++ b/drivers/video/font.h @@ -13,21 +13,37 @@ #include <linux/types.h> - - /* - * Find a font with a specific name - */ - -extern int findsoftfont(char *name, int *width, int *height, u_char *data[]); - - - /* - * Get the default font for a specific screen size - */ - -extern void getdefaultfont(int xres, int yres, char *name[], int *width, - int *height, u_char *data[]); - +struct fbcon_font_desc { + int idx; + char *name; + int width, height; + void *data; + int pref; +}; + +#define VGA8x8_IDX 0 +#define VGA8x16_IDX 1 +#define PEARL8x8_IDX 2 +#define VGA6x11_IDX 3 +#define SUN8x16_IDX 4 +#define SUN12x22_IDX 5 +#define ACORN8x8_IDX 6 + +extern struct fbcon_font_desc font_vga_8x8, + font_vga_8x16, + font_pearl_8x8, + font_vga_6x11, + font_sun_8x16, + font_sun_12x22, + font_acorn_8x8; + +/* Find a font with a specific name */ + +extern struct fbcon_font_desc *fbcon_find_font(char *name); + +/* Get the default font for a specific screen size */ + +extern struct fbcon_font_desc *fbcon_get_default_font(int xres, int yres); /* Max. length for the name of a predefined font */ #define MAX_FONT_NAME 32 diff --git a/drivers/video/font_6x11.c b/drivers/video/font_6x11.c index ebfe24258..88a20e09e 100644 --- a/drivers/video/font_6x11.c +++ b/drivers/video/font_6x11.c @@ -4,14 +4,11 @@ /* */ /**********************************************/ -#define FONTDATAMAX (11*256) - -char fontname_6x11[] = "ProFont6x11"; +#include "font.h" -int fontheight_6x11 = 11; -int fontwidth_6x11 = 6; +#define FONTDATAMAX (11*256) -unsigned char fontdata_6x11[FONTDATAMAX] = { +static unsigned char fontdata_6x11[FONTDATAMAX] = { /* 0 0x00 '^A' */ 0x00, /* 00000000 */ @@ -3343,3 +3340,12 @@ unsigned char fontdata_6x11[FONTDATAMAX] = { }; + +struct fbcon_font_desc font_vga_6x11 = { + VGA6x11_IDX, + "ProFont6x11", + 6, + 11, + fontdata_6x11, + -2000 /* Try avoiding this font if possible unless on MAC */ +}; diff --git a/drivers/video/font_8x16.c b/drivers/video/font_8x16.c index 59801b438..26a34bce7 100644 --- a/drivers/video/font_8x16.c +++ b/drivers/video/font_8x16.c @@ -4,14 +4,11 @@ /* */ /**********************************************/ -#define FONTDATAMAX 4096 - -char fontname_8x16[] = "VGA8x16"; +#include "font.h" -int fontheight_8x16 = 16; -int fontwidth_8x16 = 8; +#define FONTDATAMAX 4096 -unsigned char fontdata_8x16[FONTDATAMAX] = { +static unsigned char fontdata_8x16[FONTDATAMAX] = { /* 0 0x00 '^@' */ 0x00, /* 00000000 */ @@ -4623,3 +4620,12 @@ unsigned char fontdata_8x16[FONTDATAMAX] = { }; + +struct fbcon_font_desc font_vga_8x16 = { + VGA8x16_IDX, + "VGA8x16", + 8, + 16, + fontdata_8x16, + 0 +}; diff --git a/drivers/video/font_8x8.c b/drivers/video/font_8x8.c index 72a6c3f8f..ff0701a68 100644 --- a/drivers/video/font_8x8.c +++ b/drivers/video/font_8x8.c @@ -4,14 +4,11 @@ /* */ /**********************************************/ -#define FONTDATAMAX 2048 - -char fontname_8x8[] = "VGA8x8"; +#include "font.h" -int fontheight_8x8 = 8; -int fontwidth_8x8 = 8; +#define FONTDATAMAX 2048 -unsigned char fontdata_8x8[FONTDATAMAX] = { +static unsigned char fontdata_8x8[FONTDATAMAX] = { /* 0 0x00 '^@' */ 0x00, /* 00000000 */ @@ -2575,3 +2572,12 @@ unsigned char fontdata_8x8[FONTDATAMAX] = { }; + +struct fbcon_font_desc font_vga_8x8 = { + VGA8x8_IDX, + "VGA8x8", + 8, + 8, + fontdata_8x8, + 0 +}; diff --git a/drivers/video/font_acorn_8x8.c b/drivers/video/font_acorn_8x8.c new file mode 100644 index 000000000..41acfd5f6 --- /dev/null +++ b/drivers/video/font_acorn_8x8.c @@ -0,0 +1,277 @@ +/* Acorn-like font definition, with PC graphics characters */ + +#include <linux/config.h> + +#include "font.h" + +static unsigned char acorndata_8x8[] = { +/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */ +/* 01 */ 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, /* ^A */ +/* 02 */ 0x7e, 0xff, 0xbd, 0xff, 0xc3, 0xe7, 0xff, 0x7e, /* ^B */ +/* 03 */ 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, /* ^C */ +/* 04 */ 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, /* ^D */ +/* 05 */ 0x00, 0x18, 0x3c, 0xe7, 0xe7, 0x3c, 0x18, 0x00, /* ^E */ +/* 06 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 07 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 09 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 0A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 0B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 0C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 0D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 0E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 0F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 10 */ 0x00, 0x60, 0x78, 0x7e, 0x7e, 0x78, 0x60, 0x00, /* |> */ +/* 11 */ 0x00, 0x06, 0x1e, 0x7e, 0x7e, 0x1e, 0x06, 0x00, /* <| */ +/* 12 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 13 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 14 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 15 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 16 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 17 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 19 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 1A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 1B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 1C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 1D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 1E */ 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x7e, 0x7e, 0x00, /* /\ */ +/* 1F */ 0x00, 0x7e, 0x7e, 0x3c, 0x3c, 0x18, 0x18, 0x00, /* \/ */ +/* 20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* */ +/* 21 */ 0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00, /* ! */ +/* 22 */ 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, /* " */ +/* 23 */ 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00, /* # */ +/* 24 */ 0x0C, 0x3F, 0x68, 0x3E, 0x0B, 0x7E, 0x18, 0x00, /* $ */ +/* 25 */ 0x60, 0x66, 0x0C, 0x18, 0x30, 0x66, 0x06, 0x00, /* % */ +/* 26 */ 0x38, 0x6C, 0x6C, 0x38, 0x6D, 0x66, 0x3B, 0x00, /* & */ +/* 27 */ 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' */ +/* 28 */ 0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, /* ( */ +/* 29 */ 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, /* ) */ +/* 2A */ 0x00, 0x18, 0x7E, 0x3C, 0x7E, 0x18, 0x00, 0x00, /* * */ +/* 2B */ 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, /* + */ +/* 2C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, /* , */ +/* 2D */ 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, /* - */ +/* 2E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, /* . */ +/* 2F */ 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, /* / */ +/* 30 */ 0x3C, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x3C, 0x00, /* 0 */ +/* 31 */ 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, /* 1 */ +/* 32 */ 0x3C, 0x66, 0x06, 0x0C, 0x18, 0x30, 0x7E, 0x00, /* 2 */ +/* 33 */ 0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C, 0x00, /* 3 */ +/* 34 */ 0x0C, 0x1C, 0x3C, 0x6C, 0x7E, 0x0C, 0x0C, 0x00, /* 4 */ +/* 35 */ 0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C, 0x00, /* 5 */ +/* 36 */ 0x1C, 0x30, 0x60, 0x7C, 0x66, 0x66, 0x3C, 0x00, /* 6 */ +/* 37 */ 0x7E, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00, /* 7 */ +/* 38 */ 0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00, /* 8 */ +/* 39 */ 0x3C, 0x66, 0x66, 0x3E, 0x06, 0x0C, 0x38, 0x00, /* 9 */ +/* 3A */ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, /* : */ +/* 3B */ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, /* ; */ +/* 3C */ 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00, /* < */ +/* 3D */ 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, /* = */ +/* 3E */ 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00, /* > */ +/* 3F */ 0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00, /* ? */ +/* 40 */ 0x3C, 0x66, 0x6E, 0x6A, 0x6E, 0x60, 0x3C, 0x00, /* @ */ +/* 41 */ 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, /* A */ +/* 42 */ 0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00, /* B */ +/* 43 */ 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x00, /* C */ +/* 44 */ 0x78, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0x78, 0x00, /* D */ +/* 45 */ 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x7E, 0x00, /* E */ +/* 46 */ 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60, 0x00, /* F */ +/* 47 */ 0x3C, 0x66, 0x60, 0x6E, 0x66, 0x66, 0x3C, 0x00, /* G */ +/* 48 */ 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, /* H */ +/* 49 */ 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, /* I */ +/* 4A */ 0x3E, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x00, /* J */ +/* 4B */ 0x66, 0x6C, 0x78, 0x70, 0x78, 0x6C, 0x66, 0x00, /* K */ +/* 4C */ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7E, 0x00, /* L */ +/* 4D */ 0x63, 0x77, 0x7F, 0x6B, 0x6B, 0x63, 0x63, 0x00, /* M */ +/* 4E */ 0x66, 0x66, 0x76, 0x7E, 0x6E, 0x66, 0x66, 0x00, /* N */ +/* 4F */ 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, /* O */ +/* 50 */ 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x00, /* P */ +/* 51 */ 0x3C, 0x66, 0x66, 0x66, 0x6A, 0x6C, 0x36, 0x00, /* Q */ +/* 52 */ 0x7C, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x00, /* R */ +/* 53 */ 0x3C, 0x66, 0x60, 0x3C, 0x06, 0x66, 0x3C, 0x00, /* S */ +/* 54 */ 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, /* T */ +/* 55 */ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, /* U */ +/* 56 */ 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, /* V */ +/* 57 */ 0x63, 0x63, 0x6B, 0x6B, 0x7F, 0x77, 0x63, 0x00, /* W */ +/* 58 */ 0x66, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00, /* X */ +/* 59 */ 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00, /* Y */ +/* 5A */ 0x7E, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x7E, 0x00, /* Z */ +/* 5B */ 0x7C, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7C, 0x00, /* [ */ +/* 5C */ 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, /* \ */ +/* 5D */ 0x3E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x3E, 0x00, /* ] */ +/* 5E */ 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^ */ +/* 5F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, /* _ */ +/* 60 */ 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ` */ +/* 61 */ 0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E, 0x00, /* a */ +/* 62 */ 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x00, /* b */ +/* 63 */ 0x00, 0x00, 0x3C, 0x66, 0x60, 0x66, 0x3C, 0x00, /* c */ +/* 64 */ 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x00, /* d */ +/* 65 */ 0x00, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00, /* e */ +/* 66 */ 0x1C, 0x30, 0x30, 0x7C, 0x30, 0x30, 0x30, 0x00, /* f */ +/* 67 */ 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x3C, /* g */ +/* 68 */ 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00, /* h */ +/* 69 */ 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00, /* i */ +/* 6A */ 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x70, /* j */ +/* 6B */ 0x60, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0x00, /* k */ +/* 6C */ 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, /* l */ +/* 6D */ 0x00, 0x00, 0x36, 0x7F, 0x6B, 0x6B, 0x63, 0x00, /* m */ +/* 6E */ 0x00, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00, /* n */ +/* 6F */ 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, /* o */ +/* 70 */ 0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, /* p */ +/* 71 */ 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x07, /* q */ +/* 72 */ 0x00, 0x00, 0x6C, 0x76, 0x60, 0x60, 0x60, 0x00, /* r */ +/* 73 */ 0x00, 0x00, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x00, /* s */ +/* 74 */ 0x30, 0x30, 0x7C, 0x30, 0x30, 0x30, 0x1C, 0x00, /* t */ +/* 75 */ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00, /* u */ +/* 76 */ 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, /* v */ +/* 77 */ 0x00, 0x00, 0x63, 0x6B, 0x6B, 0x7F, 0x36, 0x00, /* w */ +/* 78 */ 0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00, /* x */ +/* 79 */ 0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x3C, /* y */ +/* 7A */ 0x00, 0x00, 0x7E, 0x0C, 0x18, 0x30, 0x7E, 0x00, /* z */ +/* 7B */ 0x0C, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0C, 0x00, /* { */ +/* 7C */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, /* | */ +/* 7D */ 0x30, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x30, 0x00, /* } */ +/* 7E */ 0x31, 0x6B, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, /* ~ */ +/* 7F */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* */ +/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 81 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 82 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 83 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 84 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 85 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 86 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 87 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 88 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 89 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 8A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 8B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 8C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 8D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 8E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 8F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 91 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 92 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 93 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 94 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 95 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 97 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 98 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 99 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 9A */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 9B */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 9C */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 9D */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 9E */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* 9F */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* A9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* AA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* AB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* AC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* AD */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* AE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* AF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* B0 */ 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, +/* B1 */ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, +/* B2 */ 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, +/* B3 */ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +/* B4 */ 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, +/* B5 */ 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, +/* B6 */ 0x66, 0x66, 0x66, 0xe6, 0x66, 0x66, 0x66, 0x66, +/* B7 */ 0x00, 0x00, 0x00, 0xfe, 0x66, 0x66, 0x66, 0x66, +/* B8 */ 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, +/* B9 */ 0x66, 0x66, 0xe6, 0x06, 0xe6, 0x66, 0x66, 0x66, +/* BA */ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +/* BB */ 0x00, 0x00, 0xfe, 0x06, 0xe6, 0x66, 0x66, 0x66, +/* BC */ 0x66, 0x66, 0xe6, 0x06, 0xfe, 0x00, 0x00, 0x00, +/* BD */ 0x66, 0x66, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, +/* BE */ 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, +/* BF */ 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, +/* C0 */ 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, +/* C1 */ 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, +/* C2 */ 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, +/* C3 */ 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +/* C4 */ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +/* C5 */ 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, +/* C6 */ 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, +/* C7 */ 0x66, 0x66, 0x66, 0x67, 0x66, 0x66, 0x66, 0x66, +/* C8 */ 0x66, 0x66, 0x67, 0x60, 0x7f, 0x00, 0x00, 0x00, +/* C9 */ 0x00, 0x00, 0x7f, 0x60, 0x67, 0x66, 0x66, 0x66, +/* CA */ 0x66, 0x66, 0xe7, 0x00, 0xff, 0x00, 0x00, 0x00, +/* CB */ 0x00, 0x00, 0xff, 0x00, 0xe7, 0x66, 0x66, 0x66, +/* CC */ 0x66, 0x66, 0x67, 0x60, 0x67, 0x66, 0x66, 0x66, +/* CD */ 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, +/* CE */ 0x66, 0x66, 0xe7, 0x00, 0xe7, 0x66, 0x66, 0x66, +/* CF */ 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, +/* D0 */ 0x66, 0x66, 0x66, 0xff, 0x00, 0x00, 0x00, 0x00, +/* D1 */ 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, +/* D2 */ 0x00, 0x00, 0x00, 0xff, 0x66, 0x66, 0x66, 0x66, +/* D3 */ 0x66, 0x66, 0x66, 0x7f, 0x00, 0x00, 0x00, 0x00, +/* D4 */ 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, +/* D5 */ 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, +/* D6 */ 0x00, 0x00, 0x00, 0x7f, 0x66, 0x66, 0x66, 0x66, +/* D7 */ 0x66, 0x66, 0x66, 0xff, 0x66, 0x66, 0x66, 0x66, +/* D8 */ 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, +/* D9 */ 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, +/* DA */ 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, +/* DB */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +/* DC */ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +/* DD */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, +/* DE */ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, +/* DF */ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, +/* E0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* E1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* E2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* E3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* E4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* E5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* E6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* E7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* E8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* E9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* EA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* EB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* EC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* ED */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* EE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* EF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* F1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* F2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* F3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* F4 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* F5 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* F6 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* F7 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* F8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* F9 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* FA */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* FB */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* FC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* FD */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* FE */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* FF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +struct fbcon_font_desc font_acorn_8x8 = { + ACORN8x8_IDX, + "Acorn8x8", + 8, + 8, + acorndata_8x8, +#ifdef CONFIG_ARCH_ACORN + 20 +#else + 0 +#endif +}; diff --git a/drivers/video/pearl_8x8.c b/drivers/video/font_pearl_8x8.c index a48c702d2..1f4e40fa6 100644 --- a/drivers/video/pearl_8x8.c +++ b/drivers/video/font_pearl_8x8.c @@ -9,14 +9,11 @@ /* */ /**********************************************/ -#define FONTDATAMAX 2048 - -char fontname_pearl8x8[] = "PEARL8x8"; +#include "font.h" -int fontheight_pearl8x8 = 8; -int fontwidth_pearl8x8 = 8; +#define FONTDATAMAX 2048 -unsigned char fontdata_pearl8x8[FONTDATAMAX] = { +static unsigned char fontdata_pearl8x8[FONTDATAMAX] = { /* 0 0x00 '^@' */ 0x00, /* 00000000 */ @@ -2580,3 +2577,11 @@ unsigned char fontdata_pearl8x8[FONTDATAMAX] = { }; +struct fbcon_font_desc font_pearl_8x8 = { + PEARL8x8_IDX, + "PEARL8x8", + 8, + 8, + fontdata_pearl8x8, + 2 +}; diff --git a/drivers/video/font_sun12x22.c b/drivers/video/font_sun12x22.c new file mode 100644 index 000000000..837e04203 --- /dev/null +++ b/drivers/video/font_sun12x22.c @@ -0,0 +1,6220 @@ +#include "font.h" + +#define FONTDATAMAX 5632 + +static unsigned short fontdata_sun12x22[FONTDATAMAX] = { + + /* 0 0x00 '^@' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 1 0x01 '^A' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 2 0x02 '^B' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 3 0x03 '^C' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 4 0x04 '^D' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 5 0x05 '^E' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 6 0x06 '^F' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 7 0x07 '^G' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 8 0x08 '^H' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 9 0x09 '^I' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 10 0x0a '^J' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 11 0x0b '^K' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 12 0x0c '^L' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 13 0x0d '^M' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 14 0x0e '^N' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 15 0x0f '^O' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 16 0x10 '^P' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 17 0x11 '^Q' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 18 0x12 '^R' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 19 0x13 '^S' */ + 0x0000, /* 000000000000 */ + 0x3180, /* 001100011000 */ + 0x3180, /* 001100011000 */ + 0x3180, /* 001100011000 */ + 0x3180, /* 001100011000 */ + 0x3180, /* 001100011000 */ + 0x3180, /* 001100011000 */ + 0x3180, /* 001100011000 */ + 0x3180, /* 001100011000 */ + 0x3180, /* 001100011000 */ + 0x3180, /* 001100011000 */ + 0x3180, /* 001100011000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3180, /* 001100011000 */ + 0x3180, /* 001100011000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 20 0x14 '^T' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1ff0, /* 000111111111 */ + 0x3cc0, /* 001111001100 */ + 0x7cc0, /* 011111001100 */ + 0x7cc0, /* 011111001100 */ + 0x7cc0, /* 011111001100 */ + 0x3cc0, /* 001111001100 */ + 0x1cc0, /* 000111001100 */ + 0x0cc0, /* 000011001100 */ + 0x0cc0, /* 000011001100 */ + 0x0cc0, /* 000011001100 */ + 0x0cc0, /* 000011001100 */ + 0x0cc0, /* 000011001100 */ + 0x0cc0, /* 000011001100 */ + 0x1ce0, /* 000111001110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 21 0x15 '^U' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1f00, /* 000111110000 */ + 0x3180, /* 001100011000 */ + 0x3180, /* 001100011000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x1f00, /* 000111110000 */ + 0x3180, /* 001100011000 */ + 0x3180, /* 001100011000 */ + 0x1f00, /* 000111110000 */ + 0x0180, /* 000000011000 */ + 0x0180, /* 000000011000 */ + 0x3180, /* 001100011000 */ + 0x3180, /* 001100011000 */ + 0x1f00, /* 000111110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 22 0x16 '^V' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 23 0x17 '^W' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 24 0x18 '^X' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 25 0x19 '^Y' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 26 0x1a '^Z' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 27 0x1b '^[' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 28 0x1c '^\' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 29 0x1d '^]' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 30 0x1e '^^' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 31 0x1f '^_' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 32 0x20 ' ' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 33 0x21 '!' */ + 0x0000, /* 000000000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 34 0x22 '"' */ + 0x0000, /* 000000000000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 35 0x23 '#' */ + 0x0000, /* 000000000000 */ + 0x0330, /* 000000110011 */ + 0x0330, /* 000000110011 */ + 0x0330, /* 000000110011 */ + 0x0660, /* 000001100110 */ + 0x1ff0, /* 000111111111 */ + 0x1ff0, /* 000111111111 */ + 0x0cc0, /* 000011001100 */ + 0x0cc0, /* 000011001100 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x7fc0, /* 011111111100 */ + 0x7fc0, /* 011111111100 */ + 0x3300, /* 001100110000 */ + 0x6600, /* 011001100000 */ + 0x6600, /* 011001100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 36 0x24 '$' */ + 0x0000, /* 000000000000 */ + 0x0600, /* 000001100000 */ + 0x1f80, /* 000111111000 */ + 0x3fc0, /* 001111111100 */ + 0x66e0, /* 011001101110 */ + 0x6660, /* 011001100110 */ + 0x6600, /* 011001100000 */ + 0x3e00, /* 001111100000 */ + 0x1f80, /* 000111111000 */ + 0x07c0, /* 000001111100 */ + 0x0660, /* 000001100110 */ + 0x0660, /* 000001100110 */ + 0x6660, /* 011001100110 */ + 0x7fc0, /* 011111111100 */ + 0x3f80, /* 001111111000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 37 0x25 '%' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x38c0, /* 001110001100 */ + 0x4cc0, /* 010011001100 */ + 0x4580, /* 010001011000 */ + 0x6580, /* 011001011000 */ + 0x3b00, /* 001110110000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0c00, /* 000011000000 */ + 0x0dc0, /* 000011011100 */ + 0x1a60, /* 000110100110 */ + 0x1a20, /* 000110100010 */ + 0x3320, /* 001100110010 */ + 0x31c0, /* 001100011100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 38 0x26 '&' */ + 0x0000, /* 000000000000 */ + 0x0700, /* 000001110000 */ + 0x0f80, /* 000011111000 */ + 0x18c0, /* 000110001100 */ + 0x18c0, /* 000110001100 */ + 0x18c0, /* 000110001100 */ + 0x0f80, /* 000011111000 */ + 0x1e00, /* 000111100000 */ + 0x3e00, /* 001111100000 */ + 0x7700, /* 011101110000 */ + 0x6360, /* 011000110110 */ + 0x61e0, /* 011000011110 */ + 0x61c0, /* 011000011100 */ + 0x6180, /* 011000011000 */ + 0x3fe0, /* 001111111110 */ + 0x1e60, /* 000111100110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 39 0x27 ''' */ + 0x0000, /* 000000000000 */ + 0x0c00, /* 000011000000 */ + 0x1e00, /* 000111100000 */ + 0x1e00, /* 000111100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0c00, /* 000011000000 */ + 0x1800, /* 000110000000 */ + 0x1000, /* 000100000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 40 0x28 '(' */ + 0x0000, /* 000000000000 */ + 0x0180, /* 000000011000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0300, /* 000000110000 */ + 0x0180, /* 000000011000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 41 0x29 ')' */ + 0x0000, /* 000000000000 */ + 0x1800, /* 000110000000 */ + 0x0c00, /* 000011000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0c00, /* 000011000000 */ + 0x1800, /* 000110000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 42 0x2a '*' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0f00, /* 000011110000 */ + 0x0600, /* 000001100000 */ + 0x6660, /* 011001100110 */ + 0x76e0, /* 011101101110 */ + 0x1980, /* 000110011000 */ + 0x0000, /* 000000000000 */ + 0x1980, /* 000110011000 */ + 0x76e0, /* 011101101110 */ + 0x6660, /* 011001100110 */ + 0x0600, /* 000001100000 */ + 0x0f00, /* 000011110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 43 0x2b '+' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x7fe0, /* 011111111110 */ + 0x7fe0, /* 011111111110 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 44 0x2c ',' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0c00, /* 000011000000 */ + 0x1e00, /* 000111100000 */ + 0x1e00, /* 000111100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0c00, /* 000011000000 */ + 0x1800, /* 000110000000 */ + 0x1000, /* 000100000000 */ + 0x0000, /* 000000000000 */ + + /* 45 0x2d '-' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x7fe0, /* 011111111110 */ + 0x7fe0, /* 011111111110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 46 0x2e '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0c00, /* 000011000000 */ + 0x1e00, /* 000111100000 */ + 0x1e00, /* 000111100000 */ + 0x0c00, /* 000011000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 47 0x2f '/' */ + 0x0000, /* 000000000000 */ + 0x0060, /* 000000000110 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x0180, /* 000000011000 */ + 0x0180, /* 000000011000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x1800, /* 000110000000 */ + 0x1800, /* 000110000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x6000, /* 011000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 48 0x30 '0' */ + 0x0000, /* 000000000000 */ + 0x0700, /* 000001110000 */ + 0x0f80, /* 000011111000 */ + 0x1180, /* 000100011000 */ + 0x10c0, /* 000100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x3080, /* 001100001000 */ + 0x1880, /* 000110001000 */ + 0x1f00, /* 000111110000 */ + 0x0e00, /* 000011100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 49 0x31 '1' */ + 0x0000, /* 000000000000 */ + 0x0200, /* 000000100000 */ + 0x0600, /* 000001100000 */ + 0x0e00, /* 000011100000 */ + 0x1e00, /* 000111100000 */ + 0x3600, /* 001101100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 50 0x32 '2' */ + 0x0000, /* 000000000000 */ + 0x1f00, /* 000111110000 */ + 0x3f80, /* 001111111000 */ + 0x61c0, /* 011000011100 */ + 0x40c0, /* 010000001100 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x0180, /* 000000011000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0c00, /* 000011000000 */ + 0x1800, /* 000110000000 */ + 0x3020, /* 001100000010 */ + 0x7fe0, /* 011111111110 */ + 0x7fe0, /* 011111111110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 51 0x33 '3' */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x1fc0, /* 000111111100 */ + 0x20e0, /* 001000001110 */ + 0x4060, /* 010000000110 */ + 0x0060, /* 000000000110 */ + 0x00e0, /* 000000001110 */ + 0x07c0, /* 000001111100 */ + 0x0fc0, /* 000011111100 */ + 0x00e0, /* 000000001110 */ + 0x0060, /* 000000000110 */ + 0x0060, /* 000000000110 */ + 0x4060, /* 010000000110 */ + 0x6040, /* 011000000100 */ + 0x3f80, /* 001111111000 */ + 0x1f00, /* 000111110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 52 0x34 '4' */ + 0x0000, /* 000000000000 */ + 0x0180, /* 000000011000 */ + 0x0380, /* 000000111000 */ + 0x0380, /* 000000111000 */ + 0x0580, /* 000001011000 */ + 0x0580, /* 000001011000 */ + 0x0980, /* 000010011000 */ + 0x0980, /* 000010011000 */ + 0x1180, /* 000100011000 */ + 0x1180, /* 000100011000 */ + 0x2180, /* 001000011000 */ + 0x3fe0, /* 001111111110 */ + 0x7fe0, /* 011111111110 */ + 0x0180, /* 000000011000 */ + 0x0180, /* 000000011000 */ + 0x0180, /* 000000011000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 53 0x35 '5' */ + 0x0000, /* 000000000000 */ + 0x0fc0, /* 000011111100 */ + 0x0fc0, /* 000011111100 */ + 0x1000, /* 000100000000 */ + 0x1000, /* 000100000000 */ + 0x2000, /* 001000000000 */ + 0x3f80, /* 001111111000 */ + 0x31c0, /* 001100011100 */ + 0x00e0, /* 000000001110 */ + 0x0060, /* 000000000110 */ + 0x0060, /* 000000000110 */ + 0x0060, /* 000000000110 */ + 0x4060, /* 010000000110 */ + 0x6060, /* 011000000110 */ + 0x30c0, /* 001100001100 */ + 0x1f80, /* 000111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 54 0x36 '6' */ + 0x0000, /* 000000000000 */ + 0x0700, /* 000001110000 */ + 0x0c00, /* 000011000000 */ + 0x1800, /* 000110000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x6000, /* 011000000000 */ + 0x6780, /* 011001111000 */ + 0x6fc0, /* 011011111100 */ + 0x70e0, /* 011100001110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x7040, /* 011100000100 */ + 0x3f80, /* 001111111000 */ + 0x1f00, /* 000111110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 55 0x37 '7' */ + 0x0000, /* 000000000000 */ + 0x1fe0, /* 000111111110 */ + 0x3fe0, /* 001111111110 */ + 0x6040, /* 011000000100 */ + 0x0040, /* 000000000100 */ + 0x00c0, /* 000000001100 */ + 0x0080, /* 000000001000 */ + 0x0080, /* 000000001000 */ + 0x0180, /* 000000011000 */ + 0x0100, /* 000000010000 */ + 0x0100, /* 000000010000 */ + 0x0300, /* 000000110000 */ + 0x0200, /* 000000100000 */ + 0x0200, /* 000000100000 */ + 0x0600, /* 000001100000 */ + 0x0400, /* 000001000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 56 0x38 '8' */ + 0x0000, /* 000000000000 */ + 0x0f00, /* 000011110000 */ + 0x1180, /* 000100011000 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x1880, /* 000110001000 */ + 0x0d00, /* 000011010000 */ + 0x0600, /* 000001100000 */ + 0x0b00, /* 000010110000 */ + 0x1180, /* 000100011000 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x1880, /* 000110001000 */ + 0x0f00, /* 000011110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 57 0x39 '9' */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x11c0, /* 000100011100 */ + 0x20e0, /* 001000001110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x70e0, /* 011100001110 */ + 0x3f60, /* 001111110110 */ + 0x1e60, /* 000111100110 */ + 0x0060, /* 000000000110 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x0180, /* 000000011000 */ + 0x0700, /* 000001110000 */ + 0x3c00, /* 001111000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 58 0x3a ':' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0c00, /* 000011000000 */ + 0x1e00, /* 000111100000 */ + 0x1e00, /* 000111100000 */ + 0x0c00, /* 000011000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0c00, /* 000011000000 */ + 0x1e00, /* 000111100000 */ + 0x1e00, /* 000111100000 */ + 0x0c00, /* 000011000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 59 0x3b ';' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0c00, /* 000011000000 */ + 0x1e00, /* 000111100000 */ + 0x1e00, /* 000111100000 */ + 0x0c00, /* 000011000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0c00, /* 000011000000 */ + 0x1e00, /* 000111100000 */ + 0x1e00, /* 000111100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0c00, /* 000011000000 */ + 0x1800, /* 000110000000 */ + 0x1000, /* 000100000000 */ + 0x0000, /* 000000000000 */ + + /* 60 0x3c '<' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0060, /* 000000000110 */ + 0x01c0, /* 000000011100 */ + 0x0700, /* 000001110000 */ + 0x1c00, /* 000111000000 */ + 0x7000, /* 011100000000 */ + 0x7000, /* 011100000000 */ + 0x1c00, /* 000111000000 */ + 0x0700, /* 000001110000 */ + 0x01c0, /* 000000011100 */ + 0x0060, /* 000000000110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 61 0x3d '=' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x7fe0, /* 011111111110 */ + 0x7fe0, /* 011111111110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x7fe0, /* 011111111110 */ + 0x7fe0, /* 011111111110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 62 0x3e '>' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x6000, /* 011000000000 */ + 0x3800, /* 001110000000 */ + 0x0e00, /* 000011100000 */ + 0x0380, /* 000000111000 */ + 0x00e0, /* 000000001110 */ + 0x00e0, /* 000000001110 */ + 0x0380, /* 000000111000 */ + 0x0e00, /* 000011100000 */ + 0x3800, /* 001110000000 */ + 0x6000, /* 011000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 63 0x3f '?' */ + 0x0000, /* 000000000000 */ + 0x0f00, /* 000011110000 */ + 0x1f80, /* 000111111000 */ + 0x39c0, /* 001110011100 */ + 0x20c0, /* 001000001100 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x0180, /* 000000011000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 64 0x40 '@' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x3fc0, /* 001111111100 */ + 0x3060, /* 001100000110 */ + 0x6060, /* 011000000110 */ + 0x6720, /* 011001110010 */ + 0x6fa0, /* 011011111010 */ + 0x6ca0, /* 011011001010 */ + 0x6ca0, /* 011011001010 */ + 0x67e0, /* 011001111110 */ + 0x6000, /* 011000000000 */ + 0x3000, /* 001100000000 */ + 0x3fe0, /* 001111111110 */ + 0x0fe0, /* 000011111110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 65 0x41 'A' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0b00, /* 000010110000 */ + 0x0b00, /* 000010110000 */ + 0x0900, /* 000010010000 */ + 0x1180, /* 000100011000 */ + 0x1180, /* 000100011000 */ + 0x1080, /* 000100001000 */ + 0x3fc0, /* 001111111100 */ + 0x20c0, /* 001000001100 */ + 0x2040, /* 001000000100 */ + 0x4060, /* 010000000110 */ + 0x4060, /* 010000000110 */ + 0xe0f0, /* 111000001111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 66 0x42 'B' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xff00, /* 111111110000 */ + 0x6080, /* 011000001000 */ + 0x60c0, /* 011000001100 */ + 0x60c0, /* 011000001100 */ + 0x60c0, /* 011000001100 */ + 0x6180, /* 011000011000 */ + 0x7f80, /* 011111111000 */ + 0x60c0, /* 011000001100 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x60c0, /* 011000001100 */ + 0xff80, /* 111111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 67 0x43 'C' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0fc0, /* 000011111100 */ + 0x1060, /* 000100000110 */ + 0x2020, /* 001000000010 */ + 0x2000, /* 001000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x2000, /* 001000000000 */ + 0x3020, /* 001100000010 */ + 0x1840, /* 000110000100 */ + 0x0f80, /* 000011111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 68 0x44 'D' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xff00, /* 111111110000 */ + 0x61c0, /* 011000011100 */ + 0x60c0, /* 011000001100 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6040, /* 011000000100 */ + 0x6180, /* 011000011000 */ + 0xfe00, /* 111111100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 69 0x45 'E' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x7fc0, /* 011111111100 */ + 0x3040, /* 001100000100 */ + 0x3040, /* 001100000100 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3080, /* 001100001000 */ + 0x3f80, /* 001111111000 */ + 0x3080, /* 001100001000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3020, /* 001100000010 */ + 0x3020, /* 001100000010 */ + 0x7fe0, /* 011111111110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 70 0x46 'F' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x7fc0, /* 011111111100 */ + 0x3040, /* 001100000100 */ + 0x3040, /* 001100000100 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3080, /* 001100001000 */ + 0x3f80, /* 001111111000 */ + 0x3080, /* 001100001000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x7800, /* 011110000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 71 0x47 'G' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0fc0, /* 000011111100 */ + 0x1060, /* 000100000110 */ + 0x2020, /* 001000000010 */ + 0x2000, /* 001000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x61f0, /* 011000011111 */ + 0x6060, /* 011000000110 */ + 0x2060, /* 001000000110 */ + 0x3060, /* 001100000110 */ + 0x1860, /* 000110000110 */ + 0x0f80, /* 000011111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 72 0x48 'H' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xf0f0, /* 111100001111 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x7fe0, /* 011111111110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0xf0f0, /* 111100001111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 73 0x49 'I' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1f80, /* 000111111000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x1f80, /* 000111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 74 0x4a 'J' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1f80, /* 000111111000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0400, /* 000001000000 */ + 0x3800, /* 001110000000 */ + 0x3000, /* 001100000000 */ + 0x0000, /* 000000000000 */ + + /* 75 0x4b 'K' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xf0e0, /* 111100001110 */ + 0x6180, /* 011000011000 */ + 0x6300, /* 011000110000 */ + 0x6600, /* 011001100000 */ + 0x6c00, /* 011011000000 */ + 0x7800, /* 011110000000 */ + 0x7800, /* 011110000000 */ + 0x7c00, /* 011111000000 */ + 0x6e00, /* 011011100000 */ + 0x6700, /* 011001110000 */ + 0x6380, /* 011000111000 */ + 0x61c0, /* 011000011100 */ + 0x60e0, /* 011000001110 */ + 0xf070, /* 111100000111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 76 0x4c 'L' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x7800, /* 011110000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3020, /* 001100000010 */ + 0x3020, /* 001100000010 */ + 0x7fe0, /* 011111111110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 77 0x4d 'M' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xe070, /* 111000000111 */ + 0x60e0, /* 011000001110 */ + 0x70e0, /* 011100001110 */ + 0x70e0, /* 011100001110 */ + 0x70e0, /* 011100001110 */ + 0x5960, /* 010110010110 */ + 0x5960, /* 010110010110 */ + 0x5960, /* 010110010110 */ + 0x4d60, /* 010011010110 */ + 0x4e60, /* 010011100110 */ + 0x4e60, /* 010011100110 */ + 0x4460, /* 010001000110 */ + 0x4460, /* 010001000110 */ + 0xe4f0, /* 111001001111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 78 0x4e 'N' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xc070, /* 110000000111 */ + 0x6020, /* 011000000010 */ + 0x7020, /* 011100000010 */ + 0x7820, /* 011110000010 */ + 0x5820, /* 010110000010 */ + 0x4c20, /* 010011000010 */ + 0x4620, /* 010001100010 */ + 0x4720, /* 010001110010 */ + 0x4320, /* 010000110010 */ + 0x41a0, /* 010000011010 */ + 0x40e0, /* 010000001110 */ + 0x40e0, /* 010000001110 */ + 0x4060, /* 010000000110 */ + 0xe030, /* 111000000011 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 79 0x4f 'O' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0f00, /* 000011110000 */ + 0x11c0, /* 000100011100 */ + 0x20c0, /* 001000001100 */ + 0x2060, /* 001000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x2040, /* 001000000100 */ + 0x3040, /* 001100000100 */ + 0x1880, /* 000110001000 */ + 0x0f00, /* 000011110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 80 0x50 'P' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x7f80, /* 011111111000 */ + 0x30c0, /* 001100001100 */ + 0x3060, /* 001100000110 */ + 0x3060, /* 001100000110 */ + 0x3060, /* 001100000110 */ + 0x30c0, /* 001100001100 */ + 0x3780, /* 001101111000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x7800, /* 011110000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 81 0x51 'Q' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0f00, /* 000011110000 */ + 0x11c0, /* 000100011100 */ + 0x20c0, /* 001000001100 */ + 0x2060, /* 001000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x3040, /* 001100000100 */ + 0x3840, /* 001110000100 */ + 0x1f80, /* 000111111000 */ + 0x0e00, /* 000011100000 */ + 0x1f00, /* 000111110000 */ + 0x2390, /* 001000111001 */ + 0x01e0, /* 000000011110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 82 0x52 'R' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xff00, /* 111111110000 */ + 0x6180, /* 011000011000 */ + 0x60c0, /* 011000001100 */ + 0x60c0, /* 011000001100 */ + 0x60c0, /* 011000001100 */ + 0x6080, /* 011000001000 */ + 0x7f00, /* 011111110000 */ + 0x7c00, /* 011111000000 */ + 0x6e00, /* 011011100000 */ + 0x6700, /* 011001110000 */ + 0x6380, /* 011000111000 */ + 0x61c0, /* 011000011100 */ + 0x60e0, /* 011000001110 */ + 0xf070, /* 111100000111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 83 0x53 'S' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1fe0, /* 000111111110 */ + 0x3060, /* 001100000110 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x7000, /* 011100000000 */ + 0x3c00, /* 001111000000 */ + 0x1e00, /* 000111100000 */ + 0x0780, /* 000001111000 */ + 0x01c0, /* 000000011100 */ + 0x00e0, /* 000000001110 */ + 0x4060, /* 010000000110 */ + 0x4060, /* 010000000110 */ + 0x60c0, /* 011000001100 */ + 0x7f80, /* 011111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 84 0x54 'T' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x7fe0, /* 011111111110 */ + 0x4620, /* 010001100010 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x1f80, /* 000111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 85 0x55 'U' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xf070, /* 111100000111 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x7040, /* 011100000100 */ + 0x3fc0, /* 001111111100 */ + 0x1f80, /* 000111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 86 0x56 'V' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xe0e0, /* 111000001110 */ + 0x6040, /* 011000000100 */ + 0x3080, /* 001100001000 */ + 0x3080, /* 001100001000 */ + 0x3080, /* 001100001000 */ + 0x1900, /* 000110010000 */ + 0x1900, /* 000110010000 */ + 0x1900, /* 000110010000 */ + 0x0a00, /* 000010100000 */ + 0x0e00, /* 000011100000 */ + 0x0e00, /* 000011100000 */ + 0x0400, /* 000001000000 */ + 0x0400, /* 000001000000 */ + 0x0400, /* 000001000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 87 0x57 'W' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xfef0, /* 111111101111 */ + 0x6620, /* 011001100010 */ + 0x6620, /* 011001100010 */ + 0x6620, /* 011001100010 */ + 0x7620, /* 011101100010 */ + 0x7740, /* 011101110100 */ + 0x3340, /* 001100110100 */ + 0x3740, /* 001101110100 */ + 0x3bc0, /* 001110111100 */ + 0x3b80, /* 001110111000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 88 0x58 'X' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xf070, /* 111100000111 */ + 0x6020, /* 011000000010 */ + 0x3040, /* 001100000100 */ + 0x3880, /* 001110001000 */ + 0x1880, /* 000110001000 */ + 0x0d00, /* 000011010000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0b00, /* 000010110000 */ + 0x1180, /* 000100011000 */ + 0x11c0, /* 000100011100 */ + 0x20c0, /* 001000001100 */ + 0x4060, /* 010000000110 */ + 0xe0f0, /* 111000001111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 89 0x59 'Y' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xf070, /* 111100000111 */ + 0x6020, /* 011000000010 */ + 0x3040, /* 001100000100 */ + 0x1880, /* 000110001000 */ + 0x1880, /* 000110001000 */ + 0x0d00, /* 000011010000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0f00, /* 000011110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 90 0x5a 'Z' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fe0, /* 001111111110 */ + 0x20c0, /* 001000001100 */ + 0x00c0, /* 000000001100 */ + 0x0180, /* 000000011000 */ + 0x0180, /* 000000011000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x1800, /* 000110000000 */ + 0x1820, /* 000110000010 */ + 0x3fe0, /* 001111111110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 91 0x5b '[' */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x0f80, /* 000011111000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0f80, /* 000011111000 */ + 0x0f80, /* 000011111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 92 0x5c '\' */ + 0x0000, /* 000000000000 */ + 0x6000, /* 011000000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x1800, /* 000110000000 */ + 0x1800, /* 000110000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0180, /* 000000011000 */ + 0x0180, /* 000000011000 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x0060, /* 000000000110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 93 0x5d ']' */ + 0x0000, /* 000000000000 */ + 0x1f00, /* 000111110000 */ + 0x1f00, /* 000111110000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x1f00, /* 000111110000 */ + 0x1f00, /* 000111110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 94 0x5e '^' */ + 0x0000, /* 000000000000 */ + 0x0400, /* 000001000000 */ + 0x0e00, /* 000011100000 */ + 0x1b00, /* 000110110000 */ + 0x3180, /* 001100011000 */ + 0x60c0, /* 011000001100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 95 0x5f '_' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 96 0x60 '`' */ + 0x0000, /* 000000000000 */ + 0x0100, /* 000000010000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0780, /* 000001111000 */ + 0x0780, /* 000001111000 */ + 0x0300, /* 000000110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 97 0x61 'a' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x18c0, /* 000110001100 */ + 0x10c0, /* 000100001100 */ + 0x03c0, /* 000000111100 */ + 0x1cc0, /* 000111001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x39c0, /* 001110011100 */ + 0x1ee0, /* 000111101110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 98 0x62 'b' */ + 0x0000, /* 000000000000 */ + 0x2000, /* 001000000000 */ + 0x6000, /* 011000000000 */ + 0xe000, /* 111000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6780, /* 011001111000 */ + 0x6fc0, /* 011011111100 */ + 0x70e0, /* 011100001110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x7060, /* 011100000110 */ + 0x78c0, /* 011110001100 */ + 0x4f80, /* 010011111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 99 0x63 'c' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1f80, /* 000111111000 */ + 0x31c0, /* 001100011100 */ + 0x20c0, /* 001000001100 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x7040, /* 011100000100 */ + 0x30c0, /* 001100001100 */ + 0x1f80, /* 000111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 100 0x64 'd' */ + 0x0000, /* 000000000000 */ + 0x0060, /* 000000000110 */ + 0x00e0, /* 000000001110 */ + 0x0060, /* 000000000110 */ + 0x0060, /* 000000000110 */ + 0x0060, /* 000000000110 */ + 0x0f60, /* 000011110110 */ + 0x31e0, /* 001100011110 */ + 0x20e0, /* 001000001110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x70e0, /* 011100001110 */ + 0x3960, /* 001110010110 */ + 0x1e70, /* 000111100111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 101 0x65 'e' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0f00, /* 000011110000 */ + 0x30c0, /* 001100001100 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x7fe0, /* 011111111110 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x3000, /* 001100000000 */ + 0x1860, /* 000110000110 */ + 0x0f80, /* 000011111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 102 0x66 'f' */ + 0x0000, /* 000000000000 */ + 0x0380, /* 000000111000 */ + 0x04c0, /* 000001001100 */ + 0x04c0, /* 000001001100 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x3f80, /* 001111111000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x1e00, /* 000111100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 103 0x67 'g' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1f20, /* 000111110010 */ + 0x31e0, /* 001100011110 */ + 0x60c0, /* 011000001100 */ + 0x60c0, /* 011000001100 */ + 0x60c0, /* 011000001100 */ + 0x3180, /* 001100011000 */ + 0x3f00, /* 001111110000 */ + 0x6000, /* 011000000000 */ + 0x7fc0, /* 011111111100 */ + 0x3fe0, /* 001111111110 */ + 0x2060, /* 001000000110 */ + 0x4020, /* 010000000010 */ + 0x4020, /* 010000000010 */ + 0x7fc0, /* 011111111100 */ + 0x3f80, /* 001111111000 */ + 0x0000, /* 000000000000 */ + + /* 104 0x68 'h' */ + 0x0000, /* 000000000000 */ + 0x1000, /* 000100000000 */ + 0x3000, /* 001100000000 */ + 0x7000, /* 011100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3780, /* 001101111000 */ + 0x39c0, /* 001110011100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x79e0, /* 011110011110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 105 0x69 'i' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1e00, /* 000111100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x1f80, /* 000111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 106 0x6a 'j' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x03c0, /* 000000111100 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x20c0, /* 001000001100 */ + 0x30c0, /* 001100001100 */ + 0x3880, /* 001110001000 */ + 0x1f00, /* 000111110000 */ + 0x0e00, /* 000011100000 */ + 0x0000, /* 000000000000 */ + + /* 107 0x6b 'k' */ + 0x0000, /* 000000000000 */ + 0x6000, /* 011000000000 */ + 0xe000, /* 111000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x61c0, /* 011000011100 */ + 0x6300, /* 011000110000 */ + 0x6600, /* 011001100000 */ + 0x7c00, /* 011111000000 */ + 0x7800, /* 011110000000 */ + 0x7c00, /* 011111000000 */ + 0x6e00, /* 011011100000 */ + 0x6700, /* 011001110000 */ + 0x6380, /* 011000111000 */ + 0xf1e0, /* 111100011110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 108 0x6c 'l' */ + 0x0000, /* 000000000000 */ + 0x1e00, /* 000111100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x1f80, /* 000111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 109 0x6d 'm' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xddc0, /* 110111011100 */ + 0x6ee0, /* 011011101110 */ + 0x6660, /* 011001100110 */ + 0x6660, /* 011001100110 */ + 0x6660, /* 011001100110 */ + 0x6660, /* 011001100110 */ + 0x6660, /* 011001100110 */ + 0x6660, /* 011001100110 */ + 0x6660, /* 011001100110 */ + 0xef70, /* 111011110111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 110 0x6e 'n' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x2780, /* 001001111000 */ + 0x79c0, /* 011110011100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x79e0, /* 011110011110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 111 0x6f 'o' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x11c0, /* 000100011100 */ + 0x20e0, /* 001000001110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x7040, /* 011100000100 */ + 0x3880, /* 001110001000 */ + 0x1f00, /* 000111110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 112 0x70 'p' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xef80, /* 111011111000 */ + 0x71c0, /* 011100011100 */ + 0x60e0, /* 011000001110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6040, /* 011000000100 */ + 0x7080, /* 011100001000 */ + 0x7f00, /* 011111110000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0xf000, /* 111100000000 */ + 0x0000, /* 000000000000 */ + + /* 113 0x71 'q' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0f20, /* 000011110010 */ + 0x11e0, /* 000100011110 */ + 0x20e0, /* 001000001110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x7060, /* 011100000110 */ + 0x38e0, /* 001110001110 */ + 0x1fe0, /* 000111111110 */ + 0x0060, /* 000000000110 */ + 0x0060, /* 000000000110 */ + 0x0060, /* 000000000110 */ + 0x0060, /* 000000000110 */ + 0x00f0, /* 000000001111 */ + 0x0000, /* 000000000000 */ + + /* 114 0x72 'r' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x7380, /* 011100111000 */ + 0x34c0, /* 001101001100 */ + 0x38c0, /* 001110001100 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x7800, /* 011110000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 115 0x73 's' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1fc0, /* 000111111100 */ + 0x30c0, /* 001100001100 */ + 0x3040, /* 001100000100 */ + 0x3800, /* 001110000000 */ + 0x1e00, /* 000111100000 */ + 0x0780, /* 000001111000 */ + 0x01c0, /* 000000011100 */ + 0x20c0, /* 001000001100 */ + 0x30c0, /* 001100001100 */ + 0x3f80, /* 001111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 116 0x74 't' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0400, /* 000001000000 */ + 0x0400, /* 000001000000 */ + 0x0c00, /* 000011000000 */ + 0x7fc0, /* 011111111100 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c00, /* 000011000000 */ + 0x0c20, /* 000011000010 */ + 0x0e40, /* 000011100100 */ + 0x0780, /* 000001111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 117 0x75 'u' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x79e0, /* 011110011110 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x39c0, /* 001110011100 */ + 0x1e60, /* 000111100110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 118 0x76 'v' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xf070, /* 111100000111 */ + 0x6020, /* 011000000010 */ + 0x3040, /* 001100000100 */ + 0x3040, /* 001100000100 */ + 0x1880, /* 000110001000 */ + 0x1880, /* 000110001000 */ + 0x0d00, /* 000011010000 */ + 0x0d00, /* 000011010000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 119 0x77 'w' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xff70, /* 111111110111 */ + 0x6620, /* 011001100010 */ + 0x6620, /* 011001100010 */ + 0x6620, /* 011001100010 */ + 0x3740, /* 001101110100 */ + 0x3b40, /* 001110110100 */ + 0x3b40, /* 001110110100 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 120 0x78 'x' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xf8f0, /* 111110001111 */ + 0x7040, /* 011100000100 */ + 0x3880, /* 001110001000 */ + 0x1d00, /* 000111010000 */ + 0x0e00, /* 000011100000 */ + 0x0700, /* 000001110000 */ + 0x0b80, /* 000010111000 */ + 0x11c0, /* 000100011100 */ + 0x20e0, /* 001000001110 */ + 0xf1f0, /* 111100011111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 121 0x79 'y' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xf0f0, /* 111100001111 */ + 0x6020, /* 011000000010 */ + 0x3040, /* 001100000100 */ + 0x3040, /* 001100000100 */ + 0x1880, /* 000110001000 */ + 0x1880, /* 000110001000 */ + 0x0d00, /* 000011010000 */ + 0x0d00, /* 000011010000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0400, /* 000001000000 */ + 0x0c00, /* 000011000000 */ + 0x0800, /* 000010000000 */ + 0x7800, /* 011110000000 */ + 0x7000, /* 011100000000 */ + 0x0000, /* 000000000000 */ + + /* 122 0x7a 'z' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x7fe0, /* 011111111110 */ + 0x60e0, /* 011000001110 */ + 0x41c0, /* 010000011100 */ + 0x0380, /* 000000111000 */ + 0x0700, /* 000001110000 */ + 0x0e00, /* 000011100000 */ + 0x1c00, /* 000111000000 */ + 0x3820, /* 001110000010 */ + 0x7060, /* 011100000110 */ + 0x7fe0, /* 011111111110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 123 0x7b '{' */ + 0x0000, /* 000000000000 */ + 0x0380, /* 000000111000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0c00, /* 000011000000 */ + 0x3800, /* 001110000000 */ + 0x0c00, /* 000011000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0380, /* 000000111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 124 0x7c '|' */ + 0x0000, /* 000000000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + + /* 125 0x7d '}' */ + 0x0000, /* 000000000000 */ + 0x1c00, /* 000111000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0300, /* 000000110000 */ + 0x01c0, /* 000000011100 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x1c00, /* 000111000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 126 0x7e '~' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1c20, /* 000111000010 */ + 0x3e60, /* 001111100110 */ + 0x67c0, /* 011001111100 */ + 0x4380, /* 010000111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 127 0x7f '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 128 0x80 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0fc0, /* 000011111100 */ + 0x1060, /* 000100000110 */ + 0x2020, /* 001000000010 */ + 0x2000, /* 001000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x2000, /* 001000000000 */ + 0x3020, /* 001100000010 */ + 0x1840, /* 000110000100 */ + 0x0f80, /* 000011111000 */ + 0x0600, /* 000001100000 */ + 0x0300, /* 000000110000 */ + 0x0180, /* 000000011000 */ + 0x0f00, /* 000011110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 129 0x81 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x79e0, /* 011110011110 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x39c0, /* 001110011100 */ + 0x1e60, /* 000111100110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 130 0x82 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0180, /* 000000011000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0f00, /* 000011110000 */ + 0x30c0, /* 001100001100 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x7fe0, /* 011111111110 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x3000, /* 001100000000 */ + 0x1860, /* 000110000110 */ + 0x0f80, /* 000011111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 131 0x83 '.' */ + 0x0000, /* 000000000000 */ + 0x0200, /* 000000100000 */ + 0x0700, /* 000001110000 */ + 0x0d80, /* 000011011000 */ + 0x18c0, /* 000110001100 */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x18c0, /* 000110001100 */ + 0x10c0, /* 000100001100 */ + 0x03c0, /* 000000111100 */ + 0x1cc0, /* 000111001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x39c0, /* 001110011100 */ + 0x1ee0, /* 000111101110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 132 0x84 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x18c0, /* 000110001100 */ + 0x10c0, /* 000100001100 */ + 0x03c0, /* 000000111100 */ + 0x1cc0, /* 000111001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x39c0, /* 001110011100 */ + 0x1ee0, /* 000111101110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 133 0x85 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0c00, /* 000011000000 */ + 0x0600, /* 000001100000 */ + 0x0300, /* 000000110000 */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x18c0, /* 000110001100 */ + 0x10c0, /* 000100001100 */ + 0x03c0, /* 000000111100 */ + 0x1cc0, /* 000111001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x39c0, /* 001110011100 */ + 0x1ee0, /* 000111101110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 134 0x86 '.' */ + 0x0000, /* 000000000000 */ + 0x0700, /* 000001110000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0700, /* 000001110000 */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x18c0, /* 000110001100 */ + 0x10c0, /* 000100001100 */ + 0x03c0, /* 000000111100 */ + 0x1cc0, /* 000111001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x39c0, /* 001110011100 */ + 0x1ee0, /* 000111101110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 135 0x87 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1f80, /* 000111111000 */ + 0x31c0, /* 001100011100 */ + 0x20c0, /* 001000001100 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x7040, /* 011100000100 */ + 0x30c0, /* 001100001100 */ + 0x1f80, /* 000111111000 */ + 0x0600, /* 000001100000 */ + 0x0300, /* 000000110000 */ + 0x0180, /* 000000011000 */ + 0x0f00, /* 000011110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 136 0x88 '.' */ + 0x0000, /* 000000000000 */ + 0x0200, /* 000000100000 */ + 0x0700, /* 000001110000 */ + 0x0d80, /* 000011011000 */ + 0x18c0, /* 000110001100 */ + 0x0000, /* 000000000000 */ + 0x0f00, /* 000011110000 */ + 0x30c0, /* 001100001100 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x7fe0, /* 011111111110 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x3000, /* 001100000000 */ + 0x1860, /* 000110000110 */ + 0x0f80, /* 000011111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 137 0x89 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0f00, /* 000011110000 */ + 0x30c0, /* 001100001100 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x7fe0, /* 011111111110 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x3000, /* 001100000000 */ + 0x1860, /* 000110000110 */ + 0x0f80, /* 000011111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 138 0x8a '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0c00, /* 000011000000 */ + 0x0600, /* 000001100000 */ + 0x0300, /* 000000110000 */ + 0x0000, /* 000000000000 */ + 0x0f00, /* 000011110000 */ + 0x30c0, /* 001100001100 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x7fe0, /* 011111111110 */ + 0x6000, /* 011000000000 */ + 0x6000, /* 011000000000 */ + 0x3000, /* 001100000000 */ + 0x1860, /* 000110000110 */ + 0x0f80, /* 000011111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 139 0x8b '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1e00, /* 000111100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x1f80, /* 000111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 140 0x8c '.' */ + 0x0000, /* 000000000000 */ + 0x0400, /* 000001000000 */ + 0x0e00, /* 000011100000 */ + 0x1b00, /* 000110110000 */ + 0x3180, /* 001100011000 */ + 0x0000, /* 000000000000 */ + 0x1e00, /* 000111100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x1f80, /* 000111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 141 0x8d '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1800, /* 000110000000 */ + 0x0c00, /* 000011000000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x1e00, /* 000111100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x1f80, /* 000111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 142 0x8e '.' */ + 0x0000, /* 000000000000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x0000, /* 000000000000 */ + 0x0400, /* 000001000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0b00, /* 000010110000 */ + 0x0b00, /* 000010110000 */ + 0x1980, /* 000110011000 */ + 0x1180, /* 000100011000 */ + 0x3fc0, /* 001111111100 */ + 0x20c0, /* 001000001100 */ + 0x6060, /* 011000000110 */ + 0x4060, /* 010000000110 */ + 0xe0f0, /* 111000001111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 143 0x8f '.' */ + 0x0000, /* 000000000000 */ + 0x0f00, /* 000011110000 */ + 0x1980, /* 000110011000 */ + 0x0f00, /* 000011110000 */ + 0x0400, /* 000001000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0b00, /* 000010110000 */ + 0x0b00, /* 000010110000 */ + 0x1980, /* 000110011000 */ + 0x1180, /* 000100011000 */ + 0x3fc0, /* 001111111100 */ + 0x20c0, /* 001000001100 */ + 0x6060, /* 011000000110 */ + 0x4060, /* 010000000110 */ + 0xe0f0, /* 111000001111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 144 0x90 '.' */ + 0x0000, /* 000000000000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0800, /* 000010000000 */ + 0x7fe0, /* 011111111110 */ + 0x3020, /* 001100000010 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3080, /* 001100001000 */ + 0x3f80, /* 001111111000 */ + 0x3080, /* 001100001000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3020, /* 001100000010 */ + 0x3020, /* 001100000010 */ + 0x7fe0, /* 011111111110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 145 0x91 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3de0, /* 001111011110 */ + 0x6630, /* 011001100011 */ + 0x4630, /* 010001100011 */ + 0x0630, /* 000001100011 */ + 0x3ff0, /* 001111111111 */ + 0x6600, /* 011001100000 */ + 0xc600, /* 110001100000 */ + 0xc600, /* 110001100000 */ + 0xe730, /* 111001110011 */ + 0x7de0, /* 011111011110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 146 0x92 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x03f0, /* 000000111111 */ + 0x0710, /* 000001110001 */ + 0x0710, /* 000001110001 */ + 0x0b00, /* 000010110000 */ + 0x0b00, /* 000010110000 */ + 0x0b20, /* 000010110010 */ + 0x13e0, /* 000100111110 */ + 0x1320, /* 000100110010 */ + 0x3f00, /* 001111110000 */ + 0x2300, /* 001000110000 */ + 0x2300, /* 001000110000 */ + 0x4310, /* 010000110001 */ + 0x4310, /* 010000110001 */ + 0xe7f0, /* 111001111111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 147 0x93 '.' */ + 0x0000, /* 000000000000 */ + 0x0200, /* 000000100000 */ + 0x0700, /* 000001110000 */ + 0x0d80, /* 000011011000 */ + 0x18c0, /* 000110001100 */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x11c0, /* 000100011100 */ + 0x20e0, /* 001000001110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x7040, /* 011100000100 */ + 0x3880, /* 001110001000 */ + 0x1f00, /* 000111110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 148 0x94 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x11c0, /* 000100011100 */ + 0x20e0, /* 001000001110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x7040, /* 011100000100 */ + 0x3880, /* 001110001000 */ + 0x1f00, /* 000111110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 149 0x95 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0c00, /* 000011000000 */ + 0x0600, /* 000001100000 */ + 0x0300, /* 000000110000 */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x11c0, /* 000100011100 */ + 0x20e0, /* 001000001110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x7040, /* 011100000100 */ + 0x3880, /* 001110001000 */ + 0x1f00, /* 000111110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 150 0x96 '.' */ + 0x0000, /* 000000000000 */ + 0x0200, /* 000000100000 */ + 0x0700, /* 000001110000 */ + 0x0d80, /* 000011011000 */ + 0x18c0, /* 000110001100 */ + 0x0000, /* 000000000000 */ + 0x79e0, /* 011110011110 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x39c0, /* 001110011100 */ + 0x1e60, /* 000111100110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 151 0x97 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1800, /* 000110000000 */ + 0x0c00, /* 000011000000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x79e0, /* 011110011110 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x39c0, /* 001110011100 */ + 0x1e60, /* 000111100110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 152 0x98 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xf0f0, /* 111100001111 */ + 0x6020, /* 011000000010 */ + 0x3040, /* 001100000100 */ + 0x3040, /* 001100000100 */ + 0x1880, /* 000110001000 */ + 0x1880, /* 000110001000 */ + 0x0d00, /* 000011010000 */ + 0x0d00, /* 000011010000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0400, /* 000001000000 */ + 0x0c00, /* 000011000000 */ + 0x0800, /* 000010000000 */ + 0x7800, /* 011110000000 */ + 0x7000, /* 011100000000 */ + 0x0000, /* 000000000000 */ + + /* 153 0x99 '.' */ + 0x0000, /* 000000000000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x11c0, /* 000100011100 */ + 0x20c0, /* 001000001100 */ + 0x2060, /* 001000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x2040, /* 001000000100 */ + 0x3040, /* 001100000100 */ + 0x1880, /* 000110001000 */ + 0x0f00, /* 000011110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 154 0x9a '.' */ + 0x0000, /* 000000000000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0xe030, /* 111000000011 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x6020, /* 011000000010 */ + 0x7040, /* 011100000100 */ + 0x3fc0, /* 001111111100 */ + 0x1f80, /* 000111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 155 0x9b '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x1f80, /* 000111111000 */ + 0x36c0, /* 001101101100 */ + 0x26c0, /* 001001101100 */ + 0x6600, /* 011001100000 */ + 0x6600, /* 011001100000 */ + 0x6600, /* 011001100000 */ + 0x6600, /* 011001100000 */ + 0x7640, /* 011101100100 */ + 0x36c0, /* 001101101100 */ + 0x1f80, /* 000111111000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 156 0x9c '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x1cc0, /* 000111001100 */ + 0x18c0, /* 000110001100 */ + 0x1800, /* 000110000000 */ + 0x1800, /* 000110000000 */ + 0x1800, /* 000110000000 */ + 0x7e00, /* 011111100000 */ + 0x7e00, /* 011111100000 */ + 0x1800, /* 000110000000 */ + 0x1800, /* 000110000000 */ + 0x1800, /* 000110000000 */ + 0x1800, /* 000110000000 */ + 0x3e20, /* 001111100010 */ + 0x7fe0, /* 011111111110 */ + 0x61c0, /* 011000011100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 157 0x9d '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x30c0, /* 001100001100 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x0f00, /* 000011110000 */ + 0x0600, /* 000001100000 */ + 0x1f80, /* 000111111000 */ + 0x0600, /* 000001100000 */ + 0x1f80, /* 000111111000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 158 0x9e '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 159 0x9f '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 160 0xa0 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0180, /* 000000011000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x18c0, /* 000110001100 */ + 0x10c0, /* 000100001100 */ + 0x03c0, /* 000000111100 */ + 0x1cc0, /* 000111001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x39c0, /* 001110011100 */ + 0x1ee0, /* 000111101110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 161 0xa1 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0180, /* 000000011000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x1e00, /* 000111100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x1f80, /* 000111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 162 0xa2 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0180, /* 000000011000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0f80, /* 000011111000 */ + 0x11c0, /* 000100011100 */ + 0x20e0, /* 001000001110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x6060, /* 011000000110 */ + 0x7040, /* 011100000100 */ + 0x3880, /* 001110001000 */ + 0x1f00, /* 000111110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 163 0xa3 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0180, /* 000000011000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x79e0, /* 011110011110 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x39c0, /* 001110011100 */ + 0x1e60, /* 000111100110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 164 0xa4 '.' */ + 0x0000, /* 000000000000 */ + 0x1c40, /* 000111000100 */ + 0x3fc0, /* 001111111100 */ + 0x2380, /* 001000111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x2780, /* 001001111000 */ + 0x79c0, /* 011110011100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x79e0, /* 011110011110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 165 0xa5 '.' */ + 0x0000, /* 000000000000 */ + 0x1c40, /* 000111000100 */ + 0x3fc0, /* 001111111100 */ + 0x2380, /* 001000111000 */ + 0xc070, /* 110000000111 */ + 0x6020, /* 011000000010 */ + 0x7020, /* 011100000010 */ + 0x7820, /* 011110000010 */ + 0x5c20, /* 010111000010 */ + 0x4e20, /* 010011100010 */ + 0x4720, /* 010001110010 */ + 0x43a0, /* 010000111010 */ + 0x41e0, /* 010000011110 */ + 0x40e0, /* 010000001110 */ + 0x4060, /* 010000000110 */ + 0xe030, /* 111000000011 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 166 0xa6 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1f00, /* 000111110000 */ + 0x3180, /* 001100011000 */ + 0x0180, /* 000000011000 */ + 0x0780, /* 000001111000 */ + 0x1980, /* 000110011000 */ + 0x3180, /* 001100011000 */ + 0x3180, /* 001100011000 */ + 0x3380, /* 001100111000 */ + 0x1dc0, /* 000111011100 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 167 0xa7 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0700, /* 000001110000 */ + 0x1980, /* 000110011000 */ + 0x10c0, /* 000100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x3080, /* 001100001000 */ + 0x1980, /* 000110011000 */ + 0x0e00, /* 000011100000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 168 0xa8 '.' */ + 0x0000, /* 000000000000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0300, /* 000000110000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0c00, /* 000011000000 */ + 0x1800, /* 000110000000 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x3040, /* 001100000100 */ + 0x39c0, /* 001110011100 */ + 0x1f80, /* 000111111000 */ + 0x0f00, /* 000011110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 169 0xa9 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 170 0xaa '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x00c0, /* 000000001100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 171 0xab '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1000, /* 000100000000 */ + 0x3000, /* 001100000000 */ + 0x1000, /* 000100000000 */ + 0x1040, /* 000100000100 */ + 0x1080, /* 000100001000 */ + 0x1100, /* 000100010000 */ + 0x3a00, /* 001110100000 */ + 0x05c0, /* 000001011100 */ + 0x0a20, /* 000010100010 */ + 0x1020, /* 000100000010 */ + 0x20c0, /* 001000001100 */ + 0x4100, /* 010000010000 */ + 0x0200, /* 000000100000 */ + 0x03e0, /* 000000111110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 172 0xac '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x1000, /* 000100000000 */ + 0x3000, /* 001100000000 */ + 0x1000, /* 000100000000 */ + 0x1040, /* 000100000100 */ + 0x1080, /* 000100001000 */ + 0x1100, /* 000100010000 */ + 0x3a40, /* 001110100100 */ + 0x04c0, /* 000001001100 */ + 0x0940, /* 000010010100 */ + 0x1240, /* 000100100100 */ + 0x2440, /* 001001000100 */ + 0x47e0, /* 010001111110 */ + 0x0040, /* 000000000100 */ + 0x0040, /* 000000000100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 173 0xad '.' */ + 0x0000, /* 000000000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 174 0xae '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0660, /* 000001100110 */ + 0x0cc0, /* 000011001100 */ + 0x1980, /* 000110011000 */ + 0x3300, /* 001100110000 */ + 0x6600, /* 011001100000 */ + 0x3300, /* 001100110000 */ + 0x1980, /* 000110011000 */ + 0x0cc0, /* 000011001100 */ + 0x0660, /* 000001100110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 175 0xaf '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x6600, /* 011001100000 */ + 0x3300, /* 001100110000 */ + 0x1980, /* 000110011000 */ + 0x0cc0, /* 000011001100 */ + 0x0660, /* 000001100110 */ + 0x0cc0, /* 000011001100 */ + 0x1980, /* 000110011000 */ + 0x3300, /* 001100110000 */ + 0x6600, /* 011001100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 176 0xb0 '.' */ + 0x0c30, /* 000011000011 */ + 0x0820, /* 000010000010 */ + 0x6180, /* 011000011000 */ + 0x2080, /* 001000001000 */ + 0x0c30, /* 000011000011 */ + 0x0820, /* 000010000010 */ + 0x6180, /* 011000011000 */ + 0x2080, /* 001000001000 */ + 0x0c30, /* 000011000011 */ + 0x0820, /* 000010000010 */ + 0x6180, /* 011000011000 */ + 0x2080, /* 001000001000 */ + 0x0c30, /* 000011000011 */ + 0x0820, /* 000010000010 */ + 0x6180, /* 011000011000 */ + 0x2080, /* 001000001000 */ + 0x0c30, /* 000011000011 */ + 0x0820, /* 000010000010 */ + 0x6180, /* 011000011000 */ + 0x2080, /* 001000001000 */ + 0x0c30, /* 000011000011 */ + 0x0820, /* 000010000010 */ + + /* 177 0xb1 '.' */ + 0x7770, /* 011101110111 */ + 0x2220, /* 001000100010 */ + 0x8880, /* 100010001000 */ + 0xddd0, /* 110111011101 */ + 0x8880, /* 100010001000 */ + 0x2220, /* 001000100010 */ + 0x7770, /* 011101110111 */ + 0x2220, /* 001000100010 */ + 0x8880, /* 100010001000 */ + 0xddd0, /* 110111011101 */ + 0x8880, /* 100010001000 */ + 0x2220, /* 001000100010 */ + 0x7770, /* 011101110111 */ + 0x2220, /* 001000100010 */ + 0x8880, /* 100010001000 */ + 0xddd0, /* 110111011101 */ + 0x8880, /* 100010001000 */ + 0x2220, /* 001000100010 */ + 0x7770, /* 011101110111 */ + 0x2220, /* 001000100010 */ + 0x8880, /* 100010001000 */ + 0xddd0, /* 110111011101 */ + + /* 178 0xb2 '.' */ + 0xf3c0, /* 111100111100 */ + 0xf7d0, /* 111101111101 */ + 0x9e70, /* 100111100111 */ + 0xdf70, /* 110111110111 */ + 0xf3c0, /* 111100111100 */ + 0xf7d0, /* 111101111101 */ + 0x9e70, /* 100111100111 */ + 0xdf70, /* 110111110111 */ + 0xf3c0, /* 111100111100 */ + 0xf7d0, /* 111101111101 */ + 0x9e70, /* 100111100111 */ + 0xdf70, /* 110111110111 */ + 0xf3c0, /* 111100111100 */ + 0xf7d0, /* 111101111101 */ + 0x9e70, /* 100111100111 */ + 0xdf70, /* 110111110111 */ + 0xf3c0, /* 111100111100 */ + 0xf7d0, /* 111101111101 */ + 0x9e70, /* 100111100111 */ + 0xdf70, /* 110111110111 */ + 0xf3c0, /* 111100111100 */ + 0xf7d0, /* 111101111101 */ + + /* 179 0xb3 '.' */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + + /* 180 0xb4 '.' */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0xfe00, /* 111111100000 */ + 0xfe00, /* 111111100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + + /* 181 0xb5 '.' */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0xfe00, /* 111111100000 */ + 0xfe00, /* 111111100000 */ + 0x0600, /* 000001100000 */ + 0xfe00, /* 111111100000 */ + 0xfe00, /* 111111100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + + /* 182 0xb6 '.' */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0xfd80, /* 111111011000 */ + 0xfd80, /* 111111011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + + /* 183 0xb7 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xff80, /* 111111111000 */ + 0xff80, /* 111111111000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + + /* 184 0xb8 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xfe00, /* 111111100000 */ + 0xfe00, /* 111111100000 */ + 0x0600, /* 000001100000 */ + 0xfe00, /* 111111100000 */ + 0xfe00, /* 111111100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + + /* 185 0xb9 '.' */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0xfd80, /* 111111011000 */ + 0xfd80, /* 111111011000 */ + 0x0180, /* 000000011000 */ + 0xfd80, /* 111111011000 */ + 0xfd80, /* 111111011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + + /* 186 0xba '.' */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + + /* 187 0xbb '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xff80, /* 111111111000 */ + 0xff80, /* 111111111000 */ + 0x0180, /* 000000011000 */ + 0xfd80, /* 111111011000 */ + 0xfd80, /* 111111011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + + /* 188 0xbc '.' */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0xfd80, /* 111111011000 */ + 0xfd80, /* 111111011000 */ + 0x0180, /* 000000011000 */ + 0xff80, /* 111111111000 */ + 0xff80, /* 111111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 189 0xbd '.' */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0xff80, /* 111111111000 */ + 0xff80, /* 111111111000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 190 0xbe '.' */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0xfe00, /* 111111100000 */ + 0xfe00, /* 111111100000 */ + 0x0600, /* 000001100000 */ + 0xfe00, /* 111111100000 */ + 0xfe00, /* 111111100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 191 0xbf '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xfe00, /* 111111100000 */ + 0xfe00, /* 111111100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + + /* 192 0xc0 '.' */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x07f0, /* 000001111111 */ + 0x07f0, /* 000001111111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 193 0xc1 '.' */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 194 0xc2 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + + /* 195 0xc3 '.' */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x07f0, /* 000001111111 */ + 0x07f0, /* 000001111111 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + + /* 196 0xc4 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 197 0xc5 '.' */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + + /* 198 0xc6 '.' */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x07f0, /* 000001111111 */ + 0x07f0, /* 000001111111 */ + 0x0600, /* 000001100000 */ + 0x07f0, /* 000001111111 */ + 0x07f0, /* 000001111111 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + + /* 199 0xc7 '.' */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0df0, /* 000011011111 */ + 0x0df0, /* 000011011111 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + + /* 200 0xc8 '.' */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0df0, /* 000011011111 */ + 0x0df0, /* 000011011111 */ + 0x0c00, /* 000011000000 */ + 0x0ff0, /* 000011111111 */ + 0x0ff0, /* 000011111111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 201 0xc9 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0ff0, /* 000011111111 */ + 0x0ff0, /* 000011111111 */ + 0x0c00, /* 000011000000 */ + 0x0df0, /* 000011011111 */ + 0x0df0, /* 000011011111 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + + /* 202 0xca '.' */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0xfdf0, /* 111111011111 */ + 0xfdf0, /* 111111011111 */ + 0x0000, /* 000000000000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 203 0xcb '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0000, /* 000000000000 */ + 0xfdf0, /* 111111011111 */ + 0xfdf0, /* 111111011111 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + + /* 204 0xcc '.' */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0df0, /* 000011011111 */ + 0x0df0, /* 000011011111 */ + 0x0c00, /* 000011000000 */ + 0x0df0, /* 000011011111 */ + 0x0df0, /* 000011011111 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + + /* 205 0xcd '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0000, /* 000000000000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 206 0xce '.' */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0xfdf0, /* 111111011111 */ + 0xfdf0, /* 111111011111 */ + 0x0000, /* 000000000000 */ + 0xfdf0, /* 111111011111 */ + 0xfdf0, /* 111111011111 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + + /* 207 0xcf '.' */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0000, /* 000000000000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 208 0xd0 '.' */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 209 0xd1 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0000, /* 000000000000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + + /* 210 0xd2 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + + /* 211 0xd3 '.' */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0ff0, /* 000011111111 */ + 0x0ff0, /* 000011111111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 212 0xd4 '.' */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x07f0, /* 000001111111 */ + 0x07f0, /* 000001111111 */ + 0x0600, /* 000001100000 */ + 0x07f0, /* 000001111111 */ + 0x07f0, /* 000001111111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 213 0xd5 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x07f0, /* 000001111111 */ + 0x07f0, /* 000001111111 */ + 0x0600, /* 000001100000 */ + 0x07f0, /* 000001111111 */ + 0x07f0, /* 000001111111 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + + /* 214 0xd6 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0ff0, /* 000011111111 */ + 0x0ff0, /* 000011111111 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + + /* 215 0xd7 '.' */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + 0x0d80, /* 000011011000 */ + + /* 216 0xd8 '.' */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0600, /* 000001100000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + + /* 217 0xd9 '.' */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0xfe00, /* 111111100000 */ + 0xfe00, /* 111111100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 218 0xda '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x07f0, /* 000001111111 */ + 0x07f0, /* 000001111111 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + + /* 219 0xdb '.' */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + + /* 220 0xdc '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + + /* 221 0xdd '.' */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + 0xfc00, /* 111111000000 */ + + /* 222 0xde '.' */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + 0x03f0, /* 000000111111 */ + + /* 223 0xdf '.' */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0xfff0, /* 111111111111 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 224 0xe0 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 225 0xe1 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0f00, /* 000011110000 */ + 0x1980, /* 000110011000 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x3180, /* 001100011000 */ + 0x3780, /* 001101111000 */ + 0x3180, /* 001100011000 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x3180, /* 001100011000 */ + 0x7700, /* 011101110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 226 0xe2 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 227 0xe3 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 228 0xe4 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 229 0xe5 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 230 0xe6 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x30c0, /* 001100001100 */ + 0x39c0, /* 001110011100 */ + 0x36e0, /* 001101101110 */ + 0x3000, /* 001100000000 */ + 0x3000, /* 001100000000 */ + 0x6000, /* 011000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 231 0xe7 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 232 0xe8 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 233 0xe9 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 234 0xea '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 235 0xeb '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 236 0xec '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 237 0xed '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 238 0xee '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 239 0xef '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 240 0xf0 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 241 0xf1 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x7fe0, /* 011111111110 */ + 0x7fe0, /* 011111111110 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x7fe0, /* 011111111110 */ + 0x7fe0, /* 011111111110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 242 0xf2 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 243 0xf3 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 244 0xf4 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 245 0xf5 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 246 0xf6 '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x7fe0, /* 011111111110 */ + 0x7fe0, /* 011111111110 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0600, /* 000001100000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 247 0xf7 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 248 0xf8 '.' */ + 0x0000, /* 000000000000 */ + 0x0f00, /* 000011110000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x1980, /* 000110011000 */ + 0x0f00, /* 000011110000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 249 0xf9 '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 250 0xfa '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0600, /* 000001100000 */ + 0x0f00, /* 000011110000 */ + 0x0f00, /* 000011110000 */ + 0x0600, /* 000001100000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 251 0xfb '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 252 0xfc '.' */ + /* FIXME */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 253 0xfd '.' */ + 0x0000, /* 000000000000 */ + 0x0f00, /* 000011110000 */ + 0x1f80, /* 000111111000 */ + 0x3180, /* 001100011000 */ + 0x2180, /* 001000011000 */ + 0x0300, /* 000000110000 */ + 0x0600, /* 000001100000 */ + 0x0c00, /* 000011000000 */ + 0x1840, /* 000110000100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 254 0xfe '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x3fc0, /* 001111111100 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + + /* 255 0xff '.' */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + 0x0000, /* 000000000000 */ + +}; + + +struct fbcon_font_desc font_sun_12x22 = { + SUN12x22_IDX, + "SUN12x22", + 12, + 22, + fontdata_sun12x22, +#ifdef __sparc__ + 5 +#else + -1 +#endif +}; diff --git a/drivers/video/font_sun8x16.c b/drivers/video/font_sun8x16.c new file mode 100644 index 000000000..8bf027807 --- /dev/null +++ b/drivers/video/font_sun8x16.c @@ -0,0 +1,275 @@ +#include "font.h" + +#define FONTDATAMAX 4096 + +static unsigned char fontdata_sun8x16[FONTDATAMAX] = { +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x6c,0xfe,0xfe,0xfe,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x18,0x3c,0x3c,0xe7,0xe7,0xe7,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x7e,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0xff,0xff,0xff,0xff, +/* */ 0x00,0x00,0x00,0x00,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0x00,0x00,0x00,0x00, +/* */ 0xff,0xff,0xff,0xff,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xff,0xff,0xff,0xff, +/* */ 0x00,0x00,0x1e,0x0e,0x1a,0x32,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x3c,0x66,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x3f,0x33,0x3f,0x30,0x30,0x30,0x30,0x70,0xf0,0xe0,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x7f,0x63,0x7f,0x63,0x63,0x63,0x63,0x67,0xe7,0xe6,0xc0,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x18,0x18,0xdb,0x3c,0xe7,0x3c,0xdb,0x18,0x18,0x00,0x00,0x00,0x00, +/* */ 0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfe,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00, +/* */ 0x00,0x02,0x06,0x0e,0x1e,0x3e,0xfe,0x3e,0x1e,0x0e,0x06,0x02,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x7f,0xdb,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x1b,0x1b,0x00,0x00,0x00,0x00, +/* */ 0x00,0x7c,0xc6,0x60,0x38,0x6c,0xc6,0xc6,0x6c,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfe,0xfe,0xfe,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0xfe,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xfe,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xfe,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7c,0x7c,0xfe,0xfe,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0xfe,0xfe,0x7c,0x7c,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*!*/ 0x00,0x00,0x18,0x3c,0x3c,0x3c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +/*"*/ 0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*#*/ 0x00,0x00,0x00,0x6c,0x6c,0xfe,0x6c,0x6c,0x6c,0xfe,0x6c,0x6c,0x00,0x00,0x00,0x00, +/*$*/ 0x18,0x18,0x7c,0xc6,0xc2,0xc0,0x7c,0x06,0x06,0x86,0xc6,0x7c,0x18,0x18,0x00,0x00, +/*%*/ 0x00,0x00,0x00,0x00,0xc2,0xc6,0x0c,0x18,0x30,0x60,0xc6,0x86,0x00,0x00,0x00,0x00, +/*&*/ 0x00,0x00,0x38,0x6c,0x6c,0x38,0x76,0xdc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +/*'*/ 0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*(*/ 0x00,0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00,0x00,0x00, +/*)*/ 0x00,0x00,0x30,0x18,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00,0x00, +/***/ 0x00,0x00,0x00,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x00,0x00,0x00, +/*+*/ 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +/*,*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00, +/*-*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*.*/ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x02,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00,0x00,0x00,0x00, +/*0*/ 0x00,0x00,0x7c,0xc6,0xc6,0xce,0xde,0xf6,0xe6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +/*1*/ 0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x00,0x00,0x00,0x00, +/*2*/ 0x00,0x00,0x7c,0xc6,0x06,0x0c,0x18,0x30,0x60,0xc0,0xc6,0xfe,0x00,0x00,0x00,0x00, +/*3*/ 0x00,0x00,0x7c,0xc6,0x06,0x06,0x3c,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, +/*4*/ 0x00,0x00,0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, +/*5*/ 0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xfc,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, +/*6*/ 0x00,0x00,0x38,0x60,0xc0,0xc0,0xfc,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +/*7*/ 0x00,0x00,0xfe,0xc6,0x06,0x06,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, +/*8*/ 0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +/*9*/ 0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7e,0x06,0x06,0x06,0x0c,0x78,0x00,0x00,0x00,0x00, +/*:*/ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, +/*;*/ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00, +/*<*/ 0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00, +/*=*/ 0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*>*/ 0x00,0x00,0x00,0x60,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x60,0x00,0x00,0x00,0x00, +/*?*/ 0x00,0x00,0x7c,0xc6,0xc6,0x0c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +/*@*/ 0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c,0x00,0x00,0x00,0x00, +/*A*/ 0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +/*B*/ 0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x66,0x66,0x66,0x66,0xfc,0x00,0x00,0x00,0x00, +/*C*/ 0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x00,0x00,0x00,0x00, +/*D*/ 0x00,0x00,0xf8,0x6c,0x66,0x66,0x66,0x66,0x66,0x66,0x6c,0xf8,0x00,0x00,0x00,0x00, +/*E*/ 0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, +/*F*/ 0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +/*G*/ 0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xde,0xc6,0xc6,0x66,0x3a,0x00,0x00,0x00,0x00, +/*H*/ 0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +/*I*/ 0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +/*J*/ 0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00, +/*K*/ 0x00,0x00,0xe6,0x66,0x66,0x6c,0x78,0x78,0x6c,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +/*L*/ 0x00,0x00,0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, +/*M*/ 0x00,0x00,0xc3,0xe7,0xff,0xff,0xdb,0xc3,0xc3,0xc3,0xc3,0xc3,0x00,0x00,0x00,0x00, +/*N*/ 0x00,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +/*O*/ 0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +/*P*/ 0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +/*Q*/ 0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x0c,0x0e,0x00,0x00, +/*R*/ 0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x6c,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +/*S*/ 0x00,0x00,0x7c,0xc6,0xc6,0x60,0x38,0x0c,0x06,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +/*T*/ 0x00,0x00,0xff,0xdb,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +/*U*/ 0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +/*V*/ 0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00, +/*W*/ 0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x66,0x00,0x00,0x00,0x00, +/*X*/ 0x00,0x00,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x3c,0x66,0xc3,0xc3,0x00,0x00,0x00,0x00, +/*Y*/ 0x00,0x00,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +/*Z*/ 0x00,0x00,0xff,0xc3,0x86,0x0c,0x18,0x30,0x60,0xc1,0xc3,0xff,0x00,0x00,0x00,0x00, +/*[*/ 0x00,0x00,0x3c,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3c,0x00,0x00,0x00,0x00, +/*\*/ 0x00,0x00,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x06,0x02,0x00,0x00,0x00,0x00, +/*]*/ 0x00,0x00,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00,0x00,0x00,0x00, +/*^*/ 0x10,0x38,0x6c,0xc6,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,0xff,0x00,0x00, +/*`*/ 0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/*a*/ 0x00,0x00,0x00,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +/*b*/ 0x00,0x00,0xe0,0x60,0x60,0x78,0x6c,0x66,0x66,0x66,0x66,0x7c,0x00,0x00,0x00,0x00, +/*c*/ 0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc0,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +/*d*/ 0x00,0x00,0x1c,0x0c,0x0c,0x3c,0x6c,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +/*e*/ 0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +/*f*/ 0x00,0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +/*g*/ 0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0xcc,0x78,0x00, +/*h*/ 0x00,0x00,0xe0,0x60,0x60,0x6c,0x76,0x66,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +/*i*/ 0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +/*j*/ 0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00, +/*k*/ 0x00,0x00,0xe0,0x60,0x60,0x66,0x6c,0x78,0x78,0x6c,0x66,0xe6,0x00,0x00,0x00,0x00, +/*l*/ 0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +/*m*/ 0x00,0x00,0x00,0x00,0x00,0xe6,0xff,0xdb,0xdb,0xdb,0xdb,0xdb,0x00,0x00,0x00,0x00, +/*n*/ 0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, +/*o*/ 0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +/*p*/ 0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00, +/*q*/ 0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x1e,0x00, +/*r*/ 0x00,0x00,0x00,0x00,0x00,0xdc,0x76,0x66,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +/*s*/ 0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,0x00, +/*t*/ 0x00,0x00,0x10,0x30,0x30,0xfc,0x30,0x30,0x30,0x30,0x36,0x1c,0x00,0x00,0x00,0x00, +/*u*/ 0x00,0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +/*v*/ 0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00, +/*w*/ 0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x00,0x00,0x00,0x00, +/*x*/ 0x00,0x00,0x00,0x00,0x00,0xc3,0x66,0x3c,0x18,0x3c,0x66,0xc3,0x00,0x00,0x00,0x00, +/*y*/ 0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00, +/*z*/ 0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, +/*{*/ 0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00, +/*|*/ 0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +/*}*/ 0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, +/*~*/ 0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x0c,0x06,0x7c,0x00,0x00, +/* */ 0x00,0x00,0xcc,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +/* */ 0x00,0x0c,0x18,0x30,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x10,0x38,0x6c,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0xcc,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +/* */ 0x00,0x60,0x30,0x18,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +/* */ 0x00,0x38,0x6c,0x38,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x3c,0x66,0x60,0x60,0x66,0x3c,0x0c,0x06,0x3c,0x00,0x00,0x00, +/* */ 0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x18,0x3c,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +/* */ 0x00,0xc6,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +/* */ 0x38,0x6c,0x38,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +/* */ 0x18,0x30,0x60,0x00,0xfe,0x66,0x60,0x7c,0x60,0x60,0x66,0xfe,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x6e,0x3b,0x1b,0x7e,0xd8,0xdc,0x77,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x3e,0x6c,0xcc,0xcc,0xfe,0xcc,0xcc,0xcc,0xcc,0xce,0x00,0x00,0x00,0x00, +/* */ 0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x30,0x78,0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +/* */ 0x00,0x60,0x30,0x18,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0xc6,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0x78,0x00, +/* */ 0x00,0xc6,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +/* */ 0x00,0xc6,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x18,0x18,0x7e,0xc3,0xc0,0xc0,0xc0,0xc3,0x7e,0x18,0x18,0x00,0x00,0x00,0x00, +/* */ 0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xe6,0xfc,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0xc3,0x66,0x3c,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +/* */ 0x00,0xfc,0x66,0x66,0x7c,0x62,0x66,0x6f,0x66,0x66,0x66,0xf3,0x00,0x00,0x00,0x00, +/* */ 0x00,0x0e,0x1b,0x18,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x18,0xd8,0x70,0x00,0x00, +/* */ 0x00,0x18,0x30,0x60,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +/* */ 0x00,0x0c,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x18,0x30,0x60,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x18,0x30,0x60,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x76,0xdc,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, +/* */ 0x76,0xdc,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +/* */ 0x00,0x3c,0x6c,0x6c,0x3e,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x38,0x6c,0x6c,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xc0,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x60,0xce,0x9b,0x06,0x0c,0x1f,0x00,0x00, +/* */ 0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x66,0xce,0x96,0x3e,0x06,0x06,0x00,0x00, +/* */ 0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3c,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x36,0x6c,0xd8,0x6c,0x36,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0xd8,0x6c,0x36,0x6c,0xd8,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, +/* */ 0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa, +/* */ 0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77, +/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +/* */ 0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +/* */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +/* */ 0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +/* */ 0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +/* */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +/* */ 0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +/* */ 0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +/* */ 0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +/* */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +/* */ 0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +/* */ 0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +/* */ 0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +/* */ 0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +/* */ 0x18,0x18,0x18,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +/* */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +/* */ 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +/* */ 0x18,0x18,0x18,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +/* */ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +/* */ 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, +/* */ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, +/* */ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0xd8,0xd8,0xd8,0xdc,0x76,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x78,0xcc,0xcc,0xcc,0xd8,0xcc,0xc6,0xc6,0xc6,0xcc,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0xfe,0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0xfe,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0xfe,0xc6,0x60,0x30,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x7e,0xd8,0xd8,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xc0,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x76,0xdc,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x7e,0x18,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0x6c,0x38,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x6c,0x6c,0x6c,0xee,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x1e,0x30,0x18,0x0c,0x3e,0x66,0x66,0x66,0x66,0x3c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x7e,0xdb,0xdb,0xdb,0x7e,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x03,0x06,0x7e,0xdb,0xdb,0xf3,0x7e,0x60,0xc0,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x1c,0x30,0x60,0x60,0x7c,0x60,0x60,0x60,0x30,0x1c,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0xff,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x00,0x7e,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x7e,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x0e,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +/* */ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7e,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x38,0x6c,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0xec,0x6c,0x6c,0x3c,0x1c,0x00,0x00,0x00,0x00, +/* */ 0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x70,0xd8,0x30,0x60,0xc8,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,0x00,0x00,0x00,0x00, +/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; + +struct fbcon_font_desc font_sun_8x16 = { + SUN8x16_IDX, + "SUN8x16", + 8, + 16, + fontdata_sun8x16, +#ifdef __sparc__ + 10 +#else + -1 +#endif +}; diff --git a/drivers/video/fonts.c b/drivers/video/fonts.c index 56a3a33b2..72f29410a 100644 --- a/drivers/video/fonts.c +++ b/drivers/video/fonts.c @@ -2,6 +2,7 @@ * linux/drivers/video/fonts.c -- `Soft' font definitions * * Created 1995 by Geert Uytterhoeven + * Rewritten 1998 by Martin Mares <mj@ucw.cz> * * 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 @@ -12,83 +13,66 @@ #include <linux/config.h> #include <linux/types.h> #include <linux/string.h> -#ifdef __mc68000__ +#if defined(__mc68000__) || defined(CONFIG_APUS) #include <asm/setup.h> #endif #include "font.h" +#define NO_FONTS - /* - * External Font Definitions - */ - -/* VGA8x8 */ -extern char fontname_8x8[]; -extern int fontwidth_8x8, fontheight_8x8; -extern u8 fontdata_8x8[]; - -/* VGA8x16 */ -extern char fontname_8x16[]; -extern int fontwidth_8x16, fontheight_8x16; -extern u8 fontdata_8x16[]; - -/* PEARL8x8 */ -extern char fontname_pearl8x8[]; -extern int fontwidth_pearl8x8, fontheight_pearl8x8; -extern u8 fontdata_pearl8x8[]; - -/* VGA6x11 */ -extern char fontname_6x11[]; -extern int fontwidth_6x11, fontheight_6x11; -extern u8 fontdata_6x11[]; - - - /* - * Font Descriptor Array - */ - -struct softfontdesc { - char *name; - int *width; - int *height; - 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 struct fbcon_font_desc *fbcon_fonts[] = { +#ifdef CONFIG_FONT_8x8 +#undef NO_FONTS + &font_vga_8x8, +#endif +#ifdef CONFIG_FONT_8x16 +#undef NO_FONTS + &font_vga_8x16, +#endif +#ifdef CONFIG_FONT_6x11 +#if defined(CONFIG_MAC) || defined(CONFIG_FB_SBUS) +#undef NO_FONTS +#endif + &font_vga_6x11, +#endif +#ifdef CONFIG_FONT_SUN8x16 +#undef NO_FONTS + &font_sun_8x16, +#endif +#ifdef CONFIG_FONT_SUN12x22 +#if defined(CONFIG_FB_SBUS) || defined(CONFIG_FBCON_CFB8) || defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || defined(CONFIG_FBCON_CFB32) +#undef NO_FONTS +#endif + &font_sun_12x22, +#endif +#ifdef CONFIG_FONT_ACORN_8x8 +#undef NO_FONTS + &font_acorn_8x8, +#endif +#ifdef CONFIG_FONT_PEARL_8x8 +#undef NO_FONTS + &font_pearl_8x8, +#endif }; -static unsigned int numsoftfonts = sizeof(softfonts)/sizeof(*softfonts); +#define num_fonts (sizeof(fbcon_fonts)/sizeof(*fbcon_fonts)) +#ifdef NO_FONTS +#error No fonts configured. +#endif /* * Find a font with a specific name */ -int findsoftfont(char *name, int *width, int *height, u8 *data[]) +struct fbcon_font_desc *fbcon_find_font(char *name) { unsigned int i; - for (i = 0; i < numsoftfonts; i++) - if (!strcmp(softfonts[i].name, name)) { - if (width) - *width = *softfonts[i].width; - if (height) - *height = *softfonts[i].height; - if (data) - *data = softfonts[i].data; - return(1); - } - return(0); + for (i = 0; i < num_fonts; i++) + if (!strcmp(fbcon_fonts[i]->name, name)) + return fbcon_fonts[i]; + return NULL; } @@ -96,36 +80,32 @@ int findsoftfont(char *name, int *width, int *height, u8 *data[]) * Get the default font for a specific screen size */ -void getdefaultfont(int xres, int yres, char *name[], int *width, int *height, - u8 *data[]) +struct fbcon_font_desc *fbcon_get_default_font(int xres, int yres) { - int i; - - if (yres < 400) { - i = VGA8x8_IDX; -#ifdef CONFIG_AMIGA - if (MACH_IS_AMIGA) - i = PEARL8x8_IDX; + int i, c, cc; + struct fbcon_font_desc *f, *g; + + g = NULL; + cc = -10000; + for(i=0; i<num_fonts; i++) { + f = fbcon_fonts[i]; + c = f->pref; +#ifdef __mc68000__ +#ifdef CONFIG_FONT_PEARL_8x8 + if (MACH_IS_AMIGA && f->idx == PEARL8x8_IDX) + c = 100; #endif - } 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 */ +#ifdef CONFIG_FONT_6x11 + if (MACH_IS_MAC && xres < 640 && f->idx == VGA6x11_IDX) + c = 100; #endif - if (xres < 640) - i = VGA6x11_IDX; - } #endif - - if (name) - *name = softfonts[i].name; - if (width) - *width = *softfonts[i].width; - if (height) - *height = *softfonts[i].height; - if (data) - *data = softfonts[i].data; + if ((yres < 400) == (f->height <= 8)) + c += 1000; + if (c > cc) { + cc = c; + g = f; + } + } + return g; } diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c index 56939ef61..81f7fb95e 100644 --- a/drivers/video/g364fb.c +++ b/drivers/video/g364fb.c @@ -1,4 +1,5 @@ -/* +/* $Id: g364fb.c,v 1.1 1998/08/19 21:56:39 ralf Exp $ + * * linux/drivers/video/g364fb.c -- Mips Magnum frame buffer device * * (C) 1998 Thomas Bogendoerfer diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c new file mode 100644 index 000000000..7a7bede02 --- /dev/null +++ b/drivers/video/hpfb.c @@ -0,0 +1,428 @@ +/* + * HP300 Topcat framebuffer support (derived from macfb of all things) + * Phil Blundell <philb@gnu.org> 1998 + * + * Should this be moved to drivers/dio/video/ ? -- Peter Maydell + * No! -- Jes + */ + +#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/init.h> +#include <linux/fb.h> +#include <linux/dio.h> +#include <asm/io.h> +#include <asm/blinken.h> +#include <asm/hwtest.h> + +#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 display disp; +static struct fb_info fb_info; + +unsigned long fb_start, fb_size = 1024*768, fb_line_length = 1024; +unsigned long fb_regs; +unsigned char fb_bitmask; + +#define TC_WEN 0x4088 +#define TC_REN 0x408c +#define TC_FBEN 0x4090 +#define TC_NBLANK 0x4080 + +/* blitter regs */ +#define BUSY 0x4044 +#define WMRR 0x40ef +#define SOURCE_X 0x40f2 +#define SOURCE_Y 0x40f6 +#define DEST_X 0x40fa +#define DEST_Y 0x40fe +#define WHEIGHT 0x4106 +#define WWIDTH 0x4102 +#define WMOVE 0x409c + +static struct fb_var_screeninfo hpfb_defined = { + 0,0,0,0, /* W,H, W, H (virtual) load xres,xres_virtual*/ + 0,0, /* virtual -> visible no offset */ + 0, /* depth -> load bits_per_pixel */ + 0, /* greyscale ? */ + {0,2,0}, /* R */ + {0,2,0}, /* G */ + {0,2,0}, /* B */ + {0,0,0}, /* transparency */ + 0, /* standard pixel format */ + FB_ACTIVATE_NOW, + 274,195, /* 14" monitor */ + FB_ACCEL_NONE, + 0L,0L,0L,0L,0L, + 0L,0L,0, /* No sync info */ + FB_VMODE_NONINTERLACED, + {0,0,0,0,0,0} +}; + +struct hpfb_par +{ +}; + +static int currcon = 0; +struct hpfb_par current_par; + +static void hpfb_encode_var(struct fb_var_screeninfo *var, + struct hpfb_par *par) +{ + int i=0; + var->xres=1024; + var->yres=768; + var->xres_virtual=1024; + var->yres_virtual=768; + var->xoffset=0; + var->yoffset=0; + var->bits_per_pixel = 1; + 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->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; +} + +static void hpfb_get_par(struct hpfb_par *par) +{ + *par=current_par; +} + +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 hpfb_par par; + + hpfb_get_par(&par); + hpfb_encode_var(var, &par); + return 0; +} + +static int hpfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + return 0; +} + +/* + * Set the palette. This may not work on all boards but only experimentation will tell. + * XXX Doesn't work at all. + */ + +static int hpfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + unsigned int i; + for (i = 0; i < cmap->len; i++) + { + while (readw(fb_regs + 0x6002) & 0x4) udelay(1); + writew(0, fb_regs + 0x60f0); + writew(cmap->start + i, fb_regs + 0x60b8); + writew(cmap->red[i], fb_regs + 0x60b2); + writew(cmap->green[i], fb_regs + 0x60b4); + writew(cmap->blue[i], fb_regs + 0x60b6); + writew(0xff, fb_regs + 0x60f0); + udelay(100); + } + writew(0xffff, fb_regs + 0x60ba); + return 0; +} + +static int hpfb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct hpfb_par par; + if(con==-1) + { + hpfb_get_par(&par); + hpfb_encode_var(var, &par); + } + else + *var=fb_display[con].var; + return 0; +} + +static int hpfb_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 void hpfb_encode_fix(struct fb_fix_screeninfo *fix, + struct hpfb_par *par) +{ + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + strcpy(fix->id, "HP300 Topcat"); + + /* + * X works, but screen wraps ... + */ + fix->smem_start=(char *)fb_start; + fix->smem_len=fb_size; + fix->type = FB_TYPE_PACKED_PIXELS; + fix->visual = FB_VISUAL_PSEUDOCOLOR; + fix->xpanstep=0; + fix->ypanstep=0; + fix->ywrapstep=0; + fix->line_length=fb_line_length; +} + +static int hpfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + struct hpfb_par par; + hpfb_get_par(&par); + hpfb_encode_fix(fix, &par); + return 0; +} + +static void topcat_blit(int x0, int y0, int x1, int y1, int w, int h) +{ + while (readb(fb_regs + BUSY) & fb_bitmask); + writeb(0x3, fb_regs + WMRR); + writew(x0, fb_regs + SOURCE_X); + writew(y0, fb_regs + SOURCE_Y); + writew(x1, fb_regs + DEST_X); + writew(y1, fb_regs + DEST_Y); + writew(h, fb_regs + WHEIGHT); + writew(w, fb_regs + WWIDTH); + writeb(fb_bitmask, fb_regs + WMOVE); +} + +static int hpfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info) +{ + return -EINVAL; +} + +static int hpfb_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 hpfb_blank(int blank, struct fb_info *info) +{ + /* Not supported */ +} + +static int hpfb_open(struct fb_info *info, int user) +{ + /* + * Nothing, only a usage count for the moment + */ + MOD_INC_USE_COUNT; + return(0); +} + +static void hpfb_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 */ + + hpfb_get_fix(&fix, con, 0); + + 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; + display->next_line = fix.line_length; + display->can_soft_blank = 0; + display->inverse = 0; + + display->dispsw = &fbcon_cfb8; +} + +static int hpfb_release(struct fb_info *info, int user) +{ + MOD_DEC_USE_COUNT; + return(0); +} + +static struct fb_ops hpfb_ops = { + hpfb_open, + hpfb_release, + hpfb_get_fix, + hpfb_get_var, + hpfb_set_var, + hpfb_get_cmap, + hpfb_set_cmap, + NULL, + hpfb_ioctl +}; + +#define TOPCAT_FBOMSB 0x5d +#define TOPCAT_FBOLSB 0x5f + +__initfunc(int hpfb_init_one(unsigned long base)) +{ + unsigned long fboff; + + fboff = (readb(base + TOPCAT_FBOMSB) << 8) + | readb(base + TOPCAT_FBOLSB); + + fb_start = 0xf0000000 | (readb(base + fboff) << 16); + fb_regs = base; + +#if 0 + /* This is the magic incantation NetBSD uses to make Catseye boards work. */ + writeb(0, base+0x4800); + writeb(0, base+0x4510); + writeb(0, base+0x4512); + writeb(0, base+0x4514); + writeb(0, base+0x4516); + writeb(0x90, base+0x4206); +#endif + + /* + * Fill in the available video resolution + */ + + hpfb_defined.xres = 1024; + hpfb_defined.yres = 768; + hpfb_defined.xres_virtual = 1024; + hpfb_defined.yres_virtual = 768; + hpfb_defined.bits_per_pixel = 8; + + /* + * Give the hardware a bit of a prod and work out how many bits per + * pixel are supported. + */ + + writeb(0xff, base + TC_WEN); + writeb(0xff, base + TC_FBEN); + writeb(0xff, fb_start); + fb_bitmask = readb(fb_start); + + /* + * Enable reading/writing of all the planes. + */ + writeb(fb_bitmask, base + TC_WEN); + writeb(fb_bitmask, base + TC_REN); + writeb(fb_bitmask, base + TC_FBEN); + writeb(0x1, base + TC_NBLANK); + + /* + * Let there be consoles.. + */ + strcpy(fb_info.modename, "Topcat"); + fb_info.changevar = NULL; + fb_info.node = -1; + fb_info.fbops = &hpfb_ops; + fb_info.disp = &disp; + fb_info.switch_con = &hpfb_switch; + fb_info.updatevar = &fb_update_var; + fb_info.blank = &hpfb_blank; + do_fb_set_var(&hpfb_defined, 1); + + hpfb_get_var(&disp.var, -1, &fb_info); + hpfb_set_disp(-1); + + if (register_framebuffer(&fb_info) < 0) + return 1; + + return 0; +} + +/* + * Check that the secondary ID indicates that we have some hope of working with this + * framebuffer. The catseye boards are pretty much like topcats and we can muddle through. + */ + +#define topcat_sid_ok(x) (((x) == DIO_ID2_LRCATSEYE) || ((x) == DIO_ID2_HRCCATSEYE) \ + || ((x) == DIO_ID2_HRMCATSEYE) || ((x) == DIO_ID2_TOPCAT)) + +/* + * Initialise the framebuffer + */ + +__initfunc(unsigned long hpfb_init(unsigned long mem_start)) +{ + unsigned int sid; + + /* Topcats can be on the internal IO bus or real DIO devices. + * The internal variant sits at 0xf0560000; it has primary + * and secondary ID registers just like the DIO version. + * So we merge the two detection routines. + * + * Perhaps this #define should be in a global header file: + * I believe it's common to all internal fbs, not just topcat. + */ +#define INTFBADDR 0xf0560000 + + if (hwreg_present((void *)INTFBADDR) && (DIO_ID(INTFBADDR) == DIO_ID_FBUFFER) + && topcat_sid_ok(sid = DIO_SECID(INTFBADDR))) + { + printk("Internal Topcat found (secondary id %02x)\n", sid); + hpfb_init_one(INTFBADDR); + } + else + { + int sc = dio_find(DIO_ID_FBUFFER); + if (sc) + { + unsigned long addr = (unsigned long)dio_scodetoviraddr(sc); + unsigned int sid = DIO_SECID(addr); + + if (topcat_sid_ok(sid)) + { + printk("Topcat found at DIO select code %02x " + "(secondary id %02x)\n", sc, sid); + hpfb_init_one(addr); + } + } + } + + return mem_start; +} + +__initfunc(void hpfb_setup(char *options, int *ints)) +{ +} diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index 43932a080..67d6e87b1 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c @@ -2,7 +2,6 @@ * 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> @@ -44,7 +43,7 @@ static struct fb_var_screeninfo macfb_defined={ 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 .. */ + 0, /* The only way to accelerate a mac is .. */ 0L,0L,0L,0L,0L, 0L,0L,0, /* No sync info */ FB_VMODE_NONINTERLACED, @@ -76,7 +75,7 @@ static unsigned long mac_videosize; * Open/Release the frame buffer device */ -static int macfb_open(struct fb_info *info) +static int macfb_open(struct fb_info *info, int user) { /* * Nothing, only a usage count for the moment @@ -85,7 +84,7 @@ static int macfb_open(struct fb_info *info) return(0); } -static int macfb_release(struct fb_info *info) +static int macfb_release(struct fb_info *info, int user) { MOD_DEC_USE_COUNT; return(0); @@ -94,7 +93,7 @@ static int macfb_release(struct fb_info *info) static void macfb_encode_var(struct fb_var_screeninfo *var, struct macfb_par *par) { - int i=0; + memset(var, 0, sizeof(struct fb_var_screeninfo)); var->xres=mac_xres; var->yres=mac_yres; var->xres_virtual=mac_vxres; @@ -110,7 +109,6 @@ static void macfb_encode_var(struct fb_var_screeninfo *var, var->activate=0; var->height= -1; var->width= -1; - var->accel=0; var->vmode=FB_VMODE_NONINTERLACED; var->pixclock=0; var->sync=0; @@ -120,8 +118,6 @@ static void macfb_encode_var(struct fb_var_screeninfo *var, 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; } @@ -155,8 +151,6 @@ 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"); @@ -210,7 +204,7 @@ static void macfb_set_disp(int con) macfb_get_fix(&fix, con, 0); - display->screen_base = (u_char *)(fix.smem_start+fix.smem_offset); + display->screen_base = fix.smem_start+fix.smem_offset; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; @@ -222,22 +216,22 @@ static void macfb_set_disp(int con) display->inverse = inverse; switch (mac_depth) { -#ifdef CONFIG_FBCON_MFB +#ifdef FBCON_HAS_MFB case 1: display->dispsw = &fbcon_mfb; break; #endif -#ifdef CONFIG_FBCON_CFB2 +#ifdef FBCON_HAS_CFB2 case 2: display->dispsw = &fbcon_cfb2; break; #endif -#ifdef CONFIG_FBCON_CFB4 +#ifdef FBCON_HAS_CFB4 case 4: display->dispsw = &fbcon_cfb4; break; #endif -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 case 8: display->dispsw = &fbcon_cfb8; break; @@ -323,14 +317,12 @@ static struct fb_ops macfb_ops = { 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'; @@ -372,7 +364,7 @@ static int nubus_video_card(struct nubus_device_specifier *ns, int slot, struct { if(nt->category==NUBUS_CAT_DISPLAY) return 0; - /* Claim all video cards. We dont yet do driver specifics tho. */ + /* Claim all video cards. We don't yet do driver specifics though. */ return -ENODEV; } @@ -381,13 +373,12 @@ static struct nubus_device_specifier nb_video={ NULL }; -__initfunc(unsigned long macfb_init(unsigned long mem_start)) +__initfunc(void macfb_init(void)) { /* nubus_remap the video .. */ - int err; if (!MACH_IS_MAC) - return mem_start; + return; mac_xres=mac_bi_data.dimensions&0xFFFF; mac_yres=(mac_bi_data.dimensions&0xFFFF0000)>>16; @@ -426,13 +417,6 @@ __initfunc(unsigned long macfb_init(unsigned long mem_start)) 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); @@ -442,10 +426,14 @@ __initfunc(unsigned long macfb_init(unsigned long mem_start)) register_nubus_device(&nb_video); + if (register_framebuffer(&fb_info) < 0) + { + mac_boom(6); + return; + } + 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 diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c new file mode 100644 index 000000000..57cf4877a --- /dev/null +++ b/drivers/video/macmodes.c @@ -0,0 +1,391 @@ +/* + * linux/drivers/video/macmodes.c -- Standard MacOS video modes + * + * Copyright (C) 1998 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/tty.h> +#include <linux/fb.h> +#include <linux/string.h> + +#include "macmodes.h" + +struct mac_mode { + int number; + u32 xres; + u32 yres; + u32 pixclock; + u32 left_margin; + u32 right_margin; + u32 upper_margin; + u32 lower_margin; + u32 hsync_len; + u32 vsync_len; + u32 sync; + u32 vmode; +}; + + + /* 512x384, 60Hz, Interlaced (NTSC) */ + +#if 0 +static const struct mac_mode mac_mode_1 = { + VMODE_512_384_60I, 512, 384, + pixclock, left, right, upper, lower, hslen, vslen, + sync, FB_VMODE_INTERLACED +}; +#endif + + /* 512x384, 60Hz, Non-Interlaced */ + +#if 0 +static const struct mac_mode mac_mode_2 = { + VMODE_512_384_60, 512, 384, + pixclock, left, right, upper, lower, hslen, vslen, + sync, FB_VMODE_NONINTERLACED +}; +#endif + + /* 640x480, 50Hz, Interlaced (PAL) */ + +#if 0 +static const struct mac_mode mac_mode_3 = { + VMODE_640_480_50I, 640, 480, + pixclock, left, right, upper, lower, hslen, vslen, + sync, FB_VMODE_INTERLACED +}; +#endif + + /* 640x480, 60Hz, Interlaced (NTSC) */ + +#if 0 +static const struct mac_mode mac_mode_4 = { + VMODE_640_480_60I, 640, 480, + pixclock, left, right, upper, lower, hslen, vslen, + sync, FB_VMODE_INTERLACED +}; +#endif + + /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ + +static const struct mac_mode mac_mode_5 = { + VMODE_640_480_60, 640, 480, + 39722, 32, 32, 33, 10, 96, 2, + 0, FB_VMODE_NONINTERLACED +}; + + /* 640x480, 67Hz, Non-Interlaced (30.0 MHz dotclock) */ + +static const struct mac_mode mac_mode_6 = { + VMODE_640_480_67, 640, 480, + 33334, 80, 80, 39, 3, 64, 3, + 0, FB_VMODE_NONINTERLACED +}; + + /* 640x870, 75Hz (portrait), Non-Interlaced */ + +#if 0 +static const struct mac_mode mac_mode_7 = { + VMODE_640_870_75P, 640, 870, + pixclock, left, right, upper, lower, hslen, vslen, + sync, FB_VMODE_NONINTERLACED +}; +#endif + + /* 768x576, 50Hz (PAL full frame), Interlaced */ + +#if 0 +static const struct mac_mode mac_mode_8 = { + VMODE_768_576_50I, 768, 576, + pixclock, left, right, upper, lower, hslen, vslen, + sync, FB_VMODE_INTERLACED +}; +#endif + + /* 800x600, 56 Hz, Non-Interlaced (36.00 MHz dotclock) */ + +static const struct mac_mode mac_mode_9 = { + VMODE_800_600_56, 800, 600, + 27778, 112, 40, 22, 1, 72, 2, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED +}; + + /* 800x600, 60 Hz, Non-Interlaced (40.00 MHz dotclock) */ + +static const struct mac_mode mac_mode_10 = { + VMODE_800_600_60, 800, 600, + 25000, 72, 56, 23, 1, 128, 4, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED +}; + + /* 800x600, 72 Hz, Non-Interlaced (50.00 MHz dotclock) */ + +static const struct mac_mode mac_mode_11 = { + VMODE_800_600_72, 800, 600, + 20000, 48, 72, 23, 37, 120, 6, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED +}; + + /* 800x600, 75 Hz, Non-Interlaced (49.50 MHz dotclock) */ + +static const struct mac_mode mac_mode_12 = { + VMODE_800_600_75, 800, 600, + 20203, 144, 32, 21, 1, 80, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED +}; + + /* 832x624, 75Hz, Non-Interlaced (57.6 MHz */ + +static const struct mac_mode mac_mode_13 = { + VMODE_832_624_75, 832, 624, + 17362, 208, 48, 39, 1, 64, 3, + 0, FB_VMODE_NONINTERLACED +}; + + /* 1024x768, 60 Hz, Non-Interlaced (65.00 MHz dotclock) */ + +static const struct mac_mode mac_mode_14 = { + VMODE_1024_768_60, 1024, 768, + 15385, 144, 40, 29, 3, 136, 6, + 0, FB_VMODE_NONINTERLACED +}; + + /* 1024x768, 72 Hz, Non-Interlaced (75.00 MHz dotclock) */ + +static const struct mac_mode mac_mode_15 = { + VMODE_1024_768_70, 1024, 768, + 13334, 128, 40, 29, 3, 136, 6, + 0, FB_VMODE_NONINTERLACED +}; + + /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */ + +static const struct mac_mode mac_mode_16 = { + VMODE_1024_768_75V, 1024, 768, + 12699, 176, 16, 28, 1, 96, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED +}; + + /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */ + +static const struct mac_mode mac_mode_17 = { + VMODE_1024_768_75, 1024, 768, + 12699, 160, 32, 28, 1, 96, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED +}; + + /* 1152x870, 75 Hz, Non-Interlaced (100.0 MHz dotclock) */ + +static const struct mac_mode mac_mode_18 = { + VMODE_1152_870_75, 1152, 870, + 10000, 128, 48, 39, 3, 128, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED +}; + + /* 1280x960, 75 Hz, Non-Interlaced (126.00 MHz dotclock) */ + +static const struct mac_mode mac_mode_19 = { + VMODE_1280_960_75, 1280, 960, + 7937, 224, 32, 36, 1, 144, 3, + 0, FB_VMODE_NONINTERLACED +}; + + /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */ + +static const struct mac_mode mac_mode_20 = { + VMODE_1280_1024_75, 1280, 1024, + 7408, 232, 64, 38, 1, 112, 3, + FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED +}; + + +static const struct mac_mode *mac_modes[20] = { + NULL, /* 512x384, 60Hz interlaced (NTSC) */ + NULL, /* 512x384, 60Hz */ + NULL, /* 640x480, 50Hz interlaced (PAL) */ + NULL, /* 640x480, 60Hz interlaced (NTSC) */ + &mac_mode_5, /* 640x480, 60Hz (VGA) */ + &mac_mode_6, /* 640x480, 67Hz */ + NULL, /* 640x870, 75Hz (portrait) */ + NULL, /* 768x576, 50Hz (PAL full frame) */ + &mac_mode_9, /* 800x600, 56Hz */ + &mac_mode_10, /* 800x600, 60Hz */ + &mac_mode_11, /* 800x600, 72Hz */ + &mac_mode_12, /* 800x600, 75Hz */ + &mac_mode_13, /* 832x624, 75Hz */ + &mac_mode_14, /* 1024x768, 60Hz */ + &mac_mode_15, /* 1024x768, 70Hz (or 72Hz?) */ + &mac_mode_16, /* 1024x768, 75Hz (VESA) */ + &mac_mode_17, /* 1024x768, 75Hz */ + &mac_mode_18, /* 1152x870, 75Hz */ + &mac_mode_19, /* 1280x960, 75Hz */ + &mac_mode_20, /* 1280x1024, 75Hz */ +}; + +static const struct mac_mode *mac_modes_inv[] = { + &mac_mode_6, /* 640x480, 67Hz */ + &mac_mode_5, /* 640x480, 60Hz (VGA) */ + &mac_mode_12, /* 800x600, 75Hz */ + &mac_mode_11, /* 800x600, 72Hz */ + &mac_mode_10, /* 800x600, 60Hz */ + &mac_mode_9, /* 800x600, 56Hz */ + &mac_mode_13, /* 832x624, 75Hz */ + &mac_mode_17, /* 1024x768, 75Hz */ + &mac_mode_16, /* 1024x768, 75Hz (VESA) */ + &mac_mode_15, /* 1024x768, 70Hz (or 72Hz?) */ + &mac_mode_14, /* 1024x768, 60Hz */ + &mac_mode_18, /* 1152x870, 75Hz */ + &mac_mode_19, /* 1280x960, 75Hz */ + &mac_mode_20, /* 1280x1024, 75Hz */ +}; + + +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" */ + { 0x73f, VMODE_640_480_67 }, /* no sense lines connected at all */ + { -1, VMODE_640_480_60 }, /* catch-all, must be last */ +}; + + + /* + * Convert a MacOS vmode/cmode pair to a frame buffer video mode structure + */ + +int mac_vmode_to_var(int vmode, int cmode, struct fb_var_screeninfo *var) +{ + const struct mac_mode *mode = NULL; + + if (vmode > 0 && vmode <= VMODE_MAX) + mode = mac_modes[vmode-1]; + + if (!mode) + return -EINVAL; + + memset(var, 0, sizeof(struct fb_var_screeninfo)); + switch (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; + break; + + case CMODE_16: + 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; + break; + + case CMODE_32: + 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; + + default: + return -EINVAL; + } + var->xres = mode->xres; + var->yres = mode->yres; + var->xres_virtual = mode->xres; + var->yres_virtual = mode->yres; + var->height = -1; + var->width = -1; + var->pixclock = mode->pixclock; + var->left_margin = mode->left_margin; + var->right_margin = mode->right_margin; + var->upper_margin = mode->upper_margin; + var->lower_margin = mode->lower_margin; + var->hsync_len = mode->hsync_len; + var->vsync_len = mode->vsync_len; + var->sync = mode->sync; + var->vmode = mode->vmode; + return 0; +} + + + /* + * Convert a frame buffer video mode structure to a MacOS vmode/cmode pair + */ + +int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode, + int *cmode) +{ + int i = 0; + + if (var->bits_per_pixel <= 8) + *cmode = CMODE_8; + else if (var->bits_per_pixel <= 16) + *cmode = CMODE_16; + else if (var->bits_per_pixel <= 32) + *cmode = CMODE_32; + else + return -EINVAL; + + for (i = 0; i < sizeof(mac_modes_inv)/sizeof(*mac_modes_inv); i++) { + const struct mac_mode *mode = mac_modes_inv[i]; + if (var->xres > mode->xres || var->yres > mode->yres) + continue; + if (var->xres_virtual > mode->xres || var->yres_virtual > mode->yres) + continue; + if (var->pixclock > mode->pixclock) + continue; + if (var->vmode != mode->vmode) + continue; + *vmode = mode->number; + return 0; + } + return -EINVAL; +} + + + /* + * Convert a Mac monitor sense number to a MacOS vmode number + */ + +int mac_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; +} diff --git a/drivers/video/macmodes.h b/drivers/video/macmodes.h new file mode 100644 index 000000000..e0e90c738 --- /dev/null +++ b/drivers/video/macmodes.h @@ -0,0 +1,60 @@ +/* + * linux/drivers/video/macmodes.h -- Standard MacOS video modes + * + * Copyright (C) 1998 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. + */ + + + /* + * Video mode values. + * These are supposed to be the same as the values that Apple uses in + * MacOS. + */ + +#define VMODE_NVRAM 0 +#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 + +#define CMODE_NVRAM -1 +#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 */ + + +extern int mac_vmode_to_var(int vmode, int cmode, + struct fb_var_screeninfo *var); +extern int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode, + int *cmode); +extern int mac_map_monitor_sense(int sense); + + + /* + * Addresses in NVRAM where video mode and pixel size are stored. + */ + +#define NV_VMODE 0x140f +#define NV_CMODE 0x1410 diff --git a/drivers/video/mdafb.c b/drivers/video/mdafb.c new file mode 100644 index 000000000..35190d580 --- /dev/null +++ b/drivers/video/mdafb.c @@ -0,0 +1,480 @@ +/* + * linux/drivers/video/mdafb.c -- MDA frame buffer device + * + * Adapted from vgafb, May 1998 by Andrew Apted + * + * This file is based on vgacon.c and vgafb.c. Read about their + * contributors there. + * + * 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. + */ + + +/* KNOWN PROBLEMS/TO DO ==================================================== * + * + * - detecting amount of memory is not yet implemented + * + * ========================================================================= */ + + +#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/ioport.h> +#include <linux/init.h> +#include <linux/console.h> +#include <linux/selection.h> + +#include <asm/io.h> +#include <asm/uaccess.h> + +#include "fbcon.h" +#include "fbcon-vga.h" + + +#ifdef __powerpc__ +#define VGA_OFFSET _ISA_MEM_BASE; +#else +#define VGA_OFFSET 0x0 +#endif + + +static int mda_font_height = 16; /* !!! */ + + +static int currcon = 0; +static struct display disp; +static struct fb_info fb_info; + +static struct fb_fix_screeninfo fb_fix = { { 0, } }; +static struct fb_var_screeninfo fb_var = { 0, }; + + +/* Description of the hardware situation */ +static unsigned char mda_video_type; +static unsigned long mda_video_mem_base; /* Base of video memory */ +static unsigned long mda_video_mem_len; /* End of video memory */ +static u16 mda_video_port_reg; /* Video register select port */ +static u16 mda_video_port_val; /* Video register value port */ +static unsigned long mda_video_num_columns; /* Number of text columns */ +static unsigned long mda_video_num_lines; /* Number of text lines */ + + + /* + * MDA screen access + */ + +static inline void mda_writew(u16 val, u16 *addr) +{ +#ifdef __powerpc__ + st_le16(addr, val); +#else + writew(val, (unsigned long)addr); +#endif /* !__powerpc__ */ +} + +static inline u16 mda_readw(u16 *addr) +{ +#ifdef __powerpc__ + return ld_le16(addr); +#else + return readw((unsigned long)addr); +#endif /* !__powerpc__ */ +} + + +static inline void write_mda(unsigned char reg, unsigned int val) +{ + unsigned long flags; + + save_flags(flags); cli(); + + outb(reg, mda_video_port_reg); + outb(val >> 8, mda_video_port_val); + outb(reg+1, mda_video_port_reg); + outb(val & 0xff, mda_video_port_val); + + restore_flags(flags); +} + +static inline void mda_set_origin(unsigned short location) +{ + write_mda(12, location >> 1); +} + +static inline void mda_set_cursor(int location) +{ + write_mda(14, location >> 1); +} + + + /* + * Move hardware mda cursor + */ + +void fbcon_mdafb_cursor(struct display *p, int mode, int x, int y) +{ + switch (mode) { + case CM_ERASE: + mda_set_cursor(mda_video_mem_len - 1); + break; + + case CM_MOVE: + case CM_DRAW: + mda_set_cursor(y*p->next_line + (x << 1)); + break; + } +} + + + /* + * Interface to the low level console driver + */ + +void mdafb_setup(char *options, int *ints); +static int mdafbcon_switch(int con, struct fb_info *info); +static int mdafbcon_updatevar(int con, struct fb_info *info); +static void mdafbcon_blank(int blank, struct fb_info *info); + + + /* + * Open/Release the frame buffer device + */ + +static int mdafb_open(struct fb_info *info, int user) +{ + MOD_INC_USE_COUNT; + return 0; +} + +static int mdafb_release(struct fb_info *info, int user) +{ + MOD_DEC_USE_COUNT; + return 0; +} + + + /* + * Get the Fixed Part of the Display + */ + +static int mdafb_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 mdafb_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 mdafb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct display *display; + + if (con >= 0) + display = &fb_display[con]; + else + display = &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 || + var->nonstd || !(var->accel_flags & FB_ACCELF_TEXT) || + (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) + return -EINVAL; + + memcpy(var, &fb_var, sizeof(fb_var)); + + if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { + display->var = *var; + mda_set_origin(var->yoffset/mda_font_height*fb_fix.line_length); + } + + return 0; +} + + + /* + * Pan or Wrap the Display + * + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag + */ + +static int mdafb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + if (var->xoffset || var->yoffset+var->yres > var->yres_virtual) + return -EINVAL; + + mda_set_origin(var->yoffset/mda_font_height*fb_fix.line_length); + return 0; +} + + + /* + * Get the Colormap + */ + +static int mdafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + /* MDA is simply black and white */ + + return 0; +} + + + /* + * Set the Colormap + */ + +static int mdafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + /* MDA is simply black and white */ + + return 0; +} + + +static int mdafb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info) +{ + return -EINVAL; +} + + /* + * Interface used by the world + */ + +static struct fb_ops mdafb_ops = { + mdafb_open, mdafb_release, mdafb_get_fix, mdafb_get_var, + mdafb_set_var, mdafb_get_cmap, mdafb_set_cmap, mdafb_pan_display, + mdafb_ioctl +}; + + /* + * MDA text console with hardware cursor + */ + +static struct display_switch fbcon_mdafb = { + fbcon_vga_setup, fbcon_vga_bmove, fbcon_vga_clear, fbcon_vga_putc, + fbcon_vga_putcs, fbcon_vga_revc, fbcon_mdafb_cursor, NULL, NULL, + FONTWIDTH(8) +}; + + + /* + * Initialisation + */ + +__initfunc(void mdafb_init(void)) +{ + u16 saved; + u16 *p; + + mda_video_num_lines = 25; + mda_video_num_columns = 80; + mda_video_type = VIDEO_TYPE_MDA; + mda_video_mem_base = 0xb0000 + VGA_OFFSET; + mda_video_mem_len = 0x01000; + mda_video_port_reg = 0x3b4; + mda_video_port_val = 0x3b5; + + strcpy(fb_fix.id, "MDA-Dual-Head"); + request_region(0x3b0, 12, "mda-2"); + request_region(0x3bf, 1, "mda-2"); + + /* + * Find out if there is a graphics card present. + * Are there smarter methods around? + */ + p = (u16 *)mda_video_mem_base; + saved = mda_readw(p); + mda_writew(0xAA55, p); + if (mda_readw(p) != 0xAA55) { + mda_writew(saved, p); + return; + } + mda_writew(0x55AA, p); + if (mda_readw(p) != 0x55AA) { + mda_writew(saved, p); + return; + } + mda_writew(saved, p); + + fb_fix.smem_start = (char *) mda_video_mem_base; + fb_fix.smem_len = mda_video_mem_len; + fb_fix.type = FB_TYPE_TEXT; + fb_fix.type_aux = FB_AUX_TEXT_MDA; + fb_fix.visual = FB_VISUAL_PSEUDOCOLOR; + fb_fix.ypanstep = mda_font_height; + fb_fix.xpanstep = 0; + fb_fix.ywrapstep = 0; + fb_fix.line_length = 2 * mda_video_num_columns; + fb_fix.mmio_start = NULL; + fb_fix.mmio_len = 0; + fb_fix.accel = FB_ACCEL_NONE; + + fb_var.xres = mda_video_num_columns*8; + fb_var.yres = mda_video_num_lines * mda_font_height; + fb_var.xres_virtual = fb_var.xres; + /* the cursor is put at the end of the video memory, hence the -2 */ + fb_var.yres_virtual = ((fb_fix.smem_len-2)/fb_fix.line_length)* + mda_font_height; + + fb_var.xoffset = fb_var.yoffset = 0; + fb_var.bits_per_pixel = 1; + fb_var.grayscale = 1; + fb_var.red.offset = 0; + fb_var.red.length = 0; + fb_var.red.msb_right = 0; + fb_var.green.offset = 0; + fb_var.green.length = 0; + fb_var.green.msb_right = 0; + fb_var.blue.offset = 0; + fb_var.blue.length = 0; + fb_var.blue.msb_right = 0; + fb_var.transp.offset = 0; + fb_var.transp.length = 0; + fb_var.transp.msb_right = 0; + fb_var.nonstd = 0; + fb_var.activate = 0; + fb_var.height = fb_var.width = -1; + fb_var.accel_flags = FB_ACCELF_TEXT; + fb_var.pixclock = 39722; /* 25.175 MHz */ + fb_var.left_margin = 40; + fb_var.right_margin = 24; + fb_var.upper_margin = 39; + fb_var.lower_margin = 9; + fb_var.hsync_len = 96; + fb_var.vsync_len = 2; + 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 = NULL; + disp.cmap.green = NULL; + disp.cmap.blue = NULL; + disp.cmap.transp = NULL; + +#ifdef __i386__ + disp.screen_base = ioremap((unsigned long) fb_fix.smem_start, + fb_fix.smem_len); +#else + disp.screen_base = bus_to_virt((unsigned long) fb_fix.smem_start); +#endif + disp.visual = fb_fix.visual; + disp.type = fb_fix.type; + disp.type_aux = fb_fix.type_aux; + disp.ypanstep = fb_fix.ypanstep; + disp.ywrapstep = fb_fix.ywrapstep; + disp.line_length = fb_fix.line_length; + disp.can_soft_blank = 1; + disp.inverse = 0; + disp.dispsw = &fbcon_mdafb; + + strcpy(fb_info.modename, fb_fix.id); + fb_info.node = -1; + fb_info.fbops = &mdafb_ops; + fb_info.disp = &disp; + fb_info.fontname[0] = '\0'; + fb_info.changevar = NULL; + fb_info.switch_con = &mdafbcon_switch; + fb_info.updatevar = &mdafbcon_updatevar; + fb_info.blank = &mdafbcon_blank; + + mdafb_set_var(&fb_var, -1, &fb_info); + + if (register_framebuffer(&fb_info) < 0) + return; + + printk("fb%d: MDA frame buffer device, using %dK of video memory\n", + GET_FB_IDX(fb_info.node), fb_fix.smem_len>>10); +} + +__initfunc(void mdafb_setup(char *options, int *ints)) +{ + /* nothing yet */ +} + + /* + * Update the `var' structure (called by fbcon.c) + */ + +static int mdafbcon_updatevar(int con, struct fb_info *info) +{ + if (con == currcon) { + struct fb_var_screeninfo *var = &fb_display[currcon].var; + + /* hardware scrolling */ + + mda_set_origin(var->yoffset / mda_font_height * + fb_fix.line_length); + } + + return 0; +} + +static int mdafbcon_switch(int con, struct fb_info *info) +{ + currcon = con; + mdafbcon_updatevar(con, info); + return 0; +} + + /* + * Blank the display. + */ + +static void mdafbcon_blank(int blank, struct fb_info *info) +{ + if (blank) { + outb_p(0x00, 0x3b8); /* disable video */ + } else { + outb_p(0x08, 0x3b8); /* enable video */ + } +} + + +#ifdef MODULE +int init_module(void) +{ + mdafb_init(); + return 0; +} + +void cleanup_module(void) +{ + unregister_framebuffer(&fb_info); +} +#endif /* MODULE */ diff --git a/drivers/video/newport_con.c b/drivers/video/newport_con.c index c44526641..7532b0cdf 100644 --- a/drivers/video/newport_con.c +++ b/drivers/video/newport_con.c @@ -1,4 +1,5 @@ -/* +/* $Id: newport_con.c,v 1.1 1998/08/19 21:56:41 ralf Exp $ + * * newport_con.c: Abscon for newport hardware * * (C) 1998 Thomas Bogendoerfer (tsbogend@alpha.franken.de) @@ -23,8 +24,7 @@ #include <asm/system.h> #include <asm/page.h> #include <asm/pgtable.h> - -#include "newport.h" +#include <asm/newport.h> struct newport_regs *npregs; int newport_num_lines; diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 26ab95dfb..0e6e57f56 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -27,12 +27,14 @@ #include <linux/selection.h> #include <linux/init.h> #ifdef CONFIG_FB_COMPAT_XPMAC -#include <linux/vc_ioctl.h> +#include <asm/vc_ioctl.h> #endif #include <asm/io.h> #include <asm/prom.h> +#include "fbcon.h" #include "fbcon-cfb8.h" +#include "macmodes.h" static int currcon = 0; @@ -47,8 +49,6 @@ struct fb_info_offb { volatile unsigned char *cmap_data; }; -static struct fb_info_offb fb_info[FB_MAX]; - #ifdef __powerpc__ #define mach_eieio() eieio() #else @@ -62,11 +62,11 @@ static int ofonly = 0; * Interface used by the world */ -unsigned long offb_init(unsigned long mem_start); +void offb_init(void); 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_open(struct fb_info *info, int user); +static int offb_release(struct fb_info *info, int user); 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, @@ -85,11 +85,9 @@ static int offb_ioctl(struct inode *inode, struct file *file, u_int cmd, #ifdef CONFIG_FB_COMPAT_XPMAC int console_getmode(struct vc_mode *); int console_setmode(struct vc_mode *, int); +int console_setcmap(int, unsigned char *, unsigned char *, unsigned char *); 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 */ @@ -116,7 +114,7 @@ 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, NULL, offb_ioctl + offb_get_cmap, offb_set_cmap, offb_pan_display, offb_ioctl }; @@ -124,7 +122,7 @@ static struct fb_ops offb_ops = { * Open/Release the frame buffer device */ -static int offb_open(struct fb_info *info) +static int offb_open(struct fb_info *info, int user) { /* * Nothing, only a usage count for the moment @@ -134,7 +132,7 @@ static int offb_open(struct fb_info *info) return(0); } -static int offb_release(struct fb_info *info) +static int offb_release(struct fb_info *info, int user) { MOD_DEC_USE_COUNT; return(0); @@ -276,25 +274,30 @@ static int offb_ioctl(struct inode *inode, struct file *file, u_int cmd, #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" -}; +extern void atyfb_of_init(struct device_node *dp); #endif /* CONFIG_FB_ATY */ +#ifdef CONFIG_FB_S3TRIO +extern void s3triofb_init_of(struct device_node *dp); +#endif /* CONFIG_FB_S3TRIO */ +#ifdef CONFIG_FB_CT65550 +extern void chips_of_init(struct device_node *dp); +#endif /* CONFIG_FB_CT65550 */ +#ifdef CONFIG_FB_CONTROL +extern void control_of_init(struct device_node *dp); +#endif /* CONFIG_FB_CONTROL */ +#ifdef CONFIG_FB_PLATINUM +extern void platinum_of_init(struct device_node *dp); +#endif /* CONFIG_FB_PLATINUM */ /* * Initialisation */ -__initfunc(unsigned long offb_init(unsigned long mem_start)) +__initfunc(void offb_init(void)) { struct device_node *dp; - int dpy, i, err, *pp, len; + int dpy, i, *pp, len; unsigned *up, address; struct fb_fix_screeninfo *fix; struct fb_var_screeninfo *var; @@ -305,23 +308,43 @@ __initfunc(unsigned long offb_init(unsigned long mem_start)) 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); + if (!strncmp(dp->name, "ATY", 3)) { + atyfb_of_init(dp); continue; } #endif /* CONFIG_FB_ATY */ +#ifdef CONFIG_FB_S3TRIO + if (s3triofb_init_of(dp)) + continue; +#endif /* CONFIG_FB_S3TRIO */ +#ifdef CONFIG_FB_CT65550 + if (!strcmp(dp->name, "chips65550")) { + chips_of_init(dp); + continue; + } +#endif /* CONFIG_FB_CT65550 */ +#ifdef CONFIG_FB_CONTROL + if(!strcmp(dp->name, "control")) { + control_of_init(dp); + continue; + } +#endif /* CONFIG_FB_CONTROL */ +#ifdef CONFIG_FB_PLATINUM + if (!strncmp(dp->name, "platinum",8)) { + printk("jonh: offb_init sees device node %s\n", dp->name); + platinum_of_init(dp); + continue; + } +#endif /* CONFIG_FB_PLATINUM */ } + info = kmalloc(sizeof(struct fb_info_offb), GFP_ATOMIC); + fix = &info->fix; + var = &info->var; + disp = &info->disp; + strcpy(fix->id, "OFfb "); strncat(fix->id, dp->name, sizeof(fix->id)); fix->id[sizeof(fix->id)-1] = '\0'; @@ -329,6 +352,7 @@ __initfunc(unsigned long offb_init(unsigned long 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); + kfree(info); continue; } if ((pp = (int *)get_property(dp, "width", &len)) != NULL @@ -352,11 +376,12 @@ __initfunc(unsigned long offb_init(unsigned long mem_start)) break; if (i >= dp->n_addrs) { printk("no framebuffer address found for %s\n", dp->full_name); + kfree(info); continue; } address = (u_long)dp->addrs[i].address; } - fix->smem_start = ioremap(address, fix->smem_len); + fix->smem_start = (char *)address; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; @@ -379,7 +404,6 @@ __initfunc(unsigned long offb_init(unsigned long mem_start)) 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; @@ -390,8 +414,11 @@ __initfunc(unsigned long offb_init(unsigned long mem_start)) 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->cmap.red = NULL; + disp->cmap.green = NULL; + disp->cmap.blue = NULL; + disp->cmap.transp = NULL; + disp->screen_base = ioremap(address, fix->smem_len); disp->visual = fix->visual; disp->type = fix->type; disp->type_aux = fix->type_aux; @@ -400,11 +427,12 @@ __initfunc(unsigned long offb_init(unsigned long mem_start)) disp->line_length = fix->line_length; disp->can_soft_blank = info->cmap_adr ? 1 : 0; disp->inverse = 0; -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 disp->dispsw = &fbcon_cfb8; #else disp->dispsw = NULL; #endif + disp->scrollmode = SCROLL_YREDRAW; strcpy(info->info.modename, "OFfb "); strncat(info->info.modename, dp->full_name, @@ -418,10 +446,6 @@ __initfunc(unsigned long offb_init(unsigned long mem_start)) 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]; @@ -430,6 +454,11 @@ __initfunc(unsigned long offb_init(unsigned long mem_start)) } offb_set_var(var, -1, &info->info); + if (register_framebuffer(&info->info) < 0) { + kfree(info); + return; + } + printk("fb%d: Open Firmware frame buffer device on %s\n", GET_FB_IDX(info->info.node), dp->full_name); @@ -441,22 +470,20 @@ __initfunc(unsigned long offb_init(unsigned long mem_start)) 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.fb_address = address; 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); + display_info.disp_reg_address = address + 0x7ffc00; + display_info.cmap_adr_address = address + 0x7ffcc0; + display_info.cmap_data_address = address + 0x7ffcc1; } console_fb_info = &info->info; - console_set_cmap_ptr = offb_set_cmap; } #endif /* CONFIG_FB_COMPAT_XPMAC) */ } - return mem_start; } @@ -587,16 +614,6 @@ static void do_install_cmap(int con, struct fb_info *info) /* * 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) @@ -607,12 +624,31 @@ int console_getmode(struct vc_mode *mode) int console_setmode(struct vc_mode *mode, int doit) { - int err; - - if (console_setmode_ptr == NULL) - return -EINVAL; + struct fb_var_screeninfo var; + int cmode, err; - err = (*console_setmode_ptr)(mode, doit); + if (!console_fb_info) + return -EOPNOTSUPP; + switch (mode->depth) { + case 8: + case 0: /* default */ + cmode = 0; /* CMODE_8 */ + break; + case 16: + cmode = 1; /* CMODE_16 */ + break; + case 24: + case 32: + cmode = 2; /* CMODE_32 */ + break; + default: + return -EINVAL; + } + if ((err = mac_vmode_to_var(mode->mode, cmode, &var))) + return err; + var.activate = doit ? FB_ACTIVATE_NOW : FB_ACTIVATE_TEST; + err = console_fb_info->fbops->fb_set_var(&var, fg_console, + console_fb_info); return err; } @@ -627,9 +663,9 @@ static struct fb_cmap palette_cmap = { int console_setcmap(int n_entries, unsigned char *red, unsigned char *green, unsigned char *blue) { - int i, j, n; + int i, j, n, err; - if (console_set_cmap_ptr == NULL) + if (!console_fb_info) return -EOPNOTSUPP; for (i = 0; i < n_entries; i += n) { n = n_entries-i; @@ -642,7 +678,10 @@ int console_setcmap(int n_entries, unsigned char *red, unsigned char *green, 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); + err = console_fb_info->fbops->fb_set_cmap(&palette_cmap, 1, fg_console, + console_fb_info); + if (err) + return err; } return 0; } diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c new file mode 100644 index 000000000..f2a3e9410 --- /dev/null +++ b/drivers/video/platinumfb.c @@ -0,0 +1,1052 @@ +/* + * platinumfb.c -- frame buffer device for the PowerMac 'platinum' display + * + * Created 12 July 1998 by Dan Jacobowitz <dan@debian.org> + * Copyright (C) 1998 Dan Jacobowitz + * + * Frame buffer structure from: + * drivers/video/chipsfb.c -- frame buffer device for + * Chips & Technologies 65550 chip. + * + * Copyright (C) 1998 Paul Mackerras + * + * This file is derived from the Powermac "chips" driver: + * Copyright (C) 1997 Fabio Riccardi. + * And from the frame buffer device for Open Firmware-initialized devices: + * Copyright (C) 1997 Geert Uytterhoeven. + * + * Hardware information from: + * platinum.c: Console support for PowerMac "platinum" display adaptor. + * Copyright (C) 1996 Paul Mackerras + * + * 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> +#ifdef CONFIG_FB_COMPAT_XPMAC +#include <asm/vc_ioctl.h> +#endif +#include <asm/io.h> +#include <asm/prom.h> +#include <asm/pgtable.h> +#include <asm/adb.h> +#include <asm/cuda.h> + +#include "fbcon.h" +#include "fbcon-cfb8.h" +#include "fbcon-cfb16.h" +#include "fbcon-cfb32.h" + +#include "macmodes.h" +#include "platinumfb.h" + +static int currcon = 0; +static int switching = 0; + +struct fb_par_platinum { + int vmode, cmode; + int xres, yres; + int vxres, vyres; + int xoffset, yoffset; +}; + +struct fb_info_platinum { + struct fb_info info; + struct fb_fix_screeninfo fix; + struct fb_var_screeninfo var; + struct display disp; + struct fb_par_platinum par; + struct { + __u8 red, green, blue; + } palette[256]; + + volatile struct cmap_regs *cmap_regs; + unsigned long cmap_regs_phys; + + volatile struct platinum_regs *platinum_regs; + unsigned long platinum_regs_phys; + + __u8 *frame_buffer; + __u8 *base_frame_buffer; + unsigned long frame_buffer_phys; + + int sense; + unsigned long total_vram; +}; + +/* + * Exported functions + */ +void platinum_init(void); +void platinum_of_init(struct device_node *dp); + +static int platinum_open(struct fb_info *info, int user); +static int platinum_release(struct fb_info *info, int user); +static int platinum_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int platinum_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int platinum_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int platinum_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int platinum_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int platinum_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int platinum_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info); + +static int read_platinum_sense(struct fb_info_platinum *p); +static inline int platinum_vram_reqd(int video_mode, int color_mode); +static void set_platinum_clock(struct fb_info_platinum *p, unsigned char *params); +static void platinum_set_hardware(struct fb_info_platinum *p); +static void platinum_par_to_all(struct fb_info_platinum *p, int init); +static inline void platinum_par_to_var(struct fb_par_platinum *par, struct fb_var_screeninfo *var); +static int platinum_var_to_par(struct fb_var_screeninfo *var, + struct fb_par_platinum *par, const struct fb_info *fb_info); + +static void platinum_init_info(struct fb_info *info, struct fb_info_platinum *p); +static void platinum_par_to_display(struct fb_par_platinum *par, + struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_platinum *p); +static void platinum_init_display(struct display *disp); +static void platinum_par_to_fix(struct fb_par_platinum *par, struct fb_fix_screeninfo *fix, + struct fb_info_platinum *p); +static void platinum_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_platinum *p); + +static struct fb_ops platinumfb_ops = { + platinum_open, + platinum_release, + platinum_get_fix, + platinum_get_var, + platinum_set_var, + platinum_get_cmap, + platinum_set_cmap, + platinum_pan_display, + platinum_ioctl +}; + +static int platinum_getcolreg(u_int regno, u_int *red, u_int *green, + u_int *blue, u_int *transp, struct fb_info *info); +static int platinum_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); + +#define FUNCID { printk(KERN_INFO "entering %s\n", __FUNCTION__); } + +__openfirmware + + +static int platinum_open(struct fb_info *info, int user) +{ + MOD_INC_USE_COUNT; + return 0; +} + +static int platinum_release(struct fb_info *info, int user) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +static int platinum_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + struct fb_info_platinum *cp = (struct fb_info_platinum *) info; + + *fix = cp->fix; + return 0; +} + +static int platinum_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct fb_info_platinum *cp = (struct fb_info_platinum *) info; + + *var = cp->var; + return 0; +} + +/* Sets everything according to var */ +static int platinum_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct fb_info_platinum *p = (struct fb_info_platinum *) info; + struct display *disp; + struct fb_par_platinum par; + int depthchange, err; + +// FUNCID; + disp = (con >= 0) ? &fb_display[con] : &p->disp; + if((err = platinum_var_to_par(var, &par, info))) { + printk (KERN_ERR "Error in platinum_set_var, calling platinum_var_to_par: %d.\n", err); + return err; + } + + if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) { + printk("Not activating, in platinum_set_var.\n"); + platinum_par_to_var(&par, var); + return 0; + } +/* I know, we want to use fb_display[con], but grab certain info from p->var instead. */ +#define DIRTY(x) (p->var.x != var->x) + depthchange = DIRTY(bits_per_pixel); + if(!DIRTY(xres) && !DIRTY(yres) && !DIRTY(xres_virtual) && + !DIRTY(yres_virtual) && !DIRTY(bits_per_pixel)) { + platinum_par_to_var(&par, var); + p->var = disp->var = *var; + return 0; + } + printk("Original bpp is %d, new bpp %d.\n", p->var.bits_per_pixel, var->bits_per_pixel); + /* OK, we're getting here at the right times... */ + p->par = par; + platinum_par_to_var(&par, var); + p->var = *var; + platinum_par_to_fix(&par, &p->fix, p); + platinum_par_to_display(&par, disp, &p->fix, p); + p->disp = *disp; + + if(info->changevar && !switching) /* Don't want to do this if just switching consoles. */ + (*info->changevar)(con); + if(con == currcon) + platinum_set_hardware(p); + if(depthchange) + if((err = fb_alloc_cmap(&disp->cmap, 0, 0))) + return err; + if(depthchange || switching) + do_install_cmap(con, info); + return 0; +} + +static int platinum_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *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. + */ + +// FUNCID; + if (var->xoffset != 0 || var->yoffset != 0) + return -EINVAL; + return 0; +} + +static int platinum_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ +// FUNCID; + if (con == currcon) /* current console? */ + return fb_get_cmap(cmap, &fb_display[con].var, kspc, + platinum_getcolreg, info); + if (fb_display[con].cmap.len) /* non default colormap? */ + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc? 0: 2); + else { + int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; + fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2); + } + return 0; +} + +static int platinum_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + struct display *disp = &fb_display[con]; + int err; + +// FUNCID; + if (disp->cmap.len == 0) { + int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; + err = fb_alloc_cmap(&disp->cmap, size, 0); + if (err) + return err; + } + + if (con == currcon) + return fb_set_cmap(cmap, &disp->var, kspc, platinum_setcolreg, + info); + fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); + return 0; +} + +static int platinum_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info) +{ +// FUNCID; + return -EINVAL; +} + +static int platinum_switch(int con, struct fb_info *info) +{ +// FUNCID; + if (fb_display[currcon].cmap.len) + fb_get_cmap(&fb_display[currcon].cmap, + &fb_display[currcon].var, 1, platinum_getcolreg, + info); + currcon = con; +#if 0 + platinum_var_to_par(&fb_display[currcon].var, &par, info); + platinum_set_par(&par, info); /*STOPPEDHERE - did i define that? */ + do_install_cmap(con, info); +#else + /* I see no reason not to do this. Minus info->changevar(). */ + /* DOH. This makes platinum_set_var compare, you guessed it, */ + /* fb_display[con].var (first param), and fb_display[con].var! */ + /* Perhaps I just fixed that... */ + switching = 1; + platinum_set_var(&fb_display[con].var, con, info); + switching = 0; +#endif + return 0; +} + +static int platinum_updatevar(int con, struct fb_info *info) +{ + return 0; +} + +static void platinum_blank(int blank_mode, struct fb_info *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 + */ +/* [danj] I think there's something fishy about those constants... */ +/* + struct fb_info_platinum *p = (struct fb_info_platinum *) info; + int ctrl; + + ctrl = ld_le32(&p->platinum_regs->ctrl.r) | 0x33; + if (blank_mode) + --blank_mode; + if (blank_mode & VESA_VSYNC_SUSPEND) + ctrl &= ~3; + if (blank_mode & VESA_HSYNC_SUSPEND) + ctrl &= ~0x30; + out_le32(&p->platinum_regs->ctrl.r, ctrl); +*/ +/* TODO: Figure out how the heck to powerdown this thing! */ +//FUNCID; + return; +} + +static int platinum_getcolreg(u_int regno, u_int *red, u_int *green, + u_int *blue, u_int *transp, struct fb_info *info) +{ + struct fb_info_platinum *p = (struct fb_info_platinum *) info; + +// FUNCID; + if (regno > 255 || regno < 0) + return 1; + *red = p->palette[regno].red; + *green = p->palette[regno].green; + *blue = p->palette[regno].blue; + return 0; +} + +static int platinum_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + struct fb_info_platinum *p = (struct fb_info_platinum *) info; + +// FUNCID; + if (regno > 255 || regno < 0) + return 1; + p->palette[regno].red = red; + p->palette[regno].green = green; + p->palette[regno].blue = blue; + + out_8(&p->cmap_regs->addr, regno); /* tell clut what addr to fill */ + out_8(&p->cmap_regs->lut, red); /* send one color channel at */ + out_8(&p->cmap_regs->lut, green); /* a time... */ + out_8(&p->cmap_regs->lut, blue); + + if(regno < 16) { +#if 0 +#ifdef FBCON_HAS_CFB16 + fbcon_cfb16_cmap[regno] = (red << 10) | (green << 5) | blue; +#endif +#ifdef FBCON_HAS_CFB32 + fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue; + /* I think. */ +#endif +#else +#ifdef FBCON_HAS_CFB16 + fbcon_cfb16_cmap[regno] = (regno << 10) | (regno << 5) | regno; +#endif +#ifdef FBCON_HAS_CFB32 + fbcon_cfb32_cmap[regno] = (regno << 24) | (regno << 16) | (regno << 8) | regno; + /* I think. */ +#endif +#endif + } + return 0; +} + +static void do_install_cmap(int con, struct fb_info *info) +{ +// FUNCID; + if (con != currcon) + return; + if (fb_display[con].cmap.len) + fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1, + platinum_setcolreg, info); + else { + int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; + fb_set_cmap(fb_default_cmap(size), &fb_display[con].var, 1, + platinum_setcolreg, info); + } +} + +#ifdef CONFIG_FB_COMPAT_XPMAC +extern struct vc_mode display_info; +extern struct fb_info *console_fb_info; +#if 0 +extern int (*console_setmode_ptr)(struct vc_mode *, int); +extern int (*console_set_cmap_ptr)(struct fb_cmap *, int, int, + struct fb_info *); +int console_setmode(struct vc_mode *, int); +#endif +#endif /* CONFIG_FB_COMPAT_XPMAC */ + +static inline int platinum_vram_reqd(int video_mode, int color_mode) +{ + return vmode_attrs[video_mode - 1].vres + * platinum_reg_init[video_mode-1]->pitch[color_mode]; +} + +#define STORE_D2(a, d) { \ + out_8(&p->cmap_regs->addr, (a+32)); \ + out_8(&p->cmap_regs->d2, (d)); \ +} + +static void set_platinum_clock(struct fb_info_platinum *p, unsigned char *clock_params) +{ +// FUNCID; + STORE_D2(6, 0xc6); + out_8(&p->cmap_regs->addr,3+32); + if (in_8(&p->cmap_regs->d2) == 2) { + STORE_D2(7, clock_params[0]); + STORE_D2(8, clock_params[1]); + STORE_D2(3, 3); + } else { + STORE_D2(4, clock_params[0]); + STORE_D2(5, clock_params[1]); + STORE_D2(3, 2); + } + + __delay(5000); + STORE_D2(9, 0xa6); +} + + +__initfunc(static void init_platinum(struct fb_info_platinum *p)) +{ + struct fb_par_platinum *par = &p->par; + +// FUNCID; + p->sense = read_platinum_sense(p); + printk("Monitor sense value = 0x%x, ", p->sense); + /* Try to pick a video mode out of NVRAM if we have one. */ + par->vmode = nvram_read_byte(NV_VMODE); + if(par->vmode <= 0 || par->vmode > VMODE_MAX || !platinum_reg_init[par->vmode - 1]) + par->vmode = VMODE_CHOOSE; + if(par->vmode == VMODE_CHOOSE) + par->vmode = mac_map_monitor_sense(p->sense); + if(!platinum_reg_init[par->vmode - 1]) + par->vmode = VMODE_640_480_67; + + par->cmode = nvram_read_byte(NV_CMODE); + if(par->cmode < CMODE_8 || par->cmode > CMODE_32) + par->cmode = CMODE_8; + /* + * Reduce the pixel size if we don't have enough VRAM. + */ + while(par->cmode > CMODE_8 && platinum_vram_reqd(par->vmode, par->cmode) > p->total_vram) + par->cmode--; + + printk("using video mode %d and color mode %d.\n", par->vmode, par->cmode); + + par->vxres = par->xres = vmode_attrs[par->vmode - 1].hres; + par->vyres = par->yres = vmode_attrs[par->vmode - 1].vres; + par->xoffset = par->yoffset = 0; + + platinum_par_to_all(p, 1); + + if (register_framebuffer(&p->info) < 0) { + kfree(p); + return; + } + platinum_set_hardware(p); + + printk("fb%d: platinum display adapter\n", GET_FB_IDX(p->info.node)); +} + +/* Now how about actually saying, Make it so! */ +/* Some things in here probably don't need to be done each time. */ +static void platinum_set_hardware(struct fb_info_platinum *p) +{ + struct platinum_regvals *init; + int i, dtype, clkmode; + int vmode, cmode; + +// FUNCID; + vmode = p->par.vmode; + cmode = p->par.cmode; + + init = platinum_reg_init[vmode - 1]; + + /* Initialize display timing registers */ + out_be32(&p->platinum_regs->reg[24].r, 7); /* turn display off */ + + for (i = 0; i < 26; ++i) + out_be32(&p->platinum_regs->reg[i+32].r, init->regs[i]); + out_be32(&p->platinum_regs->reg[26+32].r, (p->total_vram == 0x100000 ? + init->offset[cmode] + 4 - cmode : + init->offset[cmode])); + out_be32(&p->platinum_regs->reg[16].r, (unsigned) p->frame_buffer_phys + init->fb_offset); + out_be32(&p->platinum_regs->reg[18].r, init->pitch[cmode]); + out_be32(&p->platinum_regs->reg[19].r, (p->total_vram == 0x100000 ? + init->mode[cmode+1] : + init->mode[cmode])); + out_be32(&p->platinum_regs->reg[20].r, (p->total_vram == 0x100000 ? 0x11 : 0x1011)); + out_be32(&p->platinum_regs->reg[21].r, 0x100); + out_be32(&p->platinum_regs->reg[22].r, 1); + out_be32(&p->platinum_regs->reg[23].r, 1); + out_be32(&p->platinum_regs->reg[26].r, 0xc00); + out_be32(&p->platinum_regs->reg[27].r, 0x235); + /* out_be32(&p->platinum_regs->reg[27].r, 0x2aa); */ + + STORE_D2(0, (p->total_vram == 0x100000 ? + init->dacula_ctrl[cmode] & 0xf : + init->dacula_ctrl[cmode])); + STORE_D2(1, 4); + STORE_D2(2, 0); + /* + * Try to determine whether we have an old or a new DACula. + */ + out_8(&p->cmap_regs->addr, 0x40); + dtype = in_8(&p->cmap_regs->d2); + switch (dtype) { + case 0x3c: + clkmode = 1; + break; + case 0x84: + clkmode = 0; + break; + default: + clkmode = 0; + printk("Unknown DACula type: %x\n", dtype); + } + + set_platinum_clock(p, init->clock_params[clkmode]); + + out_be32(&p->platinum_regs->reg[24].r, 0); /* turn display on */ + +#ifdef CONFIG_FB_COMPAT_XPMAC + /* And let the world know the truth. */ + if (!console_fb_info || console_fb_info == &p->info) { + display_info.height = p->var.yres; + display_info.width = p->var.xres; + display_info.depth = ( (cmode == CMODE_32) ? 32 : + ((cmode == CMODE_16) ? 16 : 8)); + display_info.pitch = p->fix.line_length; + display_info.mode = vmode; + strncpy(display_info.name, "platinum", + sizeof(display_info.name)); + display_info.fb_address = p->frame_buffer_phys + + init->fb_offset + + 0x10; + display_info.cmap_adr_address = p->cmap_regs_phys; + display_info.cmap_data_address = p->cmap_regs_phys + 0x30; + display_info.disp_reg_address = p->platinum_regs_phys; + console_fb_info = &p->info; + } +#endif /* CONFIG_FB_COMPAT_XPMAC */ +} + +__initfunc(void platinum_init(void)) +{ +#ifndef CONFIG_FB_OF + struct device_node *dp; + + dp = find_devices("platinum"); + if (dp != 0) + platinum_of_init(dp); +#endif /* CONFIG_FB_OF */ +} + +__initfunc(void platinum_of_init(struct device_node *dp)) +{ + struct fb_info_platinum *p; + unsigned long addr, size; + int i, bank0, bank1, bank2, bank3; +//FUNCID; + if(dp->n_addrs != 2) + panic("expecting 2 address for platinum (got %d)", dp->n_addrs); + p = kmalloc(sizeof(*p), GFP_ATOMIC); + if (p == 0) + return; + + /* Map in frame buffer and registers */ + for (i = 0; i < dp->n_addrs; ++i) { + addr = dp->addrs[i].address; + size = dp->addrs[i].size; + if (size >= 0x400000) { + /* frame buffer - map only 4MB */ + p->frame_buffer_phys = addr; + p->frame_buffer = __ioremap(addr, 0x400000, _PAGE_WRITETHRU); + p->base_frame_buffer = p->frame_buffer; + } else { + /* registers */ + p->platinum_regs_phys = addr; + p->platinum_regs = ioremap(addr, size); + } + } + p->cmap_regs_phys = 0xf301b000; /* XXX not in prom? */ + p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000); + + /* Grok total video ram */ + out_be32(&p->platinum_regs->reg[16].r, (unsigned)p->frame_buffer_phys); + out_be32(&p->platinum_regs->reg[20].r, 0x1011); /* select max vram */ + out_be32(&p->platinum_regs->reg[24].r, 0); /* switch in vram */ + eieio(); + p->frame_buffer[0x100000] = 0x34; + asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0x100000]) : "memory"); + p->frame_buffer[0x200000] = 0x56; + asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0x200000]) : "memory"); + p->frame_buffer[0x300000] = 0x78; + asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0x300000]) : "memory"); + bank0 = 1; /* builtin 1MB vram, always there */ + bank1 = p->frame_buffer[0x100000] == 0x34; + bank2 = p->frame_buffer[0x200000] == 0x56; + bank3 = p->frame_buffer[0x300000] == 0x78; + p->total_vram = (bank0 + bank1 + bank2 + bank3) * 0x100000; + printk("Total VRAM = %dMB\n", p->total_vram / 1024 / 1024); + +// p->frame_buffer = p->base_frame_buffer +// + platinum_reg_init[p->par.vmode-1]->fb_offset; + +#ifdef CONFIG_FB_COMPAT_XPMAC +#if 0 + console_set_cmap_ptr = platinum_set_cmap; + console_setmode_ptr = platinum_console_setmode; +#endif +#endif /* CONFIG_FB_COMPAT_XPMAC */ + + init_platinum(p); +} + +/* + * Get the monitor sense value. + * Note that this can be called before calibrate_delay, + * so we can't use udelay. + */ +static int read_platinum_sense(struct fb_info_platinum *p) +{ + int sense; + + out_be32(&p->platinum_regs->reg[23].r, 7); /* turn off drivers */ + __delay(2000); + sense = (~in_be32(&p->platinum_regs->reg[23].r) & 7) << 8; + + /* drive each sense line low in turn and collect the other 2 */ + out_be32(&p->platinum_regs->reg[23].r, 3); /* drive A low */ + __delay(2000); + sense |= (~in_be32(&p->platinum_regs->reg[23].r) & 3) << 4; + out_be32(&p->platinum_regs->reg[23].r, 5); /* drive B low */ + __delay(2000); + sense |= (~in_be32(&p->platinum_regs->reg[23].r) & 4) << 1; + sense |= (~in_be32(&p->platinum_regs->reg[23].r) & 1) << 2; + out_be32(&p->platinum_regs->reg[23].r, 6); /* drive C low */ + __delay(2000); + sense |= (~in_be32(&p->platinum_regs->reg[23].r) & 6) >> 1; + + out_be32(&p->platinum_regs->reg[23].r, 7); /* turn off drivers */ + + return sense; +} + +#if 0 +/* This routine takes a user-supplied var, and picks the best vmode/cmode from it. */ +static int platinum_var_to_par(struct fb_var_screeninfo *var, + struct fb_par_platinum *par, const struct fb_info *fb_info) +{ + int xres = var->xres; + int yres = var->yres; + int bpp = var->bits_per_pixel; + + struct platinum_regvals *init; + struct fb_info_platinum *p = (struct fb_info_platinum *) fb_info; + +// FUNCID; + /* + * 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. + */ + /* swiped by jonh from atyfb.c */ + 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 { + printk(KERN_ERR "Bad resolution in platinum_var_to_par()!\n"); + 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; +*/ + + /* I'm too chicken to think about virtual */ + /* resolutions just yet. Bok bok. */ + + /* And I'm too chicken to even figure out what they are. Awk awk. [danj] */ + if (var->xres_virtual > xres || var->yres_virtual > yres + || var->xoffset != 0 || var->yoffset != 0) { + printk(KERN_ERR "Bad virtual resolution in platinum_var_to_par()!\n"); + return -EINVAL; + } + + par->xres = xres; + par->yres = yres; + par->vxres = xres; + par->vyres = yres; + par->xoffset = 0; + par->yoffset = 0; + + if (bpp <= 8) + par->cmode = CMODE_8; + else if (bpp <= 16) + par->cmode = CMODE_16; + else if (bpp <= 32) + par->cmode = CMODE_32; + else { + printk(KERN_ERR "Bad color mode in platinum_var_to_par()!\n"); + return -EINVAL; + } + + if (platinum_vram_reqd(par->vmode, par->cmode) > p->total_vram) { + printk(KERN_ERR "Bad vram size requested in platinum_var_to_par()!\n"); + return -EINVAL; + } + /* Check if we know about the wanted video mode */ + init = platinum_reg_init[par->vmode-1]; + if (init == NULL) { + /* I'm not sure if platinum has any specific requirements -- */ + /* if we have a regvals struct, we're good to go? */ + printk(KERN_ERR "platinum_reg_init failed platinum_var_to_par()!\n"); + return -EINVAL; + } + + return 0; +} +#else +/* This routine takes a user-supplied var, and picks the best vmode/cmode from it. */ +static int platinum_var_to_par(struct fb_var_screeninfo *var, + struct fb_par_platinum *par, const struct fb_info *fb_info) +{ + struct fb_info_platinum *p = (struct fb_info_platinum *) fb_info; + +// FUNCID; + if(mac_var_to_vmode(var, &par->vmode, &par->cmode) != 0) + return -EINVAL; + par->xres = par->vxres = vmode_attrs[par->vmode - 1].hres; + par->yres = par->vyres = vmode_attrs[par->vmode - 1].vres; + par->xoffset = par->yoffset = 0; + + if (platinum_vram_reqd(par->vmode, par->cmode) > p->total_vram) + return -EINVAL; + + /* Check if we know about the wanted video mode */ + if(!platinum_reg_init[par->vmode-1]) { + /* I'm not sure if platinum has any specific requirements -- */ + /* if we have a regvals struct, we're good to go? */ + return -EINVAL; + } + return 0; +} +#endif + +#if 0 +static void platinum_par_to_var(struct fb_par_platinum *par, struct fb_var_screeninfo *var) +{ + memset(var, 0, sizeof(*var)); + var->xres = vmode_attrs[par->vmode - 1].hres; + var->yres = vmode_attrs[par->vmode - 1].vres; + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; /* For now. */ + var->xoffset = par->xoffset; + var->yoffset = par->yoffset; + var->grayscale = 0; + + if(par->cmode != CMODE_8 && par->cmode != CMODE_16 && par->cmode != CMODE_32) { + printk(KERN_ERR "Bad color mode in platinum_par_to_var()!\n"); + par->cmode = CMODE_8; + } + 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->vmode = FB_VMODE_NONINTERLACED; + + /* these are total guesses, copied right out of atyfb.c */ + var->left_margin = var->right_margin = 64; + var->upper_margin = var->lower_margin = 32; + var->hsync_len = 8; + var->vsync_len = 8; + var->sync = 0; + +#if 1 +/* jonh's pixclocks...*/ + /* 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); +#else +/* danj's */ + /* 10^12 * clock_params[0] / (3906400 * clock_params[1] * 2^clock_params[2]) */ + /* (10^12 * clock_params[0] / (3906400 * clock_params[1])) >> clock_params[2] */ + /* (255990.17 * clock_params[0] / clock_params[1]) >> clock_params[2] */ + var->pixclock = 255990 * platinum_reg_init[par->vmode-1]->clock_params[0]; + var->pixclock /= platinum_reg_init[par->vmode-1]->clock_params[1]; + var->pixclock >>= platinum_reg_init[par->vmode-1]->clock_params[2]; +#endif +} +#else +static inline void platinum_par_to_var(struct fb_par_platinum *par, struct fb_var_screeninfo *var) +{ +// FUNCID; + mac_vmode_to_var(par->vmode, par->cmode, var); +} +#endif + +static void platinum_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_platinum *p) +{ +// FUNCID; + memset(fix, 0, sizeof(*fix)); + strcpy(fix->id, "platinum"); + fix->mmio_start = (char *)p->platinum_regs_phys; + fix->mmio_len = 0x1000; + fix->type = FB_TYPE_PACKED_PIXELS; + + fix->type_aux = 0; + fix->ywrapstep = 0; + fix->xpanstep = 0; + fix->ypanstep = 0; +} + +/* Fix must already be inited ^^^^^^^ */ +static void platinum_par_to_fix(struct fb_par_platinum *par, + struct fb_fix_screeninfo *fix, + struct fb_info_platinum *p) +{ +// FUNCID; + fix->smem_start = (void *)(p->frame_buffer_phys); + fix->smem_len = platinum_vram_reqd(par->vmode, par->cmode); + /* Hmm, jonh used total_vram here. */ + fix->visual = (par->cmode == CMODE_8) ? + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; +// fix->line_length = par->vxres << par->cmode; + fix->line_length = platinum_reg_init[par->vmode-1]->pitch[par->cmode]; + +} + +static void platinum_init_display(struct display *disp) +{ + memset(disp, 0, sizeof(*disp)); + disp->type = /* fix->type */ FB_TYPE_PACKED_PIXELS; + disp->can_soft_blank = 1; + disp->scrollmode = SCROLL_YREDRAW; +#if 0 + disp->type_aux = fix->type_aux; + disp->cmap.red = NULL; /* ??? danj */ + disp->cmap.green = NULL; + disp->cmap.blue = NULL; + disp->cmap.transp = NULL; + /* Yeah, I realize I just set 0 = 0. */ +#endif +} + +static void platinum_par_to_display(struct fb_par_platinum *par, + struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_platinum *p) +{ +// FUNCID; + disp->var = p->var; + disp->screen_base = (char *) p->frame_buffer + + platinum_reg_init[par->vmode-1]->fb_offset + + ((par->yres % 16) / 2) * fix->line_length + 0x10; + disp->visual = fix->visual; + disp->line_length = fix->line_length; + + if(disp->scrollmode != SCROLL_YREDRAW) { + printk(KERN_ERR "Scroll mode not YREDRAW in platinum_par_to_display!!\n"); + disp->scrollmode = SCROLL_YREDRAW; + } + + switch(par->cmode) { +#ifdef FBCON_HAS_CFB8 + case CMODE_8: + disp->dispsw = &fbcon_cfb8; + break; +#endif +#ifdef FBCON_HAS_CFB16 + case CMODE_16: + disp->dispsw = &fbcon_cfb16; + break; +#endif +#ifdef FBCON_HAS_CFB32 + case CMODE_32: + disp->dispsw = &fbcon_cfb32; + break; +#endif + default: + disp->dispsw = NULL; + break; + } +} + +static void platinum_init_info(struct fb_info *info, struct fb_info_platinum *p) +{ +// FUNCID; + strcpy(info->modename, p->fix.id); + info->node = -1; /* ??? danj */ + info->fbops = &platinumfb_ops; + info->disp = &p->disp; + info->fontname[0] = 0; + info->changevar = NULL; + info->switch_con = &platinum_switch; + info->updatevar = &platinum_updatevar; + info->blank = &platinum_blank; +} + +/* danj: Oh, I HOPE I didn't miss anything major in here... */ +static void platinum_par_to_all(struct fb_info_platinum *p, int init) +{ +// FUNCID; + if(init) { + platinum_init_fix(&p->fix, p); + } + platinum_par_to_fix(&p->par, &p->fix, p); + + platinum_par_to_var(&p->par, &p->var); + + if(init) { + platinum_init_display(&p->disp); + } + platinum_par_to_display(&p->par, &p->disp, &p->fix, p); + + if(init) { + platinum_init_info(&p->info, p); + } +} + +#if 0 +__initfunc(void platinum_setup(char *options, int *ints)) +{ + /* Parse user speficied options (`video=platinumfb:') */ + FUNCID; +} + +#endif + diff --git a/drivers/video/platinumfb.h b/drivers/video/platinumfb.h new file mode 100644 index 000000000..a9b4b1c8f --- /dev/null +++ b/drivers/video/platinumfb.h @@ -0,0 +1,399 @@ +/* + * linux/drivers/video/platinumfb-hw.c -- Frame buffer device for the + * Platinum on-board video in PowerMac 7200s (and some clones based + * on the same motherboard.) + * + * Created 09 Feb 1998 by Jon Howell <jonh@cs.dartmouth.edu> + * + * Copyright (C) 1998 Jon Howell + * + * based on drivers/macintosh/platinum.c: Console support + * for PowerMac "platinum" display adaptor. + * Copyright (C) 1996 Paul Mackerras and Mark Abene. + * + * based on skeletonfb.c: + * 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. + */ + +/* + * Structure of the registers for the DACula colormap device. + */ +struct cmap_regs { + unsigned char addr; + char pad1[15]; + unsigned char d1; + char pad2[15]; + unsigned char d2; + char pad3[15]; + unsigned char lut; + char pad4[15]; +}; + +/* + * Structure of the registers for the "platinum" display adaptor". + */ +struct preg { /* padded register */ + unsigned r; /* notice this is 32 bits. */ + char pad[12]; +}; + +struct platinum_regs { + struct preg reg[128]; +}; + +/* + * Register initialization tables for the platinum display. + * + * It seems that there are two different types of platinum display + * out there. Older ones use the values in clocksel[1], for which + * the formula for the clock frequency seems to be + * F = 14.3MHz * c0 / (c1 & 0x1f) / (1 << (c1 >> 5)) + * Newer ones use the values in clocksel[0], for which the formula + * seems to be + * F = 15MHz * c0 / ((c1 & 0x1f) + 2) / (1 << (c1 >> 5)) + */ +struct platinum_regvals { + int fb_offset; + int pitch[3]; + unsigned regs[26]; + unsigned char offset[3]; + unsigned char mode[3]; + unsigned char dacula_ctrl[3]; + unsigned char clock_params[2][2]; +}; + +#define DIV2 0x20 +#define DIV4 0x40 +#define DIV8 0x60 +#define DIV16 0x80 + +/* 1280x1024, 75Hz (20) */ +static struct platinum_regvals platinum_reg_init_20 = { + 0x5c00, + { 1312, 2592, 2592 }, + { 0xffc, 4, 0, 0, 0, 0, 0x428, 0, + 0, 0xb3, 0xd3, 0x12, 0x1a5, 0x23, 0x28, 0x2d, + 0x5e, 0x19e, 0x1a4, 0x854, 0x852, 4, 9, 0x50, + 0x850, 0x851 }, { 0x58, 0x5d, 0x5d }, + { 0, 0xff, 0xff }, { 0x51, 0x55, 0x55 }, + {{ 45, 3 }, { 66, 7 }} +}; + +/* 1280x960, 75Hz (19) */ +static struct platinum_regvals platinum_reg_init_19 = { + 0x5c00, + { 1312, 2592, 2592 }, + { 0xffc, 4, 0, 0, 0, 0, 0x428, 0, + 0, 0xb2, 0xd2, 0x12, 0x1a3, 0x23, 0x28, 0x2d, + 0x5c, 0x19c, 0x1a2, 0x7d0, 0x7ce, 4, 9, 0x4c, + 0x7cc, 0x7cd }, { 0x56, 0x5b, 0x5b }, + { 0, 0xff, 0xff }, { 0x51, 0x55, 0x55 }, + {{ 42, 3 }, { 44, 5 }} +}; + +/* 1152x870, 75Hz (18) */ +static struct platinum_regvals platinum_reg_init_18 = { + 0x11b0, + { 1184, 2336, 4640 }, + { 0xff0, 4, 0, 0, 0, 0, 0x38f, 0, + 0, 0x294, 0x16c, 0x20, 0x2d7, 0x3f, 0x49, 0x53, + 0x82, 0x2c2, 0x2d6, 0x726, 0x724, 4, 9, 0x52, + 0x71e, 0x722 }, { 0x74, 0x7c, 0x81 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 26, 0 + DIV2 }, { 42, 6 }} +}; + +/* 1024x768, 75Hz (17) */ +static struct platinum_regvals platinum_reg_init_17 = { + 0x10b0, + { 1056, 2080, 4128 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x254, 0x14b, 0x18, 0x295, 0x2f, 0x32, 0x3b, + 0x80, 0x280, 0x296, 0x648, 0x646, 4, 9, 0x40, + 0x640, 0x644 }, { 0x72, 0x7a, 0x7f }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 54, 3 + DIV2 }, { 67, 12 }} +}; + +/* 1024x768, 75Hz (16) */ +static struct platinum_regvals platinum_reg_init_16 = { + 0x10b0, + { 1056, 2080, 4128 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x250, 0x147, 0x17, 0x28f, 0x2f, 0x35, 0x47, + 0x82, 0x282, 0x28e, 0x640, 0x63e, 4, 9, 0x3c, + 0x63c, 0x63d }, { 0x74, 0x7c, 0x81 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 20, 0 + DIV2 }, { 11, 2 }} +}; + +/* 1024x768, 70Hz (15) */ +static struct platinum_regvals platinum_reg_init_15 = { + 0x10b0, + { 1056, 2080, 4128 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x254, 0x14b, 0x22, 0x297, 0x43, 0x49, 0x5b, + 0x86, 0x286, 0x296, 0x64c, 0x64a, 0xa, 0xf, 0x44, + 0x644, 0x646 }, { 0x78, 0x80, 0x85 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 19, 0 + DIV2 }, { 110, 21 }} +}; + +/* 1024x768, 60Hz (14) */ +static struct platinum_regvals platinum_reg_init_14 = { + 0x10b0, + { 1056, 2080, 4128 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x25a, 0x14f, 0x22, 0x29f, 0x43, 0x49, 0x5b, + 0x8e, 0x28e, 0x29e, 0x64c, 0x64a, 0xa, 0xf, 0x44, + 0x644, 0x646 }, { 0x80, 0x88, 0x8d }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 71, 6 + DIV2 }, { 118, 13 + DIV2 }} +}; + +/* 832x624, 75Hz (13) */ +static struct platinum_regvals platinum_reg_init_13 = { + 0x70, + { 864, 1680, 3360 }, /* MacOS does 1680 instead of 1696 to fit 16bpp in 1MB */ + { 0xff0, 4, 0, 0, 0, 0, 0x299, 0, + 0, 0x21e, 0x120, 0x10, 0x23f, 0x1f, 0x25, 0x37, + 0x8a, 0x22a, 0x23e, 0x536, 0x534, 4, 9, 0x52, + 0x532, 0x533 }, { 0x7c, 0x84, 0x89 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 30, 0 + DIV4 }, { 56, 7 + DIV2 }} +}; + +/* 800x600, 75Hz (12) */ +static struct platinum_regvals platinum_reg_init_12 = { + 0x1010, + { 832, 1632, 3232 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x1ce, 0x108, 0x14, 0x20f, 0x27, 0x30, 0x39, + 0x72, 0x202, 0x20e, 0x4e2, 0x4e0, 4, 9, 0x2e, + 0x4de, 0x4df }, { 0x64, 0x6c, 0x71 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 122, 7 + DIV4 }, { 62, 9 + DIV2 }} +}; + +/* 800x600, 72Hz (11) */ +static struct platinum_regvals platinum_reg_init_11 = { + 0x1010, + { 832, 1632, 3232 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x1ca, 0x104, 0x1e, 0x207, 0x3b, 0x44, 0x4d, + 0x56, 0x1e6, 0x206, 0x534, 0x532, 0xa, 0xe, 0x38, + 0x4e8, 0x4ec }, { 0x48, 0x50, 0x55 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 26, 0 + DIV4 }, { 42, 6 + DIV2 }} +}; + +/* 800x600, 60Hz (10) */ +static struct platinum_regvals platinum_reg_init_10 = { + 0x1010, + { 832, 1632, 3232 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x1ce, 0x108, 0x20, 0x20f, 0x3f, 0x45, 0x5d, + 0x66, 0x1f6, 0x20e, 0x4e8, 0x4e6, 6, 0xa, 0x34, + 0x4e4, 0x4e5 }, { 0x58, 0x60, 0x65 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 54, 3 + DIV4 }, { 95, 1 + DIV8 }} +}; + +/* 800x600, 56Hz (9) --unsupported? copy of mode 10 for now... */ +static struct platinum_regvals platinum_reg_init_9 = { + 0x1010, + { 832, 1632, 3232 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x1ce, 0x108, 0x20, 0x20f, 0x3f, 0x45, 0x5d, + 0x66, 0x1f6, 0x20e, 0x4e8, 0x4e6, 6, 0xa, 0x34, + 0x4e4, 0x4e5 }, { 0x58, 0x60, 0x65 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 54, 3 + DIV4 }, { 88, 1 + DIV8 }} +}; + +/* 768x576, 50Hz Interlaced-PAL (8) */ +static struct platinum_regvals platinum_reg_init_8 = { + 0x1010, + { 800, 1568, 3104 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0xc8, 0xec, 0x11, 0x1d7, 0x22, 0x25, 0x36, + 0x47, 0x1c7, 0x1d6, 0x271, 0x270, 4, 9, 0x27, + 0x267, 0x26b }, { 0x39, 0x41, 0x46 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 31, 0 + DIV16 }, { 74, 9 + DIV8 }} +}; + +/* 640x870, 75Hz Portrait (7) */ +static struct platinum_regvals platinum_reg_init_7 = { + 0xb10, + { 672, 1312, 2592 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x176, 0xd0, 0x14, 0x19f, 0x27, 0x2d, 0x3f, + 0x4a, 0x18a, 0x19e, 0x72c, 0x72a, 4, 9, 0x58, + 0x724, 0x72a }, { 0x3c, 0x44, 0x49 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 30, 0 + DIV4 }, { 56, 7 + DIV2 }} +}; + +/* 640x480, 67Hz (6) */ +static struct platinum_regvals platinum_reg_init_6 = { + 0x1010, + { 672, 1312, 2592 }, + { 0xff0, 4, 0, 0, 0, 0, 0x209, 0, + 0, 0x18e, 0xd8, 0x10, 0x1af, 0x1f, 0x25, 0x37, + 0x4a, 0x18a, 0x1ae, 0x41a, 0x418, 4, 9, 0x52, + 0x412, 0x416 }, { 0x3c, 0x44, 0x49 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 99, 4 + DIV8 }, { 42, 5 + DIV4 }} +}; + +/* 640x480, 60Hz (5) */ +static struct platinum_regvals platinum_reg_init_5 = { + 0x1010, + { 672, 1312, 2592 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x15e, 0xc8, 0x18, 0x18f, 0x2f, 0x35, 0x3e, + 0x42, 0x182, 0x18e, 0x41a, 0x418, 2, 7, 0x44, + 0x404, 0x408 }, { 0x34, 0x3c, 0x41 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 26, 0 + DIV8 }, { 14, 2 + DIV4 }} +}; + +/* 640x480, 60Hz Interlaced-NTSC (4) */ +static struct platinum_regvals platinum_reg_init_4 = { + 0x1010, + { 672, 1312, 2592 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0xa5, 0xc3, 0xe, 0x185, 0x1c, 0x1f, 0x30, + 0x37, 0x177, 0x184, 0x20d, 0x20c, 5, 0xb, 0x23, + 0x203, 0x206 }, { 0x29, 0x31, 0x36 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 94, 5 + DIV16 }, { 48, 7 + DIV8 }} +}; + +/* 640x480, 50Hz Interlaced-PAL (3) */ +static struct platinum_regvals platinum_reg_init_3 = { + 0x1010, + { 672, 1312, 2592 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0xc8, 0xec, 0x11, 0x1d7, 0x22, 0x25, 0x36, + 0x67, 0x1a7, 0x1d6, 0x271, 0x270, 4, 9, 0x57, + 0x237, 0x26b }, { 0x59, 0x61, 0x66 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 31, 0 + DIV16 }, { 74, 9 + DIV8 }} +}; + +/* 512x384, 60Hz (2) */ +static struct platinum_regvals platinum_reg_init_2 = { + 0x1010, + { 544, 1056, 2080 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0x25c, 0x140, 0x10, 0x27f, 0x1f, 0x2b, 0x4f, + 0x68, 0x268, 0x27e, 0x32e, 0x32c, 4, 9, 0x2a, + 0x32a, 0x32b }, { 0x5a, 0x62, 0x67 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 33, 2 + DIV8 }, { 79, 9 + DIV8 }} +}; + +/* 512x384, 60Hz Interlaced-NTSC (1) */ +static struct platinum_regvals platinum_reg_init_1 = { + 0x1010, + { 544, 1056, 2080 }, + { 0xff0, 4, 0, 0, 0, 0, 0x320, 0, + 0, 0xa5, 0xc3, 0xe, 0x185, 0x1c, 0x1f, 0x30, + 0x57, 0x157, 0x184, 0x20d, 0x20c, 5, 0xb, 0x53, + 0x1d3, 0x206 }, { 0x49, 0x51, 0x56 }, + { 2, 0, 0xff }, { 0x11, 0x15, 0x19 }, + {{ 94, 5 + DIV16 }, { 48, 7 + DIV8 }} +}; + +#define VMODE_MAX 20 + +static struct platinum_regvals *platinum_reg_init[VMODE_MAX] = { + &platinum_reg_init_1, + &platinum_reg_init_2, + &platinum_reg_init_3, + &platinum_reg_init_4, + &platinum_reg_init_5, + &platinum_reg_init_6, + &platinum_reg_init_7, + &platinum_reg_init_8, + &platinum_reg_init_9, + &platinum_reg_init_10, + &platinum_reg_init_11, + &platinum_reg_init_12, + &platinum_reg_init_13, + &platinum_reg_init_14, + &platinum_reg_init_15, + &platinum_reg_init_16, + &platinum_reg_init_17, + &platinum_reg_init_18, + &platinum_reg_init_19, + &platinum_reg_init_20 +}; + +struct vmode_attr { + int hres; + int vres; + int vfreq; + int interlaced; +}; + +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} +}; + +/* this stuff should probably be shared by the various vmode-based */ +/* drivers in a vmode.h header. */ + +#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 */ + +#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 */ diff --git a/drivers/video/prom.uni b/drivers/video/prom.uni new file mode 100644 index 000000000..58f9c04ed --- /dev/null +++ b/drivers/video/prom.uni @@ -0,0 +1,11 @@ +# +# Unicode mapping table for font in Sun PROM +# +# +0x20-0x7e idem +0xa0-0xff idem +# +0x7c U+2502 +0x2d U+2500 +0x2b U+250c U+2510 U+2514 U+2518 U+251c U+2524 U+252c U+2534 U+253c +0xa4 U+fffd diff --git a/drivers/video/promcon.c b/drivers/video/promcon.c new file mode 100644 index 000000000..76f945b45 --- /dev/null +++ b/drivers/video/promcon.c @@ -0,0 +1,600 @@ +/* $Id: promcon.c,v 1.10 1998/07/24 15:31:53 jj Exp $ + * Console driver utilizing PROM sun terminal emulation + * + * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) + * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) + */ + +#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/console.h> +#include <linux/console_struct.h> +#include <linux/vt_kern.h> +#include <linux/selection.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/kd.h> + +#include <asm/oplib.h> +#include <asm/uaccess.h> + +static short pw = 80 - 1, ph = 34 - 1; +static short px, py; +static unsigned long promcon_uni_pagedir[2]; + +extern u8 promfont_unicount[]; +extern u16 promfont_unitable[]; + +#define PROMCON_COLOR 0 + +#if PROMCON_COLOR +#define inverted(s) ((((s) & 0x7700) == 0x0700) ? 0 : 1) +#else +#define inverted(s) (((s) & 0x0800) ? 1 : 0) +#endif + +static __inline__ void +promcon_puts(char *buf, int cnt) +{ + prom_printf("%*.*s", cnt, cnt, buf); +} + +static int +promcon_start(struct vc_data *conp, char *b) +{ + unsigned short *s = (unsigned short *) + (conp->vc_origin + py * conp->vc_size_row + (px << 1)); + + if (px == pw) { + unsigned short *t = s - 1; + + if (inverted(*s) && inverted(*t)) + return sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", + *s, *t); + else if (inverted(*s)) + return sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", + *s, *t); + else if (inverted(*t)) + return sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", + *s, *t); + else + return sprintf(b, "\b%c\b\033[@%c", *s, *t); + } + + if (inverted(*s)) + return sprintf(b, "\033[7m%c\033[m\b", *s); + else + return sprintf(b, "%c\b", *s); +} + +static int +promcon_end(struct vc_data *conp, char *b) +{ + unsigned short *s = (unsigned short *) + (conp->vc_origin + py * conp->vc_size_row + (px << 1)); + char *p = b; + + b += sprintf(b, "\033[%d;%dH", py + 1, px + 1); + + if (px == pw) { + unsigned short *t = s - 1; + + if (inverted(*s) && inverted(*t)) + b += sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", *s, *t); + else if (inverted(*s)) + b += sprintf(b, "\b%c\b\033[@%c", *s, *t); + else if (inverted(*t)) + b += sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", *s, *t); + else + b += sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", *s, *t); + return b - p; + } + + if (inverted(*s)) + b += sprintf(b, "%c\b", *s); + else + b += sprintf(b, "\033[7m%c\033[m\b", *s); + return b - p; +} + +__initfunc(const char *promcon_startup(void)) +{ + const char *display_desc = "PROM"; + int node; + char buf[40]; + + node = prom_getchild(prom_root_node); + node = prom_searchsiblings(node, "options"); + if (prom_getproperty(node, "screen-#columns", buf, 40) != -1) { + pw = simple_strtoul(buf, NULL, 0); + if (pw < 10 || pw > 256) + pw = 80; + pw--; + } + if (prom_getproperty(node, "screen-#rows", buf, 40) != -1) { + ph = simple_strtoul(buf, NULL, 0); + if (ph < 10 || ph > 256) + ph = 34; + ph--; + } + promcon_puts("\033[H\033[J", 6); + return display_desc; +} + +__initfunc(static void +promcon_init_unimap(struct vc_data *conp)) +{ + mm_segment_t old_fs = get_fs(); + struct unipair *p, *p1; + u16 *q; + int i, j, k; + + p = kmalloc(256*sizeof(struct unipair), GFP_KERNEL); + if (!p) return; + + q = promfont_unitable; + p1 = p; + k = 0; + for (i = 0; i < 256; i++) + for (j = promfont_unicount[i]; j; j--) { + p1->unicode = *q++; + p1->fontpos = i; + p1++; + k++; + } + set_fs(KERNEL_DS); + con_clear_unimap(conp->vc_num, NULL); + con_set_unimap(conp->vc_num, k, p); + con_protect_unimap(conp->vc_num, 1); + set_fs(old_fs); + kfree(p); +} + +static void +promcon_init(struct vc_data *conp, int init) +{ + unsigned long p; + + conp->vc_can_do_color = PROMCON_COLOR; + if (init) { + conp->vc_cols = pw + 1; + conp->vc_rows = ph + 1; + } + p = *conp->vc_uni_pagedir_loc; + if (conp->vc_uni_pagedir_loc == &conp->vc_uni_pagedir || + !--conp->vc_uni_pagedir_loc[1]) + con_free_unimap(conp->vc_num); + conp->vc_uni_pagedir_loc = promcon_uni_pagedir; + promcon_uni_pagedir[1]++; + if (!promcon_uni_pagedir[0] && p) { + promcon_init_unimap(conp); + } + if (!init) { + if (conp->vc_cols != pw + 1 || conp->vc_rows != ph + 1) + vc_resize_con(ph + 1, pw + 1, conp->vc_num); + else if (conp->vc_num == fg_console) + update_screen(fg_console); + } +} + +static void +promcon_deinit(struct vc_data *conp) +{ + /* When closing the last console, reset video origin */ + if (!--promcon_uni_pagedir[1]) + con_free_unimap(conp->vc_num); + conp->vc_uni_pagedir_loc = &conp->vc_uni_pagedir; + con_set_default_unimap(conp->vc_num); +} + +static int +promcon_switch(struct vc_data *conp) +{ + return 1; +} + +static unsigned short * +promcon_repaint_line(unsigned short *s, unsigned char *buf, unsigned char **bp) +{ + int cnt = pw + 1; + int attr = -1; + unsigned char *b = *bp; + + while (cnt--) { + if (attr != inverted(*s)) { + attr = inverted(*s); + if (attr) { + strcpy (b, "\033[7m"); + b += 4; + } else { + strcpy (b, "\033[m"); + b += 3; + } + } + *b++ = *s++; + if (b - buf >= 224) { + promcon_puts(buf, b - buf); + b = buf; + } + } + *bp = b; + return s; +} + +static void +promcon_putcs(struct vc_data *conp, const unsigned short *s, + int count, int y, int x) +{ + unsigned char buf[256], *b = buf; + unsigned short attr = *s; + unsigned char save; + int i, last = 0; + + if (console_blanked) + return; + + if (count <= 0) + return; + + b += promcon_start(conp, b); + + if (x + count >= pw + 1) { + if (count == 1) { + x -= 1; + save = *(unsigned short *)(conp->vc_origin + + y * conp->vc_size_row + + (x << 1)); + + if (px != x || py != y) { + b += sprintf(b, "\033[%d;%dH", y + 1, x + 1); + px = x; + py = y; + } + + if (inverted(attr)) + b += sprintf(b, "\033[7m%c\033[m", *s++); + else + b += sprintf(b, "%c", *s++); + + strcpy(b, "\b\033[@"); + b += 4; + + if (inverted(save)) + b += sprintf(b, "\033[7m%c\033[m", save); + else + b += sprintf(b, "%c", save); + + px++; + + b += promcon_end(conp, b); + promcon_puts(buf, b - buf); + return; + } else { + last = 1; + count = pw - x - 1; + } + } + + if (inverted(attr)) { + strcpy(b, "\033[7m"); + b += 4; + } + + if (px != x || py != y) { + b += sprintf(b, "\033[%d;%dH", y + 1, x + 1); + px = x; + py = y; + } + + for (i = 0; i < count; i++) { + if (b - buf >= 224) { + promcon_puts(buf, b - buf); + b = buf; + } + *b++ = *s++; + } + + px += count; + + if (last) { + save = *s++; + b += sprintf(b, "%c\b\033[@%c", *s++, save); + px++; + } + + if (inverted(attr)) { + strcpy(b, "\033[m"); + b += 3; + } + + b += promcon_end(conp, b); + promcon_puts(buf, b - buf); +} + +static void +promcon_putc(struct vc_data *conp, int c, int y, int x) +{ + unsigned short s = c; + + if (console_blanked) + return; + + promcon_putcs(conp, &s, 1, y, x); +} + +static void +promcon_clear(struct vc_data *conp, int sy, int sx, int height, int width) +{ + unsigned char buf[256], *b = buf; + int i, j; + + if (console_blanked) + return; + + b += promcon_start(conp, b); + + if (!sx && width == pw + 1) { + + if (!sy && height == ph + 1) { + strcpy(b, "\033[H\033[J"); + b += 6; + b += promcon_end(conp, b); + promcon_puts(buf, b - buf); + return; + } else if (sy + height == ph + 1) { + b += sprintf(b, "\033[%dH\033[J", sy + 1); + b += promcon_end(conp, b); + promcon_puts(buf, b - buf); + return; + } + + b += sprintf(b, "\033[%dH", sy + 1); + for (i = 1; i < height; i++) { + strcpy(b, "\033[K\n"); + b += 4; + } + + strcpy(b, "\033[K"); + b += 3; + + b += promcon_end(conp, b); + promcon_puts(buf, b - buf); + return; + + } else if (sx + width == pw + 1) { + + b += sprintf(b, "\033[%d;%dH", sy + 1, sx + 1); + for (i = 1; i < height; i++) { + strcpy(b, "\033[K\n"); + b += 4; + } + + strcpy(b, "\033[K"); + b += 3; + + b += promcon_end(conp, b); + promcon_puts(buf, b - buf); + return; + } + + for (i = sy + 1; i <= sy + height; i++) { + b += sprintf(b, "\033[%d;%dH", i, sx + 1); + for (j = 0; j < width; j++) + *b++ = ' '; + if (b - buf + width >= 224) { + promcon_puts(buf, b - buf); + b = buf; + } + } + + b += promcon_end(conp, b); + promcon_puts(buf, b - buf); +} + +static void +promcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, + int height, int width) +{ + char buf[256], *b = buf; + + if (console_blanked) + return; + + b += promcon_start(conp, b); + if (sy == dy && height == 1) { + if (dx > sx && dx + width == conp->vc_cols) + b += sprintf(b, "\033[%d;%dH\033[%d@\033[%d;%dH", + sy + 1, sx + 1, dx - sx, py + 1, px + 1); + else if (dx < sx && sx + width == conp->vc_cols) + b += sprintf(b, "\033[%d;%dH\033[%dP\033[%d;%dH", + dy + 1, dx + 1, sx - dx, py + 1, px + 1); + + b += promcon_end(conp, b); + promcon_puts(buf, b - buf); + return; + } + + /* + * FIXME: What to do here??? + * Current console.c should not call it like that ever. + */ + prom_printf("\033[7mFIXME: bmove not handled\033[m\n"); +} + +static void +promcon_cursor(struct vc_data *conp, int mode) +{ + char buf[32], *b = buf; + + switch (mode) { + case CM_ERASE: + break; + + case CM_MOVE: + case CM_DRAW: + b += promcon_start(conp, b); + if (px != conp->vc_x || py != conp->vc_y) { + px = conp->vc_x; + py = conp->vc_y; + b += sprintf(b, "\033[%d;%dH", py + 1, px + 1); + } + promcon_puts(buf, b - buf); + break; + } +} + +static int +promcon_font_op(struct vc_data *conp, struct console_font_op *op) +{ + return -ENOSYS; +} + +static int +promcon_blank(struct vc_data *conp, int blank) +{ + if (blank) { + promcon_puts("\033[H\033[J\033[7m \033[m\b", 15); + return 0; + } else { + /* Let console.c redraw */ + return 1; + } +} + +static int +promcon_scroll(struct vc_data *conp, int t, int b, int dir, int count) +{ + unsigned char buf[256], *p = buf; + unsigned short *s; + int i; + + if (console_blanked) + return 0; + + p += promcon_start(conp, p); + + switch (dir) { + case SM_UP: + if (b == ph + 1) { + p += sprintf(p, "\033[%dH\033[%dM", t + 1, count); + px = 0; + py = t; + p += promcon_end(conp, p); + promcon_puts(buf, p - buf); + break; + } + + s = (unsigned short *)(conp->vc_origin + + (t + count) * conp->vc_size_row); + + p += sprintf(p, "\033[%dH", t + 1); + + for (i = t; i < b - count; i++) + s = promcon_repaint_line(s, buf, &p); + + for (; i < b - 1; i++) { + strcpy(p, "\033[K\n"); + p += 4; + if (p - buf >= 224) { + promcon_puts(buf, p - buf); + p = buf; + } + } + + strcpy(p, "\033[K"); + p += 3; + + p += promcon_end(conp, p); + promcon_puts(buf, p - buf); + break; + + case SM_DOWN: + if (b == ph + 1) { + p += sprintf(p, "\033[%dH\033[%dL", t + 1, count); + px = 0; + py = t; + p += promcon_end(conp, p); + promcon_puts(buf, p - buf); + break; + } + + s = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row); + + p += sprintf(p, "\033[%dH", t + 1); + + for (i = t; i < t + count; i++) { + strcpy(p, "\033[K\n"); + p += 4; + if (p - buf >= 224) { + promcon_puts(buf, p - buf); + p = buf; + } + } + + for (; i < b; i++) + s = promcon_repaint_line(s, buf, &p); + + p += promcon_end(conp, p); + promcon_puts(buf, p - buf); + break; + } + + return 0; +} + +#if !(PROMCON_COLOR) +static u8 promcon_build_attr(struct vc_data *conp, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse) +{ + return (_reverse) ? 0xf : 0x7; +} +#endif + +/* + * The console 'switch' structure for the VGA based console + */ + +static int promcon_dummy(void) +{ + return 0; +} + +#define DUMMY (void *) promcon_dummy + +struct consw prom_con = { + con_startup: promcon_startup, + con_init: promcon_init, + con_deinit: promcon_deinit, + con_clear: promcon_clear, + con_putc: promcon_putc, + con_putcs: promcon_putcs, + con_cursor: promcon_cursor, + con_scroll: promcon_scroll, + con_bmove: promcon_bmove, + con_switch: promcon_switch, + con_blank: promcon_blank, + con_font_op: promcon_font_op, + con_set_palette: DUMMY, + con_scrolldelta: DUMMY, + con_set_origin: NULL, + con_save_screen: NULL, +#if PROMCON_COLOR + con_build_attr: NULL, +#else + con_build_attr: promcon_build_attr, +#endif + con_invert_region: NULL, +}; + +__initfunc(void prom_con_init(void)) +{ + if (conswitchp == &dummy_con) + take_over_console(&prom_con, 0, MAX_NR_CONSOLES-1, 1); + else if (conswitchp == &prom_con) + promcon_init_unimap(vc_cons[fg_console].d); +} diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c index 82dcc2877..548f88602 100644 --- a/drivers/video/retz3fb.c +++ b/drivers/video/retz3fb.c @@ -20,8 +20,6 @@ * for more details. */ - -#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -81,6 +79,8 @@ struct retz3fb_par { int hsync_len; /* length of horizontal sync */ int vsync_len; /* length of vertical sync */ int vmode; + + int accel; }; struct display_data { @@ -196,7 +196,7 @@ static struct fb_videomode retz3fb_predefined[] __initdata = { "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, + 0, 0, -1, -1, FB_ACCELF_TEXT, 38461, 28, 32, 12, 10, 96, 2, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED } }, @@ -208,7 +208,7 @@ static struct fb_videomode retz3fb_predefined[] __initdata = { "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, + 0, 0, -1, -1, FB_ACCELF_TEXT, 27778, 64, 24, 22, 1, 120, 2, FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED } }, @@ -220,21 +220,21 @@ static struct fb_videomode retz3fb_predefined[] __initdata = { "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, + 0, 0, -1, -1, FB_ACCELF_TEXT, 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, + 0, 0, -1, -1, 0, 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, + 0, 0, -1, -1, 0, 38461/3, 28, 32, 12, 10, 96, 2, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED } }, @@ -255,8 +255,8 @@ static int z3fb_mode __initdata = 0; 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_open(struct fb_info *info, int user); +static int retz3fb_release(struct fb_info *info, int user); 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, @@ -278,7 +278,7 @@ static int retz3fb_ioctl(struct inode *inode, struct file *file, * Interface to the low level console driver */ -unsigned long retz3fb_init(unsigned long mem_start); +void retz3fb_init(void); 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); @@ -288,7 +288,7 @@ static void z3fb_blank(int blank, struct fb_info *info); * Text console acceleration */ -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 static struct display_switch fbcon_retz3_8; #endif @@ -834,12 +834,11 @@ static int retz3_init(void) static int retz3_encode_fix(struct fb_fix_screeninfo *fix, struct retz3fb_par *par) { - short i; - + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, retz3fb_name); fix->smem_start = (char *)z3_fbmem; fix->smem_len = z3_size; - fix->mmio_start = (unsigned char *)z3_regs; + fix->mmio_start = (char *)z3_regs; fix->mmio_len = 0x00c00000; fix->type = FB_TYPE_PACKED_PIXELS; @@ -854,10 +853,7 @@ 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; + fix->accel = FB_ACCEL_NCR_77C32BLT; return 0; } @@ -891,6 +887,11 @@ static int retz3_decode_var(struct fb_var_screeninfo *var, par->hsync_len = var->hsync_len; par->vsync_len = var->vsync_len; + if (var->accel_flags & FB_ACCELF_TEXT) + par->accel = FB_ACCELF_TEXT; + else + par->accel = 0; + return 0; } @@ -903,8 +904,7 @@ static int retz3_decode_var(struct fb_var_screeninfo *var, static int retz3_encode_var(struct fb_var_screeninfo *var, struct retz3fb_par *par) { - short i; - + memset(var, 0, sizeof(struct fb_var_screeninfo)); var->xres = par->xres; var->yres = par->yres; var->xres_virtual = par->xres_vir; @@ -926,7 +926,7 @@ static int retz3_encode_var(struct fb_var_screeninfo *var, var->height = -1; var->width = -1; - var->accel = FB_ACCEL_NCR77C32BLT; + var->accel_flags = (par->accel && par->bpp == 8) ? FB_ACCELF_TEXT : 0; var->pixclock = par->pixclock; @@ -938,9 +938,6 @@ static int retz3_encode_var(struct fb_var_screeninfo *var, var->hsync_len = par->hsync_len; var->vsync_len = par->vsync_len; - for (i = 0; i < arraysize(var->reserved); i++) - var->reserved[i] = 0; - var->vmode = par->vmode; return 0; } @@ -1202,7 +1199,7 @@ static void do_install_cmap(int con, struct fb_info *info) * Open/Release the frame buffer device */ -static int retz3fb_open(struct fb_info *info) +static int retz3fb_open(struct fb_info *info, int user) { /* * Nothing, only a usage count for the moment @@ -1212,7 +1209,7 @@ static int retz3fb_open(struct fb_info *info) return 0; } -static int retz3fb_release(struct fb_info *info) +static int retz3fb_release(struct fb_info *info, int user) { MOD_DEC_USE_COUNT; return 0; @@ -1272,7 +1269,7 @@ static void retz3fb_set_disp(int con, struct fb_info *info) if (con == -1) con = 0; - display->screen_base = (unsigned char *)fix.smem_start; + display->screen_base = fix.smem_start; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; @@ -1281,12 +1278,16 @@ static void retz3fb_set_disp(int con, struct fb_info *info) display->can_soft_blank = 1; display->inverse = z3fb_inverse; switch (display->var.bits_per_pixel) { -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 case 8: - display->dispsw = &fbcon_retz3_8; + if (display->var.accel_flags & FB_ACCELF_TEXT) { + display->dispsw = &fbcon_retz3_8; +#warning FIXME: We should reinit the graphics engine here + } else + display->dispsw = &fbcon_cfb8; break; #endif -#ifdef CONFIG_FBCON_CFB16 +#ifdef FBCON_HAS_CFB16 case 16: display->dispsw = &fbcon_cfb16; break; @@ -1305,7 +1306,7 @@ static void retz3fb_set_disp(int con, struct fb_info *info) static int retz3fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) { - int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp; + int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel; struct display *display; if (con >= 0) @@ -1326,12 +1327,14 @@ static int retz3fb_set_var(struct fb_var_screeninfo *var, int con, oldvxres = display->var.xres_virtual; oldvyres = display->var.yres_virtual; oldbpp = display->var.bits_per_pixel; + oldaccel = display->var.accel_flags; display->var = *var; if (oldxres != var->xres || oldyres != var->yres || oldvxres != var->xres_virtual || oldvyres != var->yres_virtual || - oldbpp != var->bits_per_pixel) { + oldbpp != var->bits_per_pixel || + oldaccel != var->accel_flags) { struct fb_fix_screeninfo fix; retz3fb_get_fix(&fix, con, info); @@ -1346,12 +1349,16 @@ static int retz3fb_set_var(struct fb_var_screeninfo *var, int con, display->can_soft_blank = 1; display->inverse = z3fb_inverse; switch (display->var.bits_per_pixel) { -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 case 8: - display->dispsw = &fbcon_retz3_8; + if (var->accel_flags & FB_ACCELF_TEXT) { + display->dispsw = &fbcon_retz3_8; +#warning FIXME: We should reinit the graphics engine here + } else + display->dispsw = &fbcon_cfb8; break; #endif -#ifdef CONFIG_FBCON_CFB16 +#ifdef FBCON_HAS_CFB16 case 16: display->dispsw = &fbcon_cfb16; break; @@ -1448,7 +1455,7 @@ static int retz3fb_ioctl(struct inode *inode, struct file *file, 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 + retz3fb_pan_display, retz3fb_ioctl }; @@ -1478,9 +1485,8 @@ __initfunc(void retz3fb_setup(char *options, int *ints)) * Initialization */ -__initfunc(unsigned long retz3fb_init(unsigned long mem_start)) +__initfunc(void retz3fb_init(void)) { - int err; unsigned long board_addr, board_size; unsigned int key; const struct ConfigDev *cd; @@ -1488,7 +1494,7 @@ __initfunc(unsigned long retz3fb_init(unsigned long mem_start)) struct retz3fb_par par; if (!(key = zorro_find(ZORRO_PROD_MACROSYSTEMS_RETINA_Z3, 0, 0))) - return mem_start; + return; cd = zorro_get_board (key); zorro_config_board (key, 0); @@ -1496,7 +1502,7 @@ __initfunc(unsigned long retz3fb_init(unsigned long mem_start)) board_size = (unsigned long)cd->cd_BoardSize; z3_mem = kernel_map (board_addr, board_size, - KERNELMAP_NOCACHE_SER, &mem_start); + KERNELMAP_NOCACHE_SER, NULL); z3_regs = (char*) z3_mem; z3_fbmem = z3_mem + VIDEO_MEM_OFFSET; @@ -1518,10 +1524,6 @@ __initfunc(unsigned long retz3fb_init(unsigned long mem_start)) fb_info.updatevar = &z3fb_updatevar; fb_info.blank = &z3fb_blank; - err = register_framebuffer(&fb_info); - if (err < 0) - return mem_start; - if (z3fb_mode == -1) retz3fb_default = retz3fb_predefined[0].var; @@ -1535,13 +1537,14 @@ __initfunc(unsigned long retz3fb_init(unsigned long mem_start)) do_install_cmap(0, &fb_info); + if (register_framebuffer(&fb_info) < 0) + return; + 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; - - return mem_start; } @@ -1604,7 +1607,8 @@ __initfunc(static int get_video_mode(const char *name)) #ifdef MODULE int init_module(void) { - return(retz3fb_init(NULL)); + retz3fb_init(); + return 0; } void cleanup_module(void) @@ -1623,7 +1627,7 @@ void cleanup_module(void) * Text console acceleration */ -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 static void fbcon_retz3_8_bmove(struct display *p, int sy, int sx, int dy, int dx, int height, int width) { @@ -1670,6 +1674,7 @@ static void fbcon_retz3_8_clear(struct vc_data *conp, struct display *p, int 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 + fbcon_cfb8_putc, fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, + fbcon_cfb8_clear_margins, FONTWIDTH(8) }; #endif diff --git a/drivers/video/sbusfb.c b/drivers/video/sbusfb.c new file mode 100644 index 000000000..a771c37bd --- /dev/null +++ b/drivers/video/sbusfb.c @@ -0,0 +1,1128 @@ +/* + * linux/drivers/video/sbusfb.c -- SBUS or UPA based frame buffer device + * + * Copyright (C) 1998 Jakub Jelinek + * + * This driver is partly based on the Open Firmware console driver + * + * Copyright (C) 1997 Geert Uytterhoeven + * + * and SPARC console subsystem + * + * Copyright (C) 1995 Peter Zaitcev (zaitcev@lab.ipmce.su) + * Copyright (C) 1995-1997 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1995-1996 Miguel de Icaza (miguel@nuclecu.unam.mx) + * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) + * Copyright (C) 1996-1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) + * + * 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/console.h> +#include <linux/kd.h> +#include <linux/vt_kern.h> + +#include <asm/uaccess.h> + +#include "sbusfb.h" + + /* + * Interface used by the world + */ + +void sbusfb_init(void); +void sbusfb_setup(char *options, int *ints); + +static int currcon; +static int defx_margin = -1, defy_margin = -1; +static char fontname[40] __initdata = { 0 }; +static struct { + int depth; + int xres, yres; + int x_margin, y_margin; +} def_margins [] = { + { 8, 1280, 1024, 64, 80 }, + { 8, 1152, 1024, 64, 80 }, + { 8, 1152, 900, 64, 18 }, + { 8, 1024, 768, 0, 0 }, + { 8, 800, 600, 16, 12 }, + { 8, 640, 480, 0, 0 }, + { 1, 1152, 900, 8, 18 }, + { 0 }, +}; + +static int sbusfb_open(struct fb_info *info, int user); +static int sbusfb_release(struct fb_info *info, int user); +static int sbusfb_mmap(struct fb_info *info, struct file *file, + struct vm_area_struct *vma); +static int sbusfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int sbusfb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int sbusfb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int sbusfb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int sbusfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int sbusfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info); +static void sbusfb_cursor(struct display *p, int mode, int x, int y); +static void sbusfb_clear_margin(struct display *p, int s); +extern int io_remap_page_range(unsigned long from, unsigned long offset, + unsigned long size, pgprot_t prot, int space); + + + /* + * Interface to the low level console driver + */ + +static int sbusfbcon_switch(int con, struct fb_info *info); +static int sbusfbcon_updatevar(int con, struct fb_info *info); +static void sbusfbcon_blank(int blank, struct fb_info *info); + + + /* + * Internal routines + */ + +static int sbusfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, + u_int *transp, struct fb_info *info); +static int sbusfb_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 sbusfb_ops = { + sbusfb_open, sbusfb_release, sbusfb_get_fix, sbusfb_get_var, sbusfb_set_var, + sbusfb_get_cmap, sbusfb_set_cmap, sbusfb_pan_display, sbusfb_ioctl, sbusfb_mmap +}; + + + /* + * Open/Release the frame buffer device + */ + +static int sbusfb_open(struct fb_info *info, int user) +{ + struct fb_info_sbusfb *fb = sbusfbinfo(info); + + if (user) { + if (fb->open) return -EBUSY; + fb->mmaped = 0; + fb->open = 1; + fb->vtconsole = -1; + } else + fb->consolecnt++; + MOD_INC_USE_COUNT; + return 0; +} + +static int sbusfb_release(struct fb_info *info, int user) +{ + struct fb_info_sbusfb *fb = sbusfbinfo(info); + + if (user) { + if (fb->vtconsole != -1) { + vt_cons[fb->vtconsole]->vc_mode = KD_TEXT; + if (fb->mmaped) + sbusfb_clear_margin(&fb_display[fb->vtconsole], 0); + } + if (fb->reset) + fb->reset(fb); + fb->open = 0; + } else + fb->consolecnt--; + MOD_DEC_USE_COUNT; + return 0; +} + +static unsigned long sbusfb_mmapsize(struct fb_info_sbusfb *fb, long size) +{ + if (size == SBUS_MMAP_EMPTY) return 0; + if (size >= 0) return size; + return fb->type.fb_size * (-size); +} + +static int sbusfb_mmap(struct fb_info *info, struct file *file, + struct vm_area_struct *vma) +{ + struct fb_info_sbusfb *fb = sbusfbinfo(info); + unsigned int size, page, r, map_size; + unsigned long map_offset = 0; + int i; + + size = vma->vm_end - vma->vm_start; + if (vma->vm_offset & ~PAGE_MASK) + return -ENXIO; + + /* To stop the swapper from even considering these pages */ + vma->vm_flags |= (VM_SHM| VM_LOCKED); + +#ifdef __sparc_v9__ + /* Align it as much as desirable */ + { + int j, max = -1, alignment, s = 0; + + map_offset = vma->vm_offset+size; + for (i = 0; fb->mmap_map[i].size; i++) { + if (fb->mmap_map[i].voff < vma->vm_offset) + continue; + if (fb->mmap_map[i].voff >= map_offset) + break; + if (max < 0 || sbusfb_mmapsize(fb,fb->mmap_map[i].size) > s) { + max = i; + s = sbusfb_mmapsize(fb,fb->mmap_map[max].size); + } + } + if (max >= 0) { + j = s; + if (fb->mmap_map[max].voff + j > map_offset) + j = map_offset - fb->mmap_map[max].voff; + for (alignment = 0x400000; alignment > PAGE_SIZE; alignment >>= 3) + if (j >= alignment && !(fb->mmap_map[max].poff & (alignment - 1))) + break; + if (alignment > PAGE_SIZE) { + j = alignment; + alignment = j - ((vma->vm_start + fb->mmap_map[max].voff - vma->vm_offset) & (j - 1)); + if (alignment != j) { + struct vm_area_struct *vmm = find_vma(current->mm, vma->vm_start); + if (!vmm || vmm->vm_start >= vma->vm_end + alignment) { + vma->vm_start += alignment; + vma->vm_end += alignment; + } + } + } + } + } +#endif + + /* Each page, see which map applies */ + for (page = 0; page < size; ){ + map_size = 0; + for (i = 0; fb->mmap_map[i].size; i++) + if (fb->mmap_map[i].voff == vma->vm_offset+page) { + map_size = sbusfb_mmapsize(fb,fb->mmap_map[i].size); + map_offset = (fb->physbase + fb->mmap_map[i].poff) & PAGE_MASK; + break; + } + if (!map_size){ + page += PAGE_SIZE; + continue; + } + if (page + map_size > size) + map_size = size - page; + r = io_remap_page_range (vma->vm_start+page, map_offset, map_size, vma->vm_page_prot, fb->iospace); + if (r) + return -EAGAIN; + page += map_size; + } + + vma->vm_file = file; + file->f_count++; + vma->vm_flags |= VM_IO; + if (!fb->mmaped) { + int lastconsole = 0; + + if (info->display_fg) + lastconsole = info->display_fg->vc_num; + fb->mmaped = 1; + if (fb->consolecnt && fb_display[lastconsole].fb_info == info) { + fb->vtconsole = lastconsole; + vt_cons [lastconsole]->vc_mode = KD_GRAPHICS; + } else if (fb->unblank && !fb->blanked) + (*fb->unblank)(fb); + } + return 0; +} + +static void sbusfb_clear_margin(struct display *p, int s) +{ + struct fb_info_sbusfb *fb = sbusfbinfod(p); + + if (fb->fill) { + unsigned short rects [16]; + + rects [0] = 0; + rects [1] = 0; + rects [2] = fb->var.xres_virtual; + rects [3] = fb->y_margin; + rects [4] = 0; + rects [5] = fb->y_margin; + rects [6] = fb->x_margin; + rects [7] = fb->var.yres_virtual; + rects [8] = fb->var.xres_virtual - fb->x_margin; + rects [9] = fb->y_margin; + rects [10] = fb->var.xres_virtual; + rects [11] = fb->var.yres_virtual; + rects [12] = fb->x_margin; + rects [13] = fb->var.yres_virtual - fb->y_margin; + rects [14] = fb->var.xres_virtual - fb->x_margin; + rects [15] = fb->var.yres_virtual; + (*fb->fill)(fb, p, s, 4, rects); + } else { + unsigned char *fb_base = p->screen_base, *q; + int skip_bytes = fb->y_margin * fb->var.xres_virtual; + int scr_size = fb->var.xres_virtual * fb->var.yres_virtual; + int h, he, incr, size; + + he = fb->var.yres; + if (fb->var.bits_per_pixel == 1) { + fb_base -= (skip_bytes + fb->x_margin) / 8; + skip_bytes /= 8; + scr_size /= 8; + memset (fb_base, ~0, skip_bytes - fb->x_margin / 8); + memset (fb_base + scr_size - skip_bytes + fb->x_margin / 8, ~0, skip_bytes - fb->x_margin / 8); + incr = fb->var.xres_virtual / 8; + size = fb->x_margin / 8 * 2; + for (q = fb_base + skip_bytes - fb->x_margin / 8, h = 0; + h <= he; q += incr, h++) + memset (q, ~0, size); + } else { + fb_base -= (skip_bytes + fb->x_margin); + memset (fb_base, attr_bgcol(p,s), skip_bytes - fb->x_margin); + memset (fb_base + scr_size - skip_bytes + fb->x_margin, attr_bgcol(p,s), skip_bytes - fb->x_margin); + incr = fb->var.xres_virtual; + size = fb->x_margin * 2; + for (q = fb_base + skip_bytes - fb->x_margin, h = 0; + h <= he; q += incr, h++) + memset (q, attr_bgcol(p,s), size); + } + } + if (fb->switch_from_graph) + (*fb->switch_from_graph)(fb); +} + +static void sbusfb_disp_setup(struct display *p) +{ + struct fb_info_sbusfb *fb = sbusfbinfod(p); + + if (fb->setup) + fb->setup(p); + sbusfb_clear_margin(p, 0); +} + + /* + * Get the Fixed Part of the Display + */ + +static int sbusfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + struct fb_info_sbusfb *fb = sbusfbinfo(info); + + memcpy(fix, &fb->fix, sizeof(struct fb_fix_screeninfo)); + return 0; +} + + /* + * Get the User Defined Part of the Display + */ + +static int sbusfb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct fb_info_sbusfb *fb = sbusfbinfo(info); + + memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo)); + return 0; +} + + /* + * Set the User Defined Part of the Display + */ + +static int sbusfb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + return -EINVAL; +} + + /* + * Pan or Wrap the Display + * + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag + */ + +static int sbusfb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + if (var->xoffset || var->yoffset) + return -EINVAL; + else + return 0; +} + + /* + * Hardware cursor + */ + +static int sbus_hw_scursor (struct fbcursor *cursor, struct fb_info_sbusfb *fb) +{ + int op; + int i, bytes = 0; + struct fbcursor f; + char red[2], green[2], blue[2]; + + if (copy_from_user (&f, cursor, sizeof(struct fbcursor))) + return -EFAULT; + op = f.set; + if (op & FB_CUR_SETSHAPE){ + if ((u32) f.size.fbx > fb->cursor.hwsize.fbx) + return -EINVAL; + if ((u32) f.size.fby > fb->cursor.hwsize.fby) + return -EINVAL; + if (f.size.fbx > 32) + bytes = f.size.fby << 3; + else + bytes = f.size.fby << 2; + } + if (op & FB_CUR_SETCMAP){ + if (f.cmap.index || f.cmap.count != 2) + return -EINVAL; + if (copy_from_user (red, f.cmap.red, 2) || + copy_from_user (green, f.cmap.green, 2) || + copy_from_user (blue, f.cmap.blue, 2)) + return -EFAULT; + } + if (op & FB_CUR_SETCMAP) + (*fb->setcursormap) (fb, red, green, blue); + if (op & FB_CUR_SETSHAPE){ + u32 u; + + fb->cursor.size = f.size; + memset ((void *)&fb->cursor.bits, 0, sizeof (fb->cursor.bits)); + if (copy_from_user (fb->cursor.bits [0], f.mask, bytes) || + copy_from_user (fb->cursor.bits [1], f.image, bytes)) + return -EFAULT; + if (f.size.fbx <= 32) { + u = ~(0xffffffff >> f.size.fbx); + for (i = fb->cursor.size.fby - 1; i >= 0; i--) { + fb->cursor.bits [0][i] &= u; + fb->cursor.bits [1][i] &= fb->cursor.bits [0][i]; + } + } else { + u = ~(0xffffffff >> (f.size.fbx - 32)); + for (i = fb->cursor.size.fby - 1; i >= 0; i--) { + fb->cursor.bits [0][2*i+1] &= u; + fb->cursor.bits [1][2*i] &= fb->cursor.bits [0][2*i]; + fb->cursor.bits [1][2*i+1] &= fb->cursor.bits [0][2*i+1]; + } + } + (*fb->setcurshape) (fb); + } + if (op & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)){ + if (op & FB_CUR_SETCUR) + fb->cursor.enable = f.enable; + if (op & FB_CUR_SETPOS) + fb->cursor.cpos = f.pos; + if (op & FB_CUR_SETHOT) + fb->cursor.chot = f.hot; + (*fb->setcursor) (fb); + } + return 0; +} + +static unsigned char hw_cursor_cmap[2] = { 0, 0xff }; + +static void sbusfb_cursor(struct display *p, int mode, int x, int y) +{ + struct fb_info_sbusfb *fb = sbusfbinfod(p); + + switch (mode) { + case CM_ERASE: + fb->cursor.enable = 0; + (*fb->setcursor)(fb); + fb->hw_cursor_shown = 0; + break; + + case CM_MOVE: + case CM_DRAW: + if (!fb->hw_cursor_shown) { + fb->cursor.size.fbx = p->fontwidth; + fb->cursor.size.fby = p->fontheight; + fb->cursor.chot.fbx = 0; + fb->cursor.chot.fby = 0; + fb->cursor.enable = 1; + memset (fb->cursor.bits, 0, sizeof (fb->cursor.bits)); + fb->cursor.bits[0][p->fontheight - 2] = (0xffffffff << (32 - p->fontwidth)); + fb->cursor.bits[1][p->fontheight - 2] = (0xffffffff << (32 - p->fontwidth)); + fb->cursor.bits[0][p->fontheight - 1] = (0xffffffff << (32 - p->fontwidth)); + fb->cursor.bits[1][p->fontheight - 1] = (0xffffffff << (32 - p->fontwidth)); + (*fb->setcursormap) (fb, hw_cursor_cmap, hw_cursor_cmap, hw_cursor_cmap); + (*fb->setcurshape) (fb); + fb->hw_cursor_shown = 1; + } + if (p->fontwidthlog) + fb->cursor.cpos.fbx = (x << p->fontwidthlog) + fb->x_margin; + else + fb->cursor.cpos.fbx = (x * p->fontwidth) + fb->x_margin; + if (p->fontheightlog) + fb->cursor.cpos.fby = (y << p->fontheightlog) + fb->y_margin; + else + fb->cursor.cpos.fby = (y * p->fontheight) + fb->y_margin; + (*fb->setcursor)(fb); + break; + } +} + + /* + * Get the Colormap + */ + +static int sbusfb_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, sbusfb_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 sbusfb_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? */ + err = fb_set_cmap(cmap, &fb_display[con].var, kspc, sbusfb_setcolreg, info); + if (!err) { + struct fb_info_sbusfb *fb = sbusfbinfo(info); + + if (fb->loadcmap) + (*fb->loadcmap)(fb, cmap->start, cmap->len); + } + return err; + } else + fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); + return 0; +} + +static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info) +{ + struct fb_info_sbusfb *fb = sbusfbinfo(info); + int i; + int lastconsole; + + switch (cmd){ + case FBIOGTYPE: /* return frame buffer type */ + copy_to_user_ret((struct fbtype *)arg, &fb->type, sizeof(struct fbtype), -EFAULT); + break; + case FBIOGATTR: { + struct fbgattr *fba = (struct fbgattr *) arg; + + i = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct fbgattr)); + if (i) return i; + __put_user_ret(fb->emulations[0], &fba->real_type, -EFAULT); + __put_user_ret(0, &fba->owner, -EFAULT); + __copy_to_user_ret(&fba->fbtype, &fb->type, + sizeof(struct fbtype), -EFAULT); + __put_user_ret(0, &fba->sattr.flags, -EFAULT); + __put_user_ret(fb->type.fb_type, &fba->sattr.emu_type, -EFAULT); + __put_user_ret(-1, &fba->sattr.dev_specific[0], -EFAULT); + for (i = 0; i < 4; i++) + put_user_ret(fb->emulations[i], &fba->emu_types[i], -EFAULT); + break; + } + case FBIOSATTR: + i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbsattr)); + if (i) return i; + return -EINVAL; + case FBIOSVIDEO: + if (fb->consolecnt) { + lastconsole = info->display_fg->vc_num; + if (vt_cons[lastconsole]->vc_mode == KD_TEXT) + break; + } + get_user_ret(i, (int *)arg, -EFAULT); + if (i){ + if (!fb->blanked || !fb->unblank) + break; + if (fb->consolecnt || (fb->open && fb->mmaped)) + (*fb->unblank)(fb); + fb->blanked = 0; + } else { + if (fb->blanked || !fb->blank) + break; + (*fb->blank)(fb); + fb->blanked = 1; + } + break; + case FBIOGVIDEO: + put_user_ret(fb->blanked, (int *) arg, -EFAULT); + break; + case FBIOGETCMAP_SPARC: { + char *rp, *gp, *bp; + int end, count, index; + struct fbcmap *cmap; + + if (!fb->loadcmap) + return -EINVAL; + i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbcmap)); + if (i) return i; + cmap = (struct fbcmap *) arg; + __get_user_ret(count, &cmap->count, -EFAULT); + __get_user_ret(index, &cmap->index, -EFAULT); + if ((index < 0) || (index > 255)) + return -EINVAL; + if (index + count > 256) + count = 256 - index; + __get_user_ret(rp, &cmap->red, -EFAULT); + __get_user_ret(gp, &cmap->green, -EFAULT); + __get_user_ret(bp, &cmap->blue, -EFAULT); + if(verify_area (VERIFY_WRITE, rp, count)) return -EFAULT; + if(verify_area (VERIFY_WRITE, gp, count)) return -EFAULT; + if(verify_area (VERIFY_WRITE, bp, count)) return -EFAULT; + end = index + count; + for (i = index; i < end; i++){ + __put_user_ret(fb->color_map CM(i,0), rp, -EFAULT); + __put_user_ret(fb->color_map CM(i,1), gp, -EFAULT); + __put_user_ret(fb->color_map CM(i,2), bp, -EFAULT); + rp++; gp++; bp++; + } + (*fb->loadcmap)(fb, index, count); + break; + } + case FBIOPUTCMAP_SPARC: { /* load color map entries */ + char *rp, *gp, *bp; + int end, count, index; + struct fbcmap *cmap; + + if (!fb->loadcmap) + return -EINVAL; + i = verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbcmap)); + if (i) return i; + cmap = (struct fbcmap *) arg; + __get_user_ret(count, &cmap->count, -EFAULT); + __get_user_ret(index, &cmap->index, -EFAULT); + if ((index < 0) || (index > 255)) + return -EINVAL; + if (index + count > 256) + count = 256 - index; + __get_user_ret(rp, &cmap->red, -EFAULT); + __get_user_ret(gp, &cmap->green, -EFAULT); + __get_user_ret(bp, &cmap->blue, -EFAULT); + if(verify_area (VERIFY_READ, rp, count)) return -EFAULT; + if(verify_area (VERIFY_READ, gp, count)) return -EFAULT; + if(verify_area (VERIFY_READ, bp, count)) return -EFAULT; + + end = index + count; + for (i = index; i < end; i++){ + __get_user_ret(fb->color_map CM(i,0), rp, -EFAULT); + __get_user_ret(fb->color_map CM(i,1), gp, -EFAULT); + __get_user_ret(fb->color_map CM(i,2), bp, -EFAULT); + rp++; gp++; bp++; + } + (*fb->loadcmap)(fb, index, count); + break; + } + case FBIOGCURMAX: { + struct fbcurpos *p = (struct fbcurpos *) arg; + if (!fb->setcursor) return -EINVAL; + if(verify_area (VERIFY_WRITE, p, sizeof (struct fbcurpos))) + return -EFAULT; + __put_user_ret(fb->cursor.hwsize.fbx, &p->fbx, -EFAULT); + __put_user_ret(fb->cursor.hwsize.fby, &p->fby, -EFAULT); + break; + } + case FBIOSCURSOR: + if (!fb->setcursor) return -EINVAL; + if (fb->consolecnt) { + lastconsole = info->display_fg->vc_num; + if (vt_cons[lastconsole]->vc_mode == KD_TEXT) + return -EINVAL; /* Don't let graphics programs hide our nice text cursor */ + fb->hw_cursor_shown = 0; /* Forget state of our text cursor */ + } + return sbus_hw_scursor ((struct fbcursor *) arg, fb); + + case FBIOSCURPOS: + if (!fb->setcursor) return -EINVAL; + /* Don't let graphics programs move our nice text cursor */ + if (fb->consolecnt) { + lastconsole = info->display_fg->vc_num; + if (vt_cons[lastconsole]->vc_mode == KD_TEXT) + return -EINVAL; /* Don't let graphics programs move our nice text cursor */ + } + if (copy_from_user(&fb->cursor.cpos, (void *)arg, sizeof(struct fbcurpos))) + return -EFAULT; + (*fb->setcursor) (fb); + break; + default: + /* FIXME: Call here possible fb specific ioctl */ + return -EINVAL; + } + return 0; +} + + /* + * Setup: parse used options + */ + +__initfunc(void sbusfb_setup(char *options, int *ints)) +{ + char *p; + + for (p = options;;) { + if (!strncmp(p, "nomargins", 9)) { + defx_margin = 0; defy_margin = 0; + } else if (!strncmp(p, "margins=", 8)) { + int i, j; + char *q; + + i = simple_strtoul(p+8,&q,10); + if (i >= 0 && *q == 'x') { + j = simple_strtoul(q+1,&q,10); + if (j >= 0 && (*q == ' ' || !*q)) { + defx_margin = i; defy_margin = j; + } + } + } else if (!strncmp(p, "font=", 5)) { + int i; + + for (i = 0; i < sizeof(fontname) - 1; i++) + if (p[i+5] == ' ' || !p[i+5]) + break; + memcpy(fontname, p+5, i); + fontname[i] = 0; + } + while (*p && *p != ' ' && *p != ',') p++; + if (*p != ',') break; + p++; + } +} + +static int sbusfbcon_switch(int con, struct fb_info *info) +{ + int x_margin, y_margin; + struct fb_info_sbusfb *fb = sbusfbinfo(info); + int lastconsole; + + /* 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, sbusfb_getcolreg, info); + + lastconsole = info->display_fg->vc_num; + if (lastconsole != con && + (fb_display[lastconsole].fontwidth != fb_display[con].fontwidth || + fb_display[lastconsole].fontheight != fb_display[con].fontheight)) + fb->hw_cursor_shown = 0; + x_margin = (fb_display[con].var.xres_virtual - fb_display[con].var.xres) / 2; + y_margin = (fb_display[con].var.yres_virtual - fb_display[con].var.yres) / 2; + if (fb->margins) + fb->margins(fb, &fb_display[con], x_margin, y_margin); + if (fb->x_margin != x_margin || fb->y_margin != y_margin) { + fb->x_margin = x_margin; fb->y_margin = y_margin; + sbusfb_clear_margin(&fb_display[con], 0); + } + currcon = con; + /* Install new colormap */ + do_install_cmap(con, info); + return 0; +} + + /* + * Update the `var' structure (called by fbcon.c) + */ + +static int sbusfbcon_updatevar(int con, struct fb_info *info) +{ + /* Nothing */ + return 0; +} + + /* + * Blank the display. + */ + +static void sbusfbcon_blank(int blank, struct fb_info *info) +{ + struct fb_info_sbusfb *fb = sbusfbinfo(info); + + if (blank && fb->blank) + return fb->blank(fb); + else if (!blank && fb->unblank) + return fb->unblank(fb); +} + + /* + * Read a single color register and split it into + * colors/transparent. Return != 0 for invalid regno. + */ + +static int sbusfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, + u_int *transp, struct fb_info *info) +{ + struct fb_info_sbusfb *fb = sbusfbinfo(info); + + if (!fb->color_map || regno > 255) + return 1; + *red = fb->color_map CM(regno, 0); + *green = fb->color_map CM(regno, 1); + *blue = fb->color_map CM(regno, 2); + 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 sbusfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + struct fb_info_sbusfb *fb = sbusfbinfo(info); + + if (!fb->color_map || regno > 255) + return 1; + fb->color_map CM(regno, 0) = red; + fb->color_map CM(regno, 1) = green; + fb->color_map CM(regno, 2) = blue; + return 0; +} + + +static void do_install_cmap(int con, struct fb_info *info) +{ + struct fb_info_sbusfb *fb = sbusfbinfo(info); + + if (con != currcon) + return; + if (fb_display[con].cmap.len) + fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1, + sbusfb_setcolreg, info); + else + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), + &fb_display[con].var, 1, sbusfb_setcolreg, info); + if (fb->loadcmap) + (*fb->loadcmap)(fb, 0, 256); +} + +static int sbusfb_set_font(struct display *p, int width, int height) +{ + int margin; + int w = p->var.xres_virtual, h = p->var.yres_virtual; + int depth = p->var.bits_per_pixel; + struct fb_info_sbusfb *fb = sbusfbinfod(p); + int x_margin, y_margin; + + if (depth > 8) depth = 8; + x_margin = 0; + y_margin = 0; + if (defx_margin < 0 || defy_margin < 0) { + for (margin = 0; def_margins[margin].depth; margin++) + if (w == def_margins[margin].xres && + h == def_margins[margin].yres && + depth == def_margins[margin].depth) { + x_margin = def_margins[margin].x_margin; + y_margin = def_margins[margin].y_margin; + break; + } + } else { + x_margin = defx_margin; + y_margin = defy_margin; + } + x_margin += ((w - 2*x_margin) % width) / 2; + y_margin += ((h - 2*y_margin) % height) / 2; + + p->var.xres = w - 2*x_margin; + p->var.yres = h - 2*y_margin; + + fb->hw_cursor_shown = 0; + + if (fb->margins) + fb->margins(fb, p, x_margin, y_margin); + if (fb->x_margin != x_margin || fb->y_margin != y_margin) { + fb->x_margin = x_margin; fb->y_margin = y_margin; + sbusfb_clear_margin(p, 0); + } + + return 1; +} + +void sbusfb_palette(int enter) +{ + int i; + struct display *p; + + for (i = 0; i < MAX_NR_CONSOLES; i++) { + p = &fb_display[i]; + if (p->dispsw && p->dispsw->setup == sbusfb_disp_setup && + p->fb_info->display_fg && + p->fb_info->display_fg->vc_num == i) { + struct fb_info_sbusfb *fb = sbusfbinfod(p); + + if (fb->restore_palette) { + if (enter) + fb->restore_palette(fb); + else if (vt_cons[i]->vc_mode != KD_GRAPHICS) + vc_cons[i].d->vc_sw->con_set_palette(vc_cons[i].d, color_table); + } + } + } +} + + /* + * Initialisation + */ + +extern void (*prom_palette)(int); + +__initfunc(static void sbusfb_init_fb(int node, int parent, int fbtype, + struct linux_sbus_device *sbdp)) +{ + struct fb_fix_screeninfo *fix; + struct fb_var_screeninfo *var; + struct display *disp; + struct fb_info_sbusfb *fb; + struct fbtype *type; + int linebytes, w, h, depth; + char *p = NULL; + int margin; + + fb = kmalloc(sizeof(struct fb_info_sbusfb), GFP_ATOMIC); + if (!fb) { + prom_printf("Could not allocate sbusfb structure\n"); + return; + } + + if (!prom_palette) + prom_palette = sbusfb_palette; + + memset(fb, 0, sizeof(struct fb_info_sbusfb)); + fix = &fb->fix; + var = &fb->var; + disp = &fb->disp; + type = &fb->type; + + fb->prom_node = node; + fb->prom_parent = parent; + fb->sbdp = sbdp; + if (sbdp) + fb->iospace = sbdp->reg_addrs[0].which_io; + + type->fb_type = fbtype; + memset(&fb->emulations, 0xff, sizeof(fb->emulations)); + fb->emulations[0] = fbtype; + +#ifndef __sparc_v9__ + disp->screen_base = (unsigned char *)prom_getintdefault(node, "address", 0); +#endif + + type->fb_height = h = prom_getintdefault(node, "height", 900); + type->fb_width = w = prom_getintdefault(node, "width", 1152); +sizechange: + type->fb_depth = depth = (fbtype == FBTYPE_SUN2BW) ? 1 : 8; + linebytes = prom_getintdefault(node, "linebytes", w * depth / 8); + type->fb_size = PAGE_ALIGN((linebytes) * h); + + if (defx_margin < 0 || defy_margin < 0) { + for (margin = 0; def_margins[margin].depth; margin++) + if (w == def_margins[margin].xres && + h == def_margins[margin].yres && + depth == def_margins[margin].depth) { + fb->x_margin = def_margins[margin].x_margin; + fb->y_margin = def_margins[margin].y_margin; + break; + } + } else { + fb->x_margin = defx_margin; + fb->y_margin = defy_margin; + } + fb->x_margin += ((w - 2*fb->x_margin) & 7) / 2; + fb->y_margin += ((h - 2*fb->y_margin) & 15) / 2; + + var->xres_virtual = w; + var->yres_virtual = h; + var->xres = w - 2*fb->x_margin; + var->yres = h - 2*fb->y_margin; + + var->bits_per_pixel = depth; + var->height = var->width = -1; + var->pixclock = 10000; + var->vmode = FB_VMODE_NONINTERLACED; + var->red.length = var->green.length = var->blue.length = 8; + + fix->line_length = linebytes; + fix->smem_len = type->fb_size; + fix->type = FB_TYPE_PACKED_PIXELS; + fix->visual = FB_VISUAL_PSEUDOCOLOR; + + fb->info.node = -1; + fb->info.fbops = &sbusfb_ops; + fb->info.disp = disp; + strcpy(fb->info.fontname, fontname); + fb->info.changevar = NULL; + fb->info.switch_con = &sbusfbcon_switch; + fb->info.updatevar = &sbusfbcon_updatevar; + fb->info.blank = &sbusfbcon_blank; + + fb->cursor.hwsize.fbx = 32; + fb->cursor.hwsize.fby = 32; + + if (depth > 1 && !fb->color_map) + fb->color_map = kmalloc(256 * 3, GFP_ATOMIC); + + switch(fbtype) { +#ifdef CONFIG_FB_CREATOR + case FBTYPE_CREATOR: + p = creatorfb_init(fb); break; +#endif +#ifdef CONFIG_FB_CGSIX + case FBTYPE_SUNFAST_COLOR: + p = cgsixfb_init(fb); break; +#endif +#ifdef CONFIG_FB_CGTHREE + case FBTYPE_SUN3COLOR: + p = cgthreefb_init(fb); break; +#endif +#ifdef CONFIG_FB_TCX + case FBTYPE_TCXCOLOR: + p = tcxfb_init(fb); break; +#endif +#ifdef CONFIG_FB_LEO + case FBTYPE_SUNLEO: + p = leofb_init(fb); break; +#endif +#ifdef CONFIG_FB_BWTWO + case FBTYPE_SUN2BW: + p = bwtwofb_init(fb); break; +#endif +#ifdef CONFIG_FB_CGFOURTEEN + case FBTYPE_MDICOLOR: + p = cgfourteenfb_init(fb); break; +#endif + } + + if (!p) { + kfree(fb); + return; + } + + if (p == SBUSFBINIT_SIZECHANGE) + goto sizechange; + + disp->dispsw = &fb->dispsw; + if (fb->setcursor) + fb->dispsw.cursor = sbusfb_cursor; + fb->dispsw.set_font = sbusfb_set_font; + fb->setup = fb->dispsw.setup; + fb->dispsw.setup = sbusfb_disp_setup; + fb->dispsw.clear_margins = NULL; + + disp->var = *var; + disp->visual = fix->visual; + disp->type = fix->type; + disp->type_aux = fix->type_aux; + disp->line_length = fix->line_length; + + if (fb->blank) + disp->can_soft_blank = 1; + + sbusfb_set_var(var, -1, &fb->info); + + if (register_framebuffer(&fb->info) < 0) { + kfree(fb); + return; + } + printk("fb%d: %s\n", GET_FB_IDX(fb->info.node), p); +} + +static inline int known_card(char *name) +{ + char *p; + for (p = name; *p && *p != ','; p++); + if (*p == ',') name = p + 1; + if (!strcmp(name, "cgsix") || !strcmp(name, "cgthree+")) + return FBTYPE_SUNFAST_COLOR; + if (!strcmp(name, "cgthree") || !strcmp(name, "cgRDI")) + return FBTYPE_SUN3COLOR; + if (!strcmp(name, "cgfourteen")) + return FBTYPE_MDICOLOR; + if (!strcmp(name, "leo")) + return FBTYPE_SUNLEO; + if (!strcmp(name, "bwtwo")) + return FBTYPE_SUN2BW; + if (!strcmp(name, "tcx")) + return FBTYPE_TCXCOLOR; + return FBTYPE_NOTYPE; +} + +__initfunc(void sbusfb_init(void)) +{ + int type; + struct linux_sbus_device *sbdp; + struct linux_sbus *sbus; + char prom_name[40]; + extern int con_is_present(void); + + if (!con_is_present()) return; + +#ifdef CONFIG_FB_CREATOR + { + int root, node; + root = prom_getchild(prom_root_node); + for (node = prom_searchsiblings(root, "SUNW,ffb"); node; + node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb")) { + sbusfb_init_fb(node, prom_root_node, FBTYPE_CREATOR, NULL); + } + } +#endif +#ifdef CONFIG_SUN4 + sbusfb_init_fb(0, 0, FBTYPE_SUN2BW, NULL); +#endif +#if defined(CONFIG_FB_CGFOURTEEN) && !defined(__sparc_v9__) + { + int root, node; + root = prom_getchild(prom_root_node); + root = prom_searchsiblings(root, "obio"); + if (root && + (node = prom_searchsiblings(prom_getchild(root), "cgfourteen"))) { + sbusfb_init_fb(node, root, FBTYPE_MDICOLOR, NULL); + } + } +#endif + if (!SBus_chain) return; + for_all_sbusdev(sbdp, sbus) { + type = known_card(sbdp->prom_name); + if (type == FBTYPE_NOTYPE) continue; + if (prom_getproperty(sbdp->prom_node, "emulation", prom_name, sizeof(prom_name)) > 0) { + type = known_card(prom_name); + if (type == FBTYPE_NOTYPE) type = known_card(sbdp->prom_name); + } + prom_apply_sbus_ranges(sbdp->my_bus, &sbdp->reg_addrs[0], + sbdp->num_registers, sbdp); + sbusfb_init_fb(sbdp->prom_node, sbdp->my_bus->prom_node, type, sbdp); + } +} diff --git a/drivers/video/sbusfb.h b/drivers/video/sbusfb.h new file mode 100644 index 000000000..f65ca1d71 --- /dev/null +++ b/drivers/video/sbusfb.h @@ -0,0 +1,116 @@ +#include <asm/sbus.h> +#include <asm/oplib.h> +#include <asm/fbio.h> + +#include "fbcon.h" + +struct bt_regs { + volatile unsigned int addr; /* address register */ + volatile unsigned int color_map; /* color map */ + volatile unsigned int control; /* control register */ + volatile unsigned int cursor; /* cursor map register */ +}; + +struct fb_info_creator { + struct ffb_fbc *fbc; + struct ffb_dac *dac; + int dac_rev; + int xy_margin; +}; +struct fb_info_cgsix { + struct bt_regs *bt; + struct cg6_fbc *fbc; + struct cg6_thc *thc; + struct cg6_tec *tec; + volatile u32 *fhc; +}; +struct fb_info_bwtwo { + struct bw2_regs *regs; +}; +struct fb_info_cgthree { + struct cg3_regs *regs; +}; +struct fb_info_tcx { + struct bt_regs *bt; + struct tcx_thc *thc; + struct tcx_tec *tec; + u32 *cplane; +}; + +struct cg_cursor { + short enable; /* cursor is enabled */ + struct fbcurpos cpos; /* position */ + struct fbcurpos chot; /* hot-spot */ + struct fbcurpos size; /* size of mask & image fields */ + struct fbcurpos hwsize; /* hw max size */ + int bits[2][128]; /* space for mask & image bits */ + char color [6]; /* cursor colors */ +}; + +struct sbus_mmap_map { + unsigned long voff; + unsigned long poff; + unsigned long size; +}; + +#define SBUS_MMAP_FBSIZE(n) (-n) +#define SBUS_MMAP_EMPTY 0x80000000 + +struct fb_info_sbusfb { + struct fb_info info; + struct fb_fix_screeninfo fix; + struct fb_var_screeninfo var; + struct display disp; + struct display_switch dispsw; + struct fbtype type; + struct linux_sbus_device *sbdp; + int prom_node, prom_parent; + union { + struct fb_info_creator ffb; + struct fb_info_cgsix cg6; + struct fb_info_bwtwo bw2; + struct fb_info_cgthree cg3; + struct fb_info_tcx tcx; + } s; + unsigned char *color_map; + struct cg_cursor cursor; + unsigned char hw_cursor_shown; + unsigned char open; + unsigned char mmaped; + unsigned char blanked; + int x_margin; + int y_margin; + int vtconsole; + int consolecnt; + int emulations[4]; + struct sbus_mmap_map *mmap_map; + unsigned long physbase; + int iospace; + /* Methods */ + void (*setup)(struct display *); + void (*setcursor)(struct fb_info_sbusfb *); + void (*setcurshape)(struct fb_info_sbusfb *); + void (*setcursormap)(struct fb_info_sbusfb *, unsigned char *, unsigned char *, unsigned char *); + void (*loadcmap)(struct fb_info_sbusfb *, int, int); + void (*blank)(struct fb_info_sbusfb *); + void (*unblank)(struct fb_info_sbusfb *); + void (*margins)(struct fb_info_sbusfb *, struct display *, int, int); + void (*reset)(struct fb_info_sbusfb *); + void (*fill)(struct fb_info_sbusfb *, struct display *, int, int, unsigned short *); + void (*switch_from_graph)(struct fb_info_sbusfb *); + void (*restore_palette)(struct fb_info_sbusfb *); +}; + +extern char *creatorfb_init(struct fb_info_sbusfb *); +extern char *cgsixfb_init(struct fb_info_sbusfb *); +extern char *cgthreefb_init(struct fb_info_sbusfb *); +extern char *tcxfb_init(struct fb_info_sbusfb *); +extern char *leofb_init(struct fb_info_sbusfb *); +extern char *bwtwofb_init(struct fb_info_sbusfb *); +extern char *cgfourteenfb_init(struct fb_info_sbusfb *); + +#define sbusfbinfod(disp) ((struct fb_info_sbusfb *)(disp->fb_info)) +#define sbusfbinfo(info) ((struct fb_info_sbusfb *)(info)) +#define CM(i, j) [3*(i)+(j)] + +#define SBUSFBINIT_SIZECHANGE ((char *)-1) diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index e2c553392..1831e6b33 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c @@ -8,7 +8,6 @@ * for more details. */ -#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -60,8 +59,7 @@ struct xxxfb_par { /* * 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). + * or allocate them dynamically (using kmalloc()). */ static struct xxxfb_info fb_info; @@ -245,15 +243,15 @@ static struct display_switch *xxx_get_dispsw(const void *par, * 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 +#ifdef FBCON_HAS_CFB8 if (is_cfb8) return &fbcon_cfb8; #endif -#ifdef CONFIG_FBCON_CFB16 +#ifdef FBCON_HAS_CFB16 if (is_cfb16) return &fbcon_cfb16; #endif -#ifdef CONFIG_FBCON_CFB32 +#ifdef FBCON_HAS_CFB32 if (is_cfb32) return &fbcon_cfb32; #endif @@ -271,16 +269,15 @@ struct fbgen_hwswitch xxx_switch = { -/* ------------ Hardware Independant Functions ------------ */ +/* ------------ Hardware Independent Functions ------------ */ /* * Initialization */ -__initfunc(unsigned long xxxfb_init(unsigned long mem_start)) +__initfunc(void xxxfb_init(void)) { - int err; struct fb_var_screeninfo var; fb_info.fbhw = &xxx_switch; @@ -296,18 +293,15 @@ __initfunc(unsigned long xxxfb_init(unsigned long mem_start)) /* 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); + if (register_framebuffer(&fb_info.gen.info) < 0) + return; 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; } @@ -344,14 +338,14 @@ __initfunc(void xxxfb_setup(char *options, int *ints)) * Frame buffer operations */ -static int xxxfb_open(const struct fb_info *info) +static int xxxfb_open(const struct fb_info *info, int user) { /* Nothing, only a usage count for the moment */ MOD_INC_USE_COUNT; return 0; } -static int xxxfb_release(const struct fb_info *info) +static int xxxfb_release(const struct fb_info *info, int user) { MOD_DEC_USE_COUNT; return 0; @@ -365,7 +359,7 @@ static int xxxfb_release(const struct fb_info *info) 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 + fbgen_get_cmap, fbgen_set_cmap, fbgen_pan_display, fbgen_ioctl }; @@ -379,7 +373,8 @@ static struct fb_ops xxxfb_ops = { #ifdef MODULE int init_module(void) { - return xxxfb_init(NULL); + xxxfb_init(); + return 0; } void cleanup_module(void) diff --git a/drivers/video/tcxfb.c b/drivers/video/tcxfb.c new file mode 100644 index 000000000..181b6c53e --- /dev/null +++ b/drivers/video/tcxfb.c @@ -0,0 +1,290 @@ +/* $Id: tcxfb.c,v 1.1 1998/07/21 14:50:44 jj Exp $ + * tcxfb.c: TCX 24/8bit frame buffer driver + * + * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) + * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) + * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) + */ + +#include <linux/module.h> +#include <linux/sched.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 <linux/selection.h> + +#include "sbusfb.h" +#include <asm/io.h> + +#include "fbcon-cfb8.h" + +/* THC definitions */ +#define TCX_THC_MISC_REV_SHIFT 16 +#define TCX_THC_MISC_REV_MASK 15 +#define TCX_THC_MISC_VSYNC_DIS (1 << 25) +#define TCX_THC_MISC_HSYNC_DIS (1 << 24) +#define TCX_THC_MISC_RESET (1 << 12) +#define TCX_THC_MISC_VIDEO (1 << 10) +#define TCX_THC_MISC_SYNC (1 << 9) +#define TCX_THC_MISC_VSYNC (1 << 8) +#define TCX_THC_MISC_SYNC_ENAB (1 << 7) +#define TCX_THC_MISC_CURS_RES (1 << 6) +#define TCX_THC_MISC_INT_ENAB (1 << 5) +#define TCX_THC_MISC_INT (1 << 4) +#define TCX_THC_MISC_INIT 0x9f +#define TCX_THC_REV_REV_SHIFT 20 +#define TCX_THC_REV_REV_MASK 15 +#define TCX_THC_REV_MINREV_SHIFT 28 +#define TCX_THC_REV_MINREV_MASK 15 + +/* The contents are unknown */ +struct tcx_tec { + volatile u32 tec_matrix; + volatile u32 tec_clip; + volatile u32 tec_vdc; +}; + +struct tcx_thc { + volatile u32 thc_rev; + u32 thc_pad0[511]; + volatile u32 thc_hs; /* hsync timing */ + volatile u32 thc_hsdvs; + volatile u32 thc_hd; + volatile u32 thc_vs; /* vsync timing */ + volatile u32 thc_vd; + volatile u32 thc_refresh; + volatile u32 thc_misc; + u32 thc_pad1[56]; + volatile u32 thc_cursxy; /* cursor x,y position (16 bits each) */ + volatile u32 thc_cursmask[32]; /* cursor mask bits */ + volatile u32 thc_cursbits[32]; /* what to show where mask enabled */ +}; + +static struct sbus_mmap_map tcx_mmap_map[] = { + { TCX_RAM8BIT, 0, SBUS_MMAP_FBSIZE(1) }, + { TCX_RAM24BIT, 0, SBUS_MMAP_FBSIZE(4) }, + { TCX_UNK3, 0, SBUS_MMAP_FBSIZE(8) }, + { TCX_UNK4, 0, SBUS_MMAP_FBSIZE(8) }, + { TCX_CONTROLPLANE, 0, SBUS_MMAP_FBSIZE(4) }, + { TCX_UNK6, 0, SBUS_MMAP_FBSIZE(8) }, + { TCX_UNK7, 0, SBUS_MMAP_FBSIZE(8) }, + { TCX_TEC, 0, PAGE_SIZE }, + { TCX_BTREGS, 0, PAGE_SIZE }, + { TCX_THC, 0, PAGE_SIZE }, + { TCX_DHC, 0, PAGE_SIZE }, + { TCX_ALT, 0, PAGE_SIZE }, + { TCX_UNK2, 0, 0x20000 }, + { 0, 0, 0 } +}; + +static void tcx_set_control_plane (struct fb_info_sbusfb *fb) +{ + u32 *p, *pend; + + p = fb->s.tcx.cplane; + if (!p) return; + for (pend = p + fb->type.fb_size; p < pend; p++) + *p &= 0xffffff; +} + +static void tcx_switch_from_graph (struct fb_info_sbusfb *fb) +{ + /* Reset control plane to 8bit mode if necessary */ + if (fb->open && fb->mmaped) + tcx_set_control_plane (fb); +} + +static void tcx_loadcmap (struct fb_info_sbusfb *fb, int index, int count) +{ + struct bt_regs *bt = fb->s.tcx.bt; + int i; + + bt->addr = index << 24; + for (i = index; count--; i++){ + bt->color_map = fb->color_map CM(i,0) << 24; + bt->color_map = fb->color_map CM(i,1) << 24; + bt->color_map = fb->color_map CM(i,2) << 24; + } +} + +static void tcx_restore_palette (struct fb_info_sbusfb *fb) +{ + struct bt_regs *bt = fb->s.tcx.bt; + + bt->addr = 0; + bt->color_map = 0xffffffff; + bt->color_map = 0xffffffff; + bt->color_map = 0xffffffff; +} + +static void tcx_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) +{ + struct bt_regs *bt = fb->s.tcx.bt; + + /* Note the 2 << 24 is different from cg6's 1 << 24 */ + bt->addr = 2 << 24; + bt->cursor = red[0] << 24; + bt->cursor = green[0] << 24; + bt->cursor = blue[0] << 24; + bt->addr = 3 << 24; + bt->cursor = red[1] << 24; + bt->cursor = green[1] << 24; + bt->cursor = blue[1] << 24; + bt->addr = 0; +} + +/* Set cursor shape */ +static void tcx_setcurshape (struct fb_info_sbusfb *fb) +{ + struct tcx_thc *thc = fb->s.tcx.thc; + int i; + + for (i = 0; i < 32; i++){ + thc->thc_cursmask [i] = fb->cursor.bits[0][i]; + thc->thc_cursbits [i] = fb->cursor.bits[1][i]; + } +} + +/* Load cursor information */ +static void tcx_setcursor (struct fb_info_sbusfb *fb) +{ + unsigned int v; + struct cg_cursor *c = &fb->cursor; + + if (c->enable) + v = ((c->cpos.fbx - c->chot.fbx) << 16) + |((c->cpos.fby - c->chot.fby) & 0xffff); + else + /* Magic constant to turn off the cursor */ + v = ((65536-32) << 16) | (65536-32); + fb->s.tcx.thc->thc_cursxy = v; +} + +static void tcx_blank (struct fb_info_sbusfb *fb) +{ + fb->s.tcx.thc->thc_misc &= ~TCX_THC_MISC_VIDEO; + /* This should put us in power-save */ + fb->s.tcx.thc->thc_misc |= TCX_THC_MISC_VSYNC_DIS; + fb->s.tcx.thc->thc_misc |= TCX_THC_MISC_HSYNC_DIS; +} + +static void tcx_unblank (struct fb_info_sbusfb *fb) +{ + fb->s.tcx.thc->thc_misc &= ~TCX_THC_MISC_VSYNC_DIS; + fb->s.tcx.thc->thc_misc &= ~TCX_THC_MISC_HSYNC_DIS; + fb->s.tcx.thc->thc_misc |= TCX_THC_MISC_VIDEO; +} + +static void tcx_reset (struct fb_info_sbusfb *fb) +{ + if (fb->open && fb->mmaped) + tcx_set_control_plane(fb); + + /* Turn off stuff in the Transform Engine. */ + fb->s.tcx.tec->tec_matrix = 0; + fb->s.tcx.tec->tec_clip = 0; + fb->s.tcx.tec->tec_vdc = 0; + + /* Enable cursor in Brooktree DAC. */ + fb->s.tcx.bt->addr = 0x06 << 24; + fb->s.tcx.bt->control |= 0x03 << 24; +} + +static void tcx_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) +{ + p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin); +} + +static char idstring[60] __initdata = { 0 }; + +__initfunc(char *tcxfb_init(struct fb_info_sbusfb *fb)) +{ + struct fb_fix_screeninfo *fix = &fb->fix; + struct display *disp = &fb->disp; + struct fbtype *type = &fb->type; + unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; + int lowdepth; + +#ifndef FBCON_HAS_CFB8 + return NULL; +#endif + + lowdepth = prom_getbool (fb->prom_node, "tcx-8-bit"); + + if (lowdepth) { + strcpy(fb->info.modename, "TCX8"); + strcpy(fix->id, "TCX8"); + } else { + strcpy(fb->info.modename, "TCX24"); + strcpy(fix->id, "TCX24"); + } + fix->line_length = fb->var.xres_virtual; + + disp->scrollmode = SCROLL_YREDRAW; + if (!disp->screen_base) + disp->screen_base = (char *)sparc_alloc_io(phys, 0, + type->fb_size, "tcx_ram", fb->iospace, 0); + disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; + fb->s.tcx.tec = (struct tcx_tec *)sparc_alloc_io(fb->sbdp->reg_addrs[7].phys_addr, 0, + sizeof(struct tcx_tec), "tcx_tec", fb->iospace, 0); + fb->s.tcx.thc = (struct tcx_thc *)sparc_alloc_io(fb->sbdp->reg_addrs[9].phys_addr, 0, + sizeof(struct tcx_thc), "tcx_thc", fb->iospace, 0); + fb->s.tcx.bt = (struct bt_regs *)sparc_alloc_io(fb->sbdp->reg_addrs[8].phys_addr, 0, + sizeof(struct bt_regs), "tcx_dac", fb->iospace, 0); + if (!lowdepth) { + fb->s.tcx.cplane = (u32 *)sparc_alloc_io(fb->sbdp->reg_addrs[4].phys_addr, 0, + type->fb_size*4, "tcx_cplane", fb->iospace, 0); + type->fb_depth = 24; + fb->switch_from_graph = tcx_switch_from_graph; + } else { + /* As there can be one tcx in a machine only, we can write directly into + tcx_mmap_map */ + tcx_mmap_map[1].size = SBUS_MMAP_EMPTY; + tcx_mmap_map[4].size = SBUS_MMAP_EMPTY; + tcx_mmap_map[5].size = SBUS_MMAP_EMPTY; + tcx_mmap_map[6].size = SBUS_MMAP_EMPTY; + } + fb->dispsw = fbcon_cfb8; + + fb->margins = tcx_margins; + fb->loadcmap = tcx_loadcmap; + if (prom_getbool (fb->prom_node, "hw-cursor")) { + fb->setcursor = tcx_setcursor; + fb->setcursormap = tcx_setcursormap; + fb->setcurshape = tcx_setcurshape; + } + fb->restore_palette = tcx_restore_palette; + fb->blank = tcx_blank; + fb->unblank = tcx_unblank; + fb->reset = tcx_reset; + + fb->physbase = 0; + fb->mmap_map = tcx_mmap_map; + + /* Initialize Brooktree DAC */ + fb->s.tcx.bt->addr = 0x04 << 24; /* color planes */ + fb->s.tcx.bt->control = 0xff << 24; + fb->s.tcx.bt->addr = 0x05 << 24; + fb->s.tcx.bt->control = 0x00 << 24; + fb->s.tcx.bt->addr = 0x06 << 24; /* overlay plane */ + fb->s.tcx.bt->control = 0x73 << 24; + fb->s.tcx.bt->addr = 0x07 << 24; + fb->s.tcx.bt->control = 0x00 << 24; + + sprintf(idstring, "tcx at %x.%08lx Rev %d.%d %s", fb->iospace, phys, + (fb->s.tcx.thc->thc_rev >> TCX_THC_REV_REV_SHIFT) & TCX_THC_REV_REV_MASK, + (fb->s.tcx.thc->thc_rev >> TCX_THC_REV_MINREV_SHIFT) & TCX_THC_REV_MINREV_MASK, + lowdepth ? "8-bit only" : "24-bit depth"); + + tcx_reset(fb); + + return idstring; +} diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 7e74f7449..d15d87a6b 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -21,8 +21,6 @@ * * KNOWN PROBLEMS/TO DO ==================================================== */ - -#include <linux/config.h> #include <linux/module.h> #include <linux/sched.h> #include <linux/kernel.h> @@ -40,6 +38,7 @@ #include <linux/selection.h> #include <asm/io.h> +#include "fbcon.h" #include "fbcon-cfb8.h" #include "fbcon-cfb32.h" @@ -252,8 +251,8 @@ static struct fb_var_screeninfo fb_var = { 0, }; * Interface used by the world */ -static int tgafb_open(struct fb_info *info); -static int tgafb_release(struct fb_info *info); +static int tgafb_open(struct fb_info *info, int user); +static int tgafb_release(struct fb_info *info, int user); 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, @@ -274,7 +273,7 @@ static int tgafb_ioctl(struct inode *inode, struct file *file, u_int cmd, * Interface to the low level console driver */ -unsigned long tgafb_init(unsigned long mem_start); +void tgafb_init(void); 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); @@ -296,7 +295,7 @@ 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, NULL, tgafb_ioctl + tgafb_get_cmap, tgafb_set_cmap, tgafb_pan_display, tgafb_ioctl }; @@ -304,7 +303,7 @@ static struct fb_ops tgafb_ops = { * Open/Release the frame buffer device */ -static int tgafb_open(struct fb_info *info) +static int tgafb_open(struct fb_info *info, int user) { /* * Nothing, only a usage count for the moment @@ -314,7 +313,7 @@ static int tgafb_open(struct fb_info *info) return(0); } -static int tgafb_release(struct fb_info *info) +static int tgafb_release(struct fb_info *info, int user) { MOD_DEC_USE_COUNT; return(0); @@ -453,15 +452,15 @@ static int tgafb_ioctl(struct inode *inode, struct file *file, u_int cmd, * Initialisation */ -__initfunc(unsigned long tgafb_init(unsigned long mem_start)) +__initfunc(void tgafb_init(void)) { - int i, j, temp, err; + int i, j, temp; unsigned char *cbp; struct pci_dev *pdev; pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL); if (!pdev) - return mem_start; + return; 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); @@ -480,7 +479,7 @@ __initfunc(unsigned long tgafb_init(unsigned long mem_start)) break; default: printk("TGA type (0x%x) unrecognized!\n", tga_type); - return mem_start; + return; } tga_regs_base = ((unsigned long)tga_mem_base + TGA_REGS_OFFSET); @@ -689,12 +688,13 @@ __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 + LCA_DENSE_MEM); + fb_fix.smem_start = (char *)__pa(tga_fb_base + dense_mem(tga_fb_base)); fb_fix.smem_len = fb_fix.line_length*fb_var.yres; fb_fix.type = FB_TYPE_PACKED_PIXELS; fb_fix.type_aux = 0; - fb_fix.mmio_start = (unsigned char *)tga_regs_base; + fb_fix.mmio_start = (char *)__pa(tga_regs_base); fb_fix.mmio_len = 0x1000; /* Is this sufficient? */ + fb_fix.accel = FB_ACCEL_DEC_TGA; fb_var.xoffset = fb_var.yoffset = 0; fb_var.grayscale = 0; @@ -714,7 +714,7 @@ __initfunc(unsigned long tgafb_init(unsigned long mem_start)) fb_var.nonstd = 0; fb_var.activate = 0; fb_var.height = fb_var.width = -1; - fb_var.accel = FB_ACCEL_TGA; + fb_var.accel_flags = 0; fb_var.pixclock = 39722; fb_var.left_margin = 40; fb_var.right_margin = 24; @@ -729,7 +729,7 @@ __initfunc(unsigned long tgafb_init(unsigned long mem_start)) 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.screen_base = (char *)tga_fb_base + dense_mem(tga_fb_base); disp.visual = fb_fix.visual; disp.type = fb_fix.type; disp.type_aux = fb_fix.type_aux; @@ -739,12 +739,12 @@ __initfunc(unsigned long tgafb_init(unsigned long mem_start)) disp.can_soft_blank = 1; disp.inverse = 0; switch (tga_type) { -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 case 0: /* 8-plane */ disp.dispsw = &fbcon_cfb8; break; #endif -#ifdef CONFIG_FBCON_CFB32 +#ifdef FBCON_HAS_CFB32 case 1: /* 24-plane */ case 3: /* 24plusZ */ disp.dispsw = &fbcon_cfb32; @@ -753,6 +753,7 @@ __initfunc(unsigned long tgafb_init(unsigned long mem_start)) default: disp.dispsw = NULL; } + disp.scrollmode = SCROLL_YREDRAW; strcpy(fb_info.modename, fb_fix.id); fb_info.node = -1; @@ -764,15 +765,13 @@ __initfunc(unsigned long tgafb_init(unsigned long mem_start)) fb_info.updatevar = &tgafbcon_updatevar; fb_info.blank = &tgafbcon_blank; - err = register_framebuffer(&fb_info); - if (err < 0) - return mem_start; - tgafb_set_var(&fb_var, -1, &fb_info); + if (register_framebuffer(&fb_info) < 0) + return; + printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node), fb_fix.id); - return mem_start; } @@ -840,10 +839,10 @@ 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 +#ifdef FBCON_HAS_CFB32 if (regno < 16 && tga_type != 0) fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue; -#endif /* CONFIG_FBCON_CFB32 */ +#endif /* How to set a single color register?? */ @@ -927,9 +926,6 @@ set_cursor(int currcons) if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS) return; - if (__real_origin != __origin) - __set_origin(__real_origin); - save_flags(flags); cli(); if (deccm) { diff --git a/drivers/video/txtcon.c b/drivers/video/txtcon.c deleted file mode 100644 index 83165b49b..000000000 --- a/drivers/video/txtcon.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * linux/drivers/video/txtcon.c -- Low level text mode based console driver - * - * Copyright (C) 1995 Geert Uytterhoeven - * - * - * This file is currently only a skeleton, since all Amigas and Ataris have - * bitmapped graphics. - * - * - * 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/errno.h> -#include <linux/types.h> -#include <linux/kdev_t.h> -#include <linux/console.h> - - - /* - * Interface used by the world - */ - -static unsigned long txtcon_startup(unsigned long kmem_start, - const char **display_desc); -static void txtcon_init(struct vc_data *conp); -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 unsigned long txtcon_startup(unsigned long kmem_start, - const char **display_desc) -{ - return kmem_start; -} - - -static void txtcon_init(struct vc_data *conp) -{ - /* ... */ -} - - -static void txtcon_deinit(struct vc_data *conp) -{ - /* ... */ -} - - -/* ====================================================================== */ - -/* txtcon_XXX routines - interface used by the world */ - - -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) -{ - return -ENOSYS; -} - - -static int txtcon_blank(int blank) -{ - return -ENOSYS; -} - - -static int txtcon_get_font(struct vc_data *conp, int *w, int *h, char *data) -{ - return -ENOSYS; -} - - -static int txtcon_set_font(struct vc_data *conp, int w, int h, char *data) -{ - return -ENOSYS; -} - - -static int txtcon_set_palette(struct vc_data *conp, unsigned char *table) -{ - return -ENOSYS; -} - - -static int txtcon_scrolldelta(int lines) -{ - 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 - */ - -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_set_mode -}; diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c new file mode 100644 index 000000000..cf1534a9a --- /dev/null +++ b/drivers/video/vesafb.c @@ -0,0 +1,478 @@ +/* + * framebuffer driver for VBE 2.0 compliant graphic boards + * + * switching to graphics mode happens at boot time (while + * running in real mode, see arch/i386/video.S). + * + * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> + * + */ + +#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 <linux/console.h> +#include <linux/selection.h> +#include <linux/ioport.h> +#include <linux/init.h> + +#include <asm/io.h> + +#include "fbcon.h" +#include "fbcon-cfb8.h" +#include "fbcon-cfb16.h" +#include "fbcon-cfb32.h" + +#define dac_reg (0x3c8) +#define dac_val (0x3c9) + +/* --------------------------------------------------------------------- */ + +/* + * card parameters + */ + +/* card */ +char *video_base; +int video_size; +char *video_vbase; /* mapped */ + +/* mode */ +int video_bpp; +int video_width; +int video_height; +int video_type = FB_TYPE_PACKED_PIXELS; +int video_visual; +int video_linelength; +int video_cmap_len; + +/* --------------------------------------------------------------------- */ + +static struct fb_var_screeninfo vesafb_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, + -1,-1, + 0, + 0L,0L,0L,0L,0L, + 0L,0L,0, /* No sync info */ + FB_VMODE_NONINTERLACED, + {0,0,0,0,0,0} +}; + +static struct display disp; +static struct fb_info fb_info; +static struct { u_char red, green, blue, pad; } palette[256]; + +static int inverse = 0; + +static int currcon = 0; + +/* --------------------------------------------------------------------- */ +/* speed up scrolling */ + +#define USE_REDRAW 1 +#define USE_MEMMOVE 2 + +static int vesafb_scroll = USE_REDRAW; +static struct display_switch vesafb_sw; + +/* --------------------------------------------------------------------- */ + + /* + * Open/Release the frame buffer device + */ + +static int vesafb_open(struct fb_info *info, int user) +{ + /* + * Nothing, only a usage count for the moment + */ + MOD_INC_USE_COUNT; + return(0); +} + +static int vesafb_release(struct fb_info *info, int user) +{ + MOD_DEC_USE_COUNT; + return(0); +} + +static int fb_update_var(int con, struct fb_info *info) +{ + return 0; +} + +static int vesafb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + strcpy(fix->id,"VESA VGA"); + + fix->smem_start=(char *) video_base; + fix->smem_len=video_size; + fix->type = video_type; + fix->visual = video_visual; + fix->xpanstep=0; + fix->ypanstep=0; + fix->ywrapstep=0; + fix->line_length=video_linelength; + return 0; +} + +static int vesafb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + if(con==-1) + memcpy(var, &vesafb_defined, sizeof(struct fb_var_screeninfo)); + else + *var=fb_display[con].var; + return 0; +} + +static void vesafb_set_disp(int con) +{ + struct fb_fix_screeninfo fix; + struct display *display; + struct display_switch *sw; + + if (con >= 0) + display = &fb_display[con]; + else + display = &disp; /* used during initialization */ + + vesafb_get_fix(&fix, con, 0); + + memset(display, 0, sizeof(struct display)); + display->screen_base = video_vbase; + 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; + vesafb_get_var(&display->var, -1, &fb_info); + + switch (video_bpp) { +#ifdef FBCON_HAS_CFB8 + case 8: + sw = &fbcon_cfb8; + break; +#endif +#ifdef FBCON_HAS_CFB16 + case 15: + case 16: + sw = &fbcon_cfb16; + break; +#endif +#ifdef FBCON_HAS_CFB32 + case 32: + sw = &fbcon_cfb32; + break; +#endif + default: + return; + } + memcpy(&vesafb_sw, sw, sizeof(*sw)); + display->dispsw = &vesafb_sw; + if (vesafb_scroll == USE_REDRAW) { + display->scrollmode = SCROLL_YREDRAW; + vesafb_sw.bmove = fbcon_redraw_bmove; + } +} + +static int vesafb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + memcpy(var, &vesafb_defined, sizeof(struct fb_var_screeninfo)); + return 0; +} + +static int vesa_getcolreg(unsigned regno, unsigned *red, unsigned *green, + unsigned *blue, unsigned *transp, + struct fb_info *fb_info) +{ + /* + * Read a single color register and split it into colors/transparent. + * Return != 0 for invalid regno. + */ + + if (regno >= video_cmap_len) + return 1; + + *red = palette[regno].red; + *green = palette[regno].green; + *blue = palette[regno].blue; + return 0; +} + +static int vesa_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + 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 >= video_cmap_len) + return 1; + + palette[regno].red = red; + palette[regno].green = green; + palette[regno].blue = blue; + + switch (video_bpp) { +#ifdef FBCON_HAS_CFB8 + case 8: + /* Hmm, can we do it _always_ this way ??? */ + outb_p(regno, dac_reg); + outb_p(red, dac_val); + outb_p(green, dac_val); + outb_p(blue, dac_val); + break; +#endif +#ifdef FBCON_HAS_CFB16 + case 15: + case 16: + fbcon_cfb16_cmap[regno] = + (red << vesafb_defined.red.offset) | (green << 5) | blue; + break; +#endif +#ifdef FBCON_HAS_CFB24 + case 24: + /* FIXME: todo */ + break; +#endif +#ifdef FBCON_HAS_CFB32 + case 32: + fbcon_cfb32_cmap[regno] = + (red << vesafb_defined.red.offset) | + (green << vesafb_defined.green.offset) | + (blue << vesafb_defined.blue.offset); + break; +#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, + vesa_setcolreg, info); + else + fb_set_cmap(fb_default_cmap(video_cmap_len), + &fb_display[con].var, 1, vesa_setcolreg, + info); +} + +static int vesafb_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, vesa_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(video_cmap_len), + cmap, kspc ? 0 : 2); + return 0; +} + +static int vesafb_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? */ + err = fb_alloc_cmap(&fb_display[con].cmap,video_cmap_len,0); + if (err) + return err; + } + if (con == currcon) /* current console? */ + return fb_set_cmap(cmap, &fb_display[con].var, kspc, vesa_setcolreg, info); + else + fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); + return 0; +} + +static int vesafb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + /* no panning */ + return -EINVAL; +} + +static int vesafb_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 vesafb_ops = { + vesafb_open, + vesafb_release, + vesafb_get_fix, + vesafb_get_var, + vesafb_set_var, + vesafb_get_cmap, + vesafb_set_cmap, + vesafb_pan_display, + vesafb_ioctl +}; + +void vesafb_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 (!*this_opt) continue; + + printk("vesafb_setup: option %s\n", this_opt); + + if (! strcmp(this_opt, "inverse")) + inverse=1; + else if (! strcmp(this_opt, "redraw")) + vesafb_scroll = USE_REDRAW; + else if (! strcmp(this_opt, "memmove")) + vesafb_scroll = USE_MEMMOVE; + else if (!strncmp(this_opt, "font:", 5)) + strcpy(fb_info.fontname, this_opt+5); + } +} + +static int vesafb_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, + vesa_getcolreg, info); + + currcon = con; + /* Install new colormap */ + do_install_cmap(con, info); + return 0; +} + +/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ + +static void vesafb_blank(int blank, struct fb_info *info) +{ + /* Not supported */ +} + +__initfunc(void vesafb_init(void)) +{ + int i,j; + + if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) + return; + + video_base = (char*)screen_info.lfb_base; + video_bpp = screen_info.lfb_depth; + video_width = screen_info.lfb_width; + video_height = screen_info.lfb_height; + video_linelength = screen_info.lfb_linelength; + video_size = video_linelength * video_height /* screen_info.lfb_size */; + video_visual = (video_bpp == 8) ? + FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; + video_vbase = ioremap((unsigned long)video_base, video_size); + + printk("vesafb: %dx%dx%d, linelength=%d\n", + video_width, video_height, video_bpp, video_linelength); + printk("vesafb: framebuffer at 0x%p, mapped to 0x%p, size %d\n", + video_base, video_vbase, video_size); + if (vesafb_scroll == USE_REDRAW) printk("vesafb: scrolling=redraw\n"); + if (vesafb_scroll == USE_MEMMOVE) printk("vesafb: scrolling=memmove\n"); + + vesafb_defined.xres=video_width; + vesafb_defined.yres=video_height; + vesafb_defined.xres_virtual=video_width; + vesafb_defined.yres_virtual=video_height; + vesafb_defined.bits_per_pixel=video_bpp; + + if (video_bpp > 8) { + vesafb_defined.red.offset = screen_info.red_pos; + vesafb_defined.red.length = screen_info.red_size; + vesafb_defined.green.offset = screen_info.green_pos; + vesafb_defined.green.length = screen_info.green_size; + vesafb_defined.blue.offset = screen_info.blue_pos; + vesafb_defined.blue.length = screen_info.blue_size; + vesafb_defined.transp.offset = screen_info.rsvd_pos; + vesafb_defined.transp.length = screen_info.rsvd_size; + printk("vesafb: directcolor: " + "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", + screen_info.rsvd_size, + screen_info.red_size, + screen_info.green_size, + screen_info.blue_size, + screen_info.rsvd_pos, + screen_info.red_pos, + screen_info.green_pos, + screen_info.blue_pos); + video_cmap_len = 16; + } else { + vesafb_defined.red.length = 6; + vesafb_defined.green.length = 6; + vesafb_defined.blue.length = 6; + for(i = 0; i < 16; i++) { + j = color_table[i]; + palette[i].red = default_red[j]; + palette[i].green = default_grn[j]; + palette[i].blue = default_blu[j]; + } + video_cmap_len = 256; + } + request_region(0x3c0, 32, "vga+"); + + strcpy(fb_info.modename, "VESA VGA"); + fb_info.changevar = NULL; + fb_info.node = -1; + fb_info.fbops = &vesafb_ops; + fb_info.disp=&disp; + fb_info.switch_con=&vesafb_switch; + fb_info.updatevar=&fb_update_var; + fb_info.blank=&vesafb_blank; + vesafb_set_disp(-1); + + if (register_framebuffer(&fb_info)<0) + return; + + printk("fb%d: %s frame buffer device\n", + GET_FB_IDX(fb_info.node), fb_info.modename); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * --------------------------------------------------------------------------- + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index eea430ffa..f2bc39cd0 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -8,7 +8,6 @@ * more details. */ -#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -56,7 +55,7 @@ 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, 0, -1, -1, 0, 20000, 64, 64, 32, 32, 64, 2, 0, FB_VMODE_NONINTERLACED }; @@ -69,8 +68,8 @@ static int vfb_enable = 0; /* disabled by default */ 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_open(struct fb_info *info, int user); +static int vfb_release(struct fb_info *info, int user); 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, @@ -91,7 +90,7 @@ static int vfb_ioctl(struct inode *inode, struct file *file, u_int cmd, * Interface to the low level console driver */ -unsigned long vfb_init(unsigned long mem_start); +void vfb_init(void); 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); @@ -114,7 +113,7 @@ static void do_install_cmap(int con, struct fb_info *info); 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 + vfb_set_cmap, vfb_pan_display, vfb_ioctl }; @@ -122,7 +121,7 @@ static struct fb_ops vfb_ops = { * Open/Release the frame buffer device */ -static int vfb_open(struct fb_info *info) +static int vfb_open(struct fb_info *info, int user) { /* * Nothing, only a usage count for the moment @@ -132,7 +131,7 @@ static int vfb_open(struct fb_info *info) return(0); } -static int vfb_release(struct fb_info *info) +static int vfb_release(struct fb_info *info, int user) { MOD_DEC_USE_COUNT; return(0); @@ -250,7 +249,7 @@ static int vfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_fix_screeninfo fix; vfb_encode_fix(&fix, var); - display->screen_base = (u_char *)fix.smem_start; + display->screen_base = (char *)videomemory; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; @@ -260,37 +259,37 @@ static int vfb_set_var(struct fb_var_screeninfo *var, int con, display->can_soft_blank = 1; display->inverse = 0; switch (var->bits_per_pixel) { -#ifdef CONFIG_FBCON_MFB +#ifdef FBCON_HAS_MFB case 1: display->dispsw = &fbcon_mfb; break; #endif -#ifdef CONFIG_FBCON_CFB2 +#ifdef FBCON_HAS_CFB2 case 2: display->dispsw = &fbcon_cfb2; break; #endif -#ifdef CONFIG_FBCON_CFB4 +#ifdef FBCON_HAS_CFB4 case 4: display->dispsw = &fbcon_cfb4; break; #endif -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 case 8: display->dispsw = &fbcon_cfb8; break; #endif -#ifdef CONFIG_FBCON_CFB16 +#ifdef FBCON_HAS_CFB16 case 16: display->dispsw = &fbcon_cfb16; break; #endif -#ifdef CONFIG_FBCON_CFB24 +#ifdef FBCON_HAS_CFB24 case 24: display->dispsw = &fbcon_cfb24; break; #endif -#ifdef CONFIG_FBCON_CFB32 +#ifdef FBCON_HAS_CFB32 case 32: display->dispsw = &fbcon_cfb32; break; @@ -417,21 +416,13 @@ __initfunc(void vfb_setup(char *options, int *ints)) * Initialisation */ -__initfunc(unsigned long vfb_init(unsigned long mem_start)) +__initfunc(void vfb_init(void)) { - int err; - if (!vfb_enable) - return mem_start; - - if (mem_start) { - videomemory = mem_start; - mem_start += videomemorysize; - } else - videomemory = (u_long)vmalloc(videomemorysize); + return; - if (!videomemory) - return mem_start; + if (!(videomemory = (u_long)vmalloc(videomemorysize))) + return; strcpy(fb_info.modename, vfb_name); fb_info.changevar = NULL; @@ -442,15 +433,15 @@ __initfunc(unsigned long vfb_init(unsigned long mem_start)) fb_info.updatevar = &vfbcon_updatevar; fb_info.blank = &vfbcon_blank; - err = register_framebuffer(&fb_info); - if (err < 0) - return mem_start; - vfb_set_var(&vfb_default, -1, &fb_info); + if (register_framebuffer(&fb_info) < 0) { + vfree((void *)videomemory); + return; + } + printk("fb%d: Virtual frame buffer device, using %ldK of video memory\n", GET_FB_IDX(fb_info.node), videomemorysize>>10); - return mem_start; } @@ -501,7 +492,7 @@ static void vfb_encode_fix(struct fb_fix_screeninfo *fix, { memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, vfb_name); - fix->smem_start = (caddr_t)videomemory; + fix->smem_start = (char *)videomemory; fix->smem_len = videomemorysize; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; @@ -629,13 +620,14 @@ static void do_install_cmap(int con, struct fb_info *info) #ifdef MODULE int init_module(void) { - return(vfb_init(NULL)); + vfb_init(); + return 0; } void cleanup_module(void) { unregister_framebuffer(&fb_info); - vfree(videomemory); + vfree((void *)videomemory); } #endif /* MODULE */ diff --git a/drivers/video/vgacon.c b/drivers/video/vgacon.c index 623ea799d..a464d389a 100644 --- a/drivers/video/vgacon.c +++ b/drivers/video/vgacon.c @@ -3,6 +3,8 @@ * * Created 28 Sep 1997 by Geert Uytterhoeven * + * Rewritten by Martin Mares <mj@ucw.cz>, July 1998 + * * This file is based on the old console.c, vga.c and vesa_blank.c drivers. * * Copyright (C) 1991, 1992 Linus Torvalds @@ -31,20 +33,7 @@ * more details. */ - - - -/* KNOWN PROBLEMS/TO DO ===================================================== * - * - * - monochrome attribute encoding (convert abscon <-> VGA style) - * - * - speed up scrolling by changing the screen origin - * - * - add support for palette, loadable fonts and VESA blanking - * - * KNOWN PROBLEMS/TO DO ==================================================== */ - - +#include <linux/config.h> #include <linux/types.h> #include <linux/sched.h> #include <linux/fs.h> @@ -61,8 +50,6 @@ #include <linux/init.h> #include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/linux_logo.h> #define BLANK 0x0020 @@ -70,121 +57,76 @@ #define CAN_LOAD_EGA_FONTS /* undefine if the user must not do this */ #define CAN_LOAD_PALETTE /* undefine if the user must not do this */ -#define dac_reg (0x3c8) -#define dac_val (0x3c9) - -#ifdef __powerpc__ -#define VGA_OFFSET _ISA_MEM_BASE; -#else -#define VGA_OFFSET 0x0 -#endif - - -/* - * Interface used by the world +/* You really do _NOT_ want to define this, unless you have buggy + * Trident VGA which will resize cursor when moving it between column + * 15 & 16. If you define this and your VGA is OK, inverse bug will + * appear. */ +#undef TRIDENT_GLITCH -static unsigned long vgacon_startup(unsigned long kmem_start, - const char **display_desc); -static void vgacon_init(struct vc_data *conp); -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); -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); +#undef VGA_CAN_DO_64KB +#define dac_reg 0x3c8 +#define dac_val 0x3c9 +#define attrib_port 0x3c0 +#define seq_port_reg 0x3c4 +#define seq_port_val 0x3c5 +#define gr_port_reg 0x3ce +#define gr_port_val 0x3cf +#define video_misc_rd 0x3cc +#define video_misc_wr 0x3c2 /* - * Internal routines + * Interface used by the world */ -static int vgacon_show_logo(void); +static const char *vgacon_startup(void); +static void vgacon_init(struct vc_data *c, int init); +static void vgacon_deinit(struct vc_data *c); +static void vgacon_cursor(struct vc_data *c, int mode); +static int vgacon_switch(struct vc_data *c); +static int vgacon_blank(struct vc_data *c, int blank); +static int vgacon_font_op(struct vc_data *c, struct console_font_op *op); +static int vgacon_set_palette(struct vc_data *c, unsigned char *table); +static int vgacon_scrolldelta(struct vc_data *c, int lines); +static int vgacon_set_origin(struct vc_data *c); +static void vgacon_save_screen(struct vc_data *c); +static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, int lines); +static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse); +static void vgacon_invert_region(struct vc_data *c, u16 *p, int count); +static unsigned long vgacon_uni_pagedir[2]; /* Description of the hardware situation */ -static unsigned long vga_video_mem_base; /* Base of video memory */ -static unsigned long vga_video_mem_term; /* End of video memory */ -static unsigned short vga_video_port_reg; /* Video register select port */ -static unsigned short vga_video_port_val; /* Video register value port */ -static unsigned long vga_video_num_columns; /* Number of text columns */ -static unsigned long vga_video_num_lines; /* Number of text lines */ -static unsigned long vga_video_size_row; -static unsigned long vga_video_screen_size; - -static int vga_can_do_color = 0; -static unsigned long vga_default_font_height; /* Height of default screen font */ - -static unsigned char vga_video_type; -static unsigned char vga_has_wrapped; /* all of videomem is data of fg_console */ -static unsigned char vga_hardscroll_enabled; -static unsigned char vga_hardscroll_disabled_by_init = 0; - - - - /* - * VGA screen access - */ - -static inline void vga_writew(unsigned short val, unsigned short * addr) -{ -#ifdef __powerpc__ - st_le16(addr, val); -#else - writew(val, (unsigned long) addr); -#endif /* !__powerpc__ */ -} - -static inline unsigned short vga_readw(unsigned short * addr) -{ -#ifdef __powerpc__ - return ld_le16(addr); -#else - return readw((unsigned long) addr); -#endif /* !__powerpc__ */ -} - -static inline void vga_memsetw(void * s, unsigned short c, unsigned int count) +static unsigned long vga_vram_base; /* Base of video memory */ +static unsigned long vga_vram_end; /* End of video memory */ +static u16 vga_video_port_reg; /* Video register select port */ +static u16 vga_video_port_val; /* Video register value port */ +static unsigned int vga_video_num_columns; /* Number of text columns */ +static unsigned int vga_video_num_lines; /* Number of text lines */ +static int vga_can_do_color = 0; /* Do we support colors? */ +static unsigned int vga_default_font_height; /* Height of default screen font */ +static unsigned char vga_video_type; /* Card type */ +static unsigned char vga_hardscroll_enabled; +static unsigned char vga_hardscroll_user_enable = 1; +static unsigned char vga_font_is_default = 1; +static int vga_vesa_blanked; +static int vga_palette_blanked; +static int vga_is_gfx; +static int vga_512_chars; +static int vga_video_font_height; + + +void no_scroll(char *str, int *ints) { - unsigned short * addr = (unsigned short *) s; - - while (count) { - count--; - vga_writew(c, addr++); - } -} - -static inline void vga_memmovew(unsigned short *to, unsigned short *from, - unsigned int count) -{ - if (to < from) { - while (count) { - count--; - vga_writew(vga_readw(from++), to++); - } - } else { - from += count; - to += count; - while (count) { - count--; - vga_writew(vga_readw(--from), --to); - } - } + /* + * Disabling scrollback is required for the Braillex ib80-piezo + * Braille reader made by F.H. Papenmeier (Germany). + * Use the "no-scroll" bootflag. + */ + vga_hardscroll_user_enable = vga_hardscroll_enabled = 0; } - /* * By replacing the four outb_p with two back to back outw, we can reduce * the window of opportunity to see text mislocated to the RHS of the @@ -209,58 +151,67 @@ static inline void write_vga(unsigned char reg, unsigned int val) #endif } - -__initfunc(static unsigned long vgacon_startup(unsigned long kmem_start, - const char **display_desc)) +__initfunc(static const char *vgacon_startup(void)) { - unsigned short saved; - unsigned short *p; + const char *display_desc = NULL; + u16 saved; + u16 *p; + + if (ORIG_VIDEO_ISVGA == VIDEO_TYPE_VLFB) { + no_vga: +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; + return conswitchp->con_startup(); +#else + return NULL; +#endif + } + vga_video_num_lines = ORIG_VIDEO_LINES; vga_video_num_columns = ORIG_VIDEO_COLS; - vga_video_size_row = 2 * ORIG_VIDEO_COLS; - vga_video_screen_size = vga_video_num_lines * vga_video_size_row; if (ORIG_VIDEO_MODE == 7) /* Is this a monochrome display? */ { - vga_video_mem_base = 0xb0000 + VGA_OFFSET; + vga_vram_base = 0xb0000; vga_video_port_reg = 0x3b4; vga_video_port_val = 0x3b5; if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { vga_video_type = VIDEO_TYPE_EGAM; - vga_video_mem_term = 0xb8000 + VGA_OFFSET; - *display_desc = "EGA+"; + vga_vram_end = 0xb8000; + display_desc = "EGA+"; request_region(0x3b0,16,"ega"); } else { vga_video_type = VIDEO_TYPE_MDA; - vga_video_mem_term = 0xb2000 + VGA_OFFSET; - *display_desc = "*MDA"; + vga_vram_end = 0xb2000; + display_desc = "*MDA"; request_region(0x3b0,12,"mda"); request_region(0x3bf, 1,"mda"); + vga_video_font_height = 16; } } else /* If not, it is color. */ { vga_can_do_color = 1; - vga_video_mem_base = 0xb8000 + VGA_OFFSET; - vga_video_port_reg = 0x3d4; - vga_video_port_val = 0x3d5; + vga_vram_base = 0xb8000; + vga_video_port_reg = 0x3d4; + vga_video_port_val = 0x3d5; if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { - int i ; + int i; - vga_video_mem_term = 0xc0000 + VGA_OFFSET; + vga_vram_end = 0xc0000; if (!ORIG_VIDEO_ISVGA) { vga_video_type = VIDEO_TYPE_EGAC; - *display_desc = "EGA"; + display_desc = "EGA"; request_region(0x3c0,32,"ega"); } else { vga_video_type = VIDEO_TYPE_VGAC; - *display_desc = "VGA+"; + display_desc = "VGA+"; request_region(0x3c0,32,"vga+"); #ifdef VGA_CAN_DO_64KB @@ -270,8 +221,8 @@ __initfunc(static unsigned long vgacon_startup(unsigned long kmem_start, * controllers (it seems like setting MM=01 * and COE=1 isn't necessarily a good idea) */ - vga_video_mem_base = 0xa0000 + VGA_OFFSET; - vga_video_mem_term = 0xb0000 + VGA_OFFSET; + vga_vram_base = 0xa0000; + vga_vram_end = 0xb0000; outb_p (6, 0x3ce) ; outb_p (6, 0x3cf) ; #endif @@ -303,287 +254,764 @@ __initfunc(static unsigned long vgacon_startup(unsigned long kmem_start, else { vga_video_type = VIDEO_TYPE_CGA; - vga_video_mem_term = 0xba000 + VGA_OFFSET; - *display_desc = "*CGA"; + vga_vram_end = 0xba000; + display_desc = "*CGA"; request_region(0x3d4,2,"cga"); + vga_video_font_height = 8; } } + vga_vram_base = VGA_MAP_MEM(vga_vram_base); + vga_vram_end = VGA_MAP_MEM(vga_vram_end); /* * 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; + p = (u16 *)vga_vram_base; + saved = scr_readw(p); + scr_writew(0xAA55, p); + if (scr_readw(p) != 0xAA55) { + scr_writew(saved, p); + goto no_vga; } - vga_writew(0x55AA, p); - if (vga_readw(p) != 0x55AA) { - vga_writew(saved, p); - return kmem_start; + scr_writew(0x55AA, p); + if (scr_readw(p) != 0x55AA) { + scr_writew(saved, p); + goto no_vga; } - vga_writew(saved, p); + scr_writew(saved, p); - vga_hardscroll_enabled = (vga_hardscroll_disabled_by_init ? 0 : - (vga_video_type == VIDEO_TYPE_EGAC + if (vga_video_type == VIDEO_TYPE_EGAC || vga_video_type == VIDEO_TYPE_VGAC - || vga_video_type == VIDEO_TYPE_EGAM)); - vga_has_wrapped = 0; - - if (vga_video_type == VIDEO_TYPE_VGAC - || vga_video_type == VIDEO_TYPE_EGAC - || vga_video_type == VIDEO_TYPE_EGAM) - { + || vga_video_type == VIDEO_TYPE_EGAM) { + vga_hardscroll_enabled = vga_hardscroll_user_enable; vga_default_font_height = ORIG_VIDEO_POINTS; - video_font_height = ORIG_VIDEO_POINTS; + vga_video_font_height = ORIG_VIDEO_POINTS; /* This may be suboptimal but is a safe bet - go with it */ video_scan_lines = - video_font_height * vga_video_num_lines; + vga_video_font_height * vga_video_num_lines; } + video_font_height = vga_video_font_height; - if (!console_show_logo) - console_show_logo = vgacon_show_logo; - - return kmem_start; + return display_desc; } +static void vgacon_init(struct vc_data *c, int init) +{ + unsigned long p; + + /* We cannot be loaded as a module, therefore init is always 1 */ + c->vc_can_do_color = vga_can_do_color; + c->vc_cols = vga_video_num_columns; + c->vc_rows = vga_video_num_lines; + c->vc_complement_mask = 0x7700; + p = *c->vc_uni_pagedir_loc; + if (c->vc_uni_pagedir_loc == &c->vc_uni_pagedir || + !--c->vc_uni_pagedir_loc[1]) + con_free_unimap(c->vc_num); + c->vc_uni_pagedir_loc = vgacon_uni_pagedir; + vgacon_uni_pagedir[1]++; + if (!vgacon_uni_pagedir[0] && p) + con_set_default_unimap(c->vc_num); +} -static void vgacon_init(struct vc_data *conp) +static inline void vga_set_mem_top(struct vc_data *c) { - conp->vc_cols = vga_video_num_columns; - conp->vc_rows = vga_video_num_lines; - conp->vc_can_do_color = vga_can_do_color; + write_vga(12, (c->vc_visible_origin-vga_vram_base)/2); } -static void vgacon_deinit(struct vc_data *conp) +static void vgacon_deinit(struct vc_data *c) { + /* When closing the last console, reset video origin */ + if (!--vgacon_uni_pagedir[1]) { + c->vc_visible_origin = vga_vram_base; + vga_set_mem_top(c); + con_free_unimap(c->vc_num); + } + c->vc_uni_pagedir_loc = &c->vc_uni_pagedir; + con_set_default_unimap(c->vc_num); } +static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse) +{ + u8 attr = color; -/* ====================================================================== */ + if (vga_can_do_color) { + if (underline) + attr = (attr & 0xf0) | c->vc_ulcolor; + else if (intensity == 0) + attr = (attr & 0xf0) | c->vc_halfcolor; + } + if (reverse) + attr = ((attr) & 0x88) | ((((attr) >> 4) | ((attr) << 4)) & 0x77); + if (blink) + attr ^= 0x80; + if (intensity == 2) + attr ^= 0x08; + if (!vga_can_do_color) { + if (underline) + attr = (attr & 0xf8) | 0x01; + else if (intensity == 0) + attr = (attr & 0xf0) | 0x08; + } + return attr; +} -static void vgacon_clear(struct vc_data *conp, int sy, int sx, int height, - int width) +static void vgacon_invert_region(struct vc_data *c, u16 *p, int count) { - int rows; - unsigned long dest; - - if (console_blanked) - return; - - dest = vga_video_mem_base + sy*vga_video_size_row + sx*2; - if (sx == 0 && width == vga_video_num_columns) - vga_memsetw((void *)dest, conp->vc_video_erase_char, height * width); - else - for (rows = height; rows-- ; dest += vga_video_size_row) - vga_memsetw((void *)dest, conp->vc_video_erase_char, width); -} + int col = vga_can_do_color; + while (count--) { + u16 a = scr_readw(p); + if (col) + a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4); + else + a ^= ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700; + scr_writew(a, p++); + } +} -static void vgacon_putc(struct vc_data *conp, int c, int ypos, int xpos) +static void vgacon_set_cursor_size(int xpos, int from, int to) { - u16 *p; + unsigned long flags; + int curs, cure; + static int lastfrom, lastto; - if (console_blanked) - return; - - p = (u16 *)(vga_video_mem_base+ypos*vga_video_size_row+xpos*2); - vga_writew(conp->vc_attr << 8 | c, p); -} +#ifdef TRIDENT_GLITCH + if (xpos<16) from--, to--; +#endif + if ((from == lastfrom) && (to == lastto)) return; + lastfrom = from; lastto = to; -static void vgacon_putcs(struct vc_data *conp, const char *s, int count, - int ypos, int xpos) -{ - u16 *p; - u16 sattr; + save_flags(flags); cli(); + outb_p(0x0a, vga_video_port_reg); /* Cursor start */ + curs = inb_p(vga_video_port_val); + outb_p(0x0b, vga_video_port_reg); /* Cursor end */ + cure = inb_p(vga_video_port_val); - if (console_blanked) - return; + curs = (curs & 0xc0) | from; + cure = (cure & 0xe0) | to; - 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++); + outb_p(0x0a, vga_video_port_reg); /* Cursor start */ + outb_p(curs, vga_video_port_val); + outb_p(0x0b, vga_video_port_reg); /* Cursor end */ + outb_p(cure, vga_video_port_val); + restore_flags(flags); } - -static void vgacon_cursor(struct vc_data *conp, int mode) +static void vgacon_cursor(struct vc_data *c, int mode) { + if (c->vc_origin != c->vc_visible_origin) + vgacon_scrolldelta(c, 0); switch (mode) { case CM_ERASE: - write_vga(14, (vga_video_mem_term - vga_video_mem_base - 1)>>1); + write_vga(14, (vga_vram_end - vga_vram_base - 1)/2); break; case CM_MOVE: case CM_DRAW: - write_vga(14, conp->vc_y*vga_video_num_columns+conp->vc_x); + write_vga(14, (c->vc_pos-vga_vram_base)/2); + switch (c->vc_cursor_type & 0x0f) { + case CUR_UNDERLINE: + vgacon_set_cursor_size(c->vc_x, + video_font_height - (video_font_height < 10 ? 2 : 3), + video_font_height - (video_font_height < 10 ? 1 : 2)); + break; + case CUR_TWO_THIRDS: + vgacon_set_cursor_size(c->vc_x, + video_font_height / 3, + video_font_height - (video_font_height < 10 ? 1 : 2)); + break; + case CUR_LOWER_THIRD: + vgacon_set_cursor_size(c->vc_x, + (video_font_height*2) / 3, + video_font_height - (video_font_height < 10 ? 1 : 2)); + break; + case CUR_LOWER_HALF: + vgacon_set_cursor_size(c->vc_x, + video_font_height / 2, + video_font_height - (video_font_height < 10 ? 1 : 2)); + break; + case CUR_NONE: + vgacon_set_cursor_size(c->vc_x, 31, 30); + break; + default: + vgacon_set_cursor_size(c->vc_x, 1, video_font_height); + break; + } break; } } +static int vgacon_switch(struct vc_data *c) +{ + /* + * We need to save screen size here as it's the only way + * we can spot the screen has been resized and we need to + * set size of freshly allocated screens ourselves. + */ + vga_video_num_columns = c->vc_cols; + vga_video_num_lines = c->vc_rows; + if (vga_is_gfx) + return 1; + scr_memcpyw_to((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, c->vc_screenbuf_size); + return 0; /* Redrawing not needed */ +} -static void vgacon_scroll(struct vc_data *conp, int t, int b, int dir, - int count) +static void vga_set_palette(struct vc_data *c, unsigned char *table) { - if (console_blanked) - return; + int i, j ; - vgacon_cursor(conp, CM_ERASE); + for (i=j=0; i<16; i++) { + outb_p (table[i], dac_reg) ; + outb_p (c->vc_palette[j++]>>2, dac_val) ; + outb_p (c->vc_palette[j++]>>2, dac_val) ; + outb_p (c->vc_palette[j++]>>2, dac_val) ; + } +} - switch (dir) { - case SM_UP: - if (count > conp->vc_rows) /* Maximum realistic size */ - count = conp->vc_rows; - vgacon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols); - vgacon_clear(conp, b-count, 0, count, conp->vc_cols); - break; +static int vgacon_set_palette(struct vc_data *c, unsigned char *table) +{ +#ifdef CAN_LOAD_PALETTE - case SM_DOWN: - if (count > conp->vc_rows) /* Maximum realistic size */ - count = conp->vc_rows; - /* - * Fixed bmove() should end Arno's frustration with copying? - * Confucius says: - * Man who copies in wrong direction, end up with trashed - * data - */ - vgacon_bmove(conp, t, 0, t+count, 0, b-t-count, conp->vc_cols); - vgacon_clear(conp, t, 0, count, conp->vc_cols); - break; + if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked) + return -EINVAL; + vga_set_palette(c, table); + return 0; +#else + return -EINVAL; +#endif +} - case SM_LEFT: - vgacon_bmove(conp, 0, t+count, 0, t, conp->vc_rows, b-t-count); - vgacon_clear(conp, 0, b-count, conp->vc_rows, count); - break; +/* structure holding original VGA register settings */ +static struct { + unsigned char SeqCtrlIndex; /* Sequencer Index reg. */ + unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */ + unsigned char CrtMiscIO; /* Miscellaneous register */ + unsigned char HorizontalTotal; /* CRT-Controller:00h */ + unsigned char HorizDisplayEnd; /* CRT-Controller:01h */ + unsigned char StartHorizRetrace; /* CRT-Controller:04h */ + unsigned char EndHorizRetrace; /* CRT-Controller:05h */ + unsigned char Overflow; /* CRT-Controller:07h */ + unsigned char StartVertRetrace; /* CRT-Controller:10h */ + unsigned char EndVertRetrace; /* CRT-Controller:11h */ + unsigned char ModeControl; /* CRT-Controller:17h */ + unsigned char ClockingMode; /* Seq-Controller:01h */ +} vga_state; + +static void vga_vesa_blank(int mode) +{ + /* save original values of VGA controller registers */ + if(!vga_vesa_blanked) { + cli(); + vga_state.SeqCtrlIndex = inb_p(seq_port_reg); + vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg); + vga_state.CrtMiscIO = inb_p(video_misc_rd); + sti(); + + outb_p(0x00,vga_video_port_reg); /* HorizontalTotal */ + vga_state.HorizontalTotal = inb_p(vga_video_port_val); + outb_p(0x01,vga_video_port_reg); /* HorizDisplayEnd */ + vga_state.HorizDisplayEnd = inb_p(vga_video_port_val); + outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */ + vga_state.StartHorizRetrace = inb_p(vga_video_port_val); + outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */ + vga_state.EndHorizRetrace = inb_p(vga_video_port_val); + outb_p(0x07,vga_video_port_reg); /* Overflow */ + vga_state.Overflow = inb_p(vga_video_port_val); + outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */ + vga_state.StartVertRetrace = inb_p(vga_video_port_val); + outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */ + vga_state.EndVertRetrace = inb_p(vga_video_port_val); + outb_p(0x17,vga_video_port_reg); /* ModeControl */ + vga_state.ModeControl = inb_p(vga_video_port_val); + outb_p(0x01,seq_port_reg); /* ClockingMode */ + vga_state.ClockingMode = inb_p(seq_port_val); + } - case SM_RIGHT: - vgacon_bmove(conp, 0, t, 0, t+count, conp->vc_rows, b-t-count); - vgacon_clear(conp, 0, t, conp->vc_rows, count); - break; - } -} + /* assure that video is enabled */ + /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ + cli(); + outb_p(0x01,seq_port_reg); + outb_p(vga_state.ClockingMode | 0x20,seq_port_val); + /* test for vertical retrace in process.... */ + if ((vga_state.CrtMiscIO & 0x80) == 0x80) + outb_p(vga_state.CrtMiscIO & 0xef,video_misc_wr); -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; - - if (sx == 0 && dx == 0 && width == vga_video_num_columns) { - src = vga_video_mem_base + sy * vga_video_size_row; - dst = vga_video_mem_base + dy * vga_video_size_row; - vga_memmovew((unsigned short *)dst, (unsigned short *)src, - height * width); - } else if (dy < sy || (dy == sy && dx < sx)) { - src = vga_video_mem_base + sy * vga_video_size_row + sx * 2; - dst = vga_video_mem_base + dy * vga_video_size_row + dx * 2; - for (rows = height; rows-- ;) { - vga_memmovew((unsigned short *)dst, (unsigned short *)src, width); - src += vga_video_size_row; - dst += vga_video_size_row; + /* + * Set <End of vertical retrace> to minimum (0) and + * <Start of vertical Retrace> to maximum (incl. overflow) + * Result: turn off vertical sync (VSync) pulse. + */ + if (mode & VESA_VSYNC_SUSPEND) { + outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */ + outb_p(0xff,vga_video_port_val); /* maximum value */ + outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */ + outb_p(0x40,vga_video_port_val); /* minimum (bits 0..3) */ + outb_p(0x07,vga_video_port_reg); /* Overflow */ + outb_p(vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */ } - } else { - src = vga_video_mem_base + (sy+height-1) * vga_video_size_row + sx * 2; - dst = vga_video_mem_base + (dy+height-1) * vga_video_size_row + dx * 2; - for (rows = height; rows-- ;) { - vga_memmovew((unsigned short *)dst, (unsigned short *)src, width); - src -= vga_video_size_row; - dst -= vga_video_size_row; + + if (mode & VESA_HSYNC_SUSPEND) { + /* + * Set <End of horizontal retrace> to minimum (0) and + * <Start of horizontal Retrace> to maximum + * Result: turn off horizontal sync (HSync) pulse. + */ + outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */ + outb_p(0xff,vga_video_port_val); /* maximum */ + outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */ + outb_p(0x00,vga_video_port_val); /* minimum (0) */ } - } -} + /* restore both index registers */ + outb_p(vga_state.SeqCtrlIndex,seq_port_reg); + outb_p(vga_state.CrtCtrlIndex,vga_video_port_reg); + sti(); +} -static int vgacon_switch(struct vc_data *conp) +static void vga_vesa_unblank(void) { - return 0; + /* restore original values of VGA controller registers */ + cli(); + outb_p(vga_state.CrtMiscIO,video_misc_wr); + + outb_p(0x00,vga_video_port_reg); /* HorizontalTotal */ + outb_p(vga_state.HorizontalTotal,vga_video_port_val); + outb_p(0x01,vga_video_port_reg); /* HorizDisplayEnd */ + outb_p(vga_state.HorizDisplayEnd,vga_video_port_val); + outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */ + outb_p(vga_state.StartHorizRetrace,vga_video_port_val); + outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */ + outb_p(vga_state.EndHorizRetrace,vga_video_port_val); + outb_p(0x07,vga_video_port_reg); /* Overflow */ + outb_p(vga_state.Overflow,vga_video_port_val); + outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */ + outb_p(vga_state.StartVertRetrace,vga_video_port_val); + outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */ + outb_p(vga_state.EndVertRetrace,vga_video_port_val); + outb_p(0x17,vga_video_port_reg); /* ModeControl */ + outb_p(vga_state.ModeControl,vga_video_port_val); + outb_p(0x01,seq_port_reg); /* ClockingMode */ + outb_p(vga_state.ClockingMode,seq_port_val); + + /* restore index/control registers */ + outb_p(vga_state.SeqCtrlIndex,seq_port_reg); + outb_p(vga_state.CrtCtrlIndex,vga_video_port_reg); + sti(); } +static void vga_pal_blank(void) +{ + int i; + + for (i=0; i<16; i++) { + outb_p (i, dac_reg) ; + outb_p (0, dac_val) ; + outb_p (0, dac_val) ; + outb_p (0, dac_val) ; + } +} -static int vgacon_blank(int blank) +static int vgacon_blank(struct vc_data *c, int blank) { - if (blank) { - vga_memsetw((void *)vga_video_mem_base, BLANK, vga_video_screen_size/2); - return 0; - } else { - /* Tell console.c that it has to restore the screen itself */ - return 1; - } - return 0; + switch (blank) { + case 0: /* Unblank */ + if (vga_vesa_blanked) { + vga_vesa_unblank(); + vga_vesa_blanked = 0; + } + if (vga_palette_blanked) { + vga_set_palette(c, color_table); + vga_palette_blanked = 0; + return 0; + } + vga_is_gfx = 0; + /* Tell console.c that it has to restore the screen itself */ + return 1; + case 1: /* Normal blanking */ + if (vga_video_type == VIDEO_TYPE_VGAC) { + vga_pal_blank(); + vga_palette_blanked = 1; + return 0; + } + scr_memsetw((void *)vga_vram_base, BLANK, vc_cons[0].d->vc_screenbuf_size); + return 1; + case -1: /* Entering graphic mode */ + scr_memsetw((void *)vga_vram_base, BLANK, vc_cons[0].d->vc_screenbuf_size); + vga_is_gfx = 1; + return 1; + default: /* VESA blanking */ + if (vga_video_type == VIDEO_TYPE_VGAC) { + vga_vesa_blank(blank-1); + vga_vesa_blanked = blank; + } + return 0; + } } +/* + * PIO_FONT support. + * + * The font loading code goes back to the codepage package by + * Joel Hoffman (joel@wam.umd.edu). (He reports that the original + * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2 + * Video Systems_ by Richard Wilton. 1987. Microsoft Press".) + * + * Change for certain monochrome monitors by Yury Shevchuck + * (sizif@botik.yaroslavl.su). + */ + +#ifdef CAN_LOAD_EGA_FONTS -static int vgacon_get_font(struct vc_data *conp, int *w, int *h, char *data) +#define colourmap 0xa0000 +/* Pauline Middelink <middelin@polyware.iaf.nl> reports that we + should use 0xA0000 for the bwmap as well.. */ +#define blackwmap 0xa0000 +#define cmapsz 8192 + +static int +vgacon_do_font_op(char *arg, int set, int ch512) { - /* TODO */ - return -ENOSYS; -} + int i; + char *charmap; + int beg; + unsigned short video_port_status = vga_video_port_reg + 6; + int font_select = 0x00; + + if (vga_video_type != VIDEO_TYPE_EGAM) { + charmap = (char *)VGA_MAP_MEM(colourmap); + beg = 0x0e; +#ifdef VGA_CAN_DO_64KB + if (vga_video_type == VIDEO_TYPE_VGAC) + beg = 0x06; +#endif + } else { + charmap = (char *)VGA_MAP_MEM(blackwmap); + beg = 0x0a; + } + +#ifdef BROKEN_GRAPHICS_PROGRAMS + /* + * All fonts are loaded in slot 0 (0:1 for 512 ch) + */ + if (!arg) + return -EINVAL; /* Return to default font not supported */ -static int vgacon_set_font(struct vc_data *conp, int w, int h, char *data) + vga_font_is_default = 0; + font_select = ch512 ? 0x04 : 0x00; +#else + /* + * The default font is kept in slot 0 and is never touched. + * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch) + */ + + if (set) { + vga_font_is_default = !arg; + if (!arg) + ch512 = 0; /* Default font is always 256 */ + font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00; + } + + if ( !vga_font_is_default ) + charmap += 4*cmapsz; +#endif + + cli(); + outb_p( 0x00, seq_port_reg ); /* First, the sequencer */ + outb_p( 0x01, seq_port_val ); /* Synchronous reset */ + outb_p( 0x02, seq_port_reg ); + outb_p( 0x04, seq_port_val ); /* CPU writes only to map 2 */ + outb_p( 0x04, seq_port_reg ); + outb_p( 0x07, seq_port_val ); /* Sequential addressing */ + outb_p( 0x00, seq_port_reg ); + outb_p( 0x03, seq_port_val ); /* Clear synchronous reset */ + + outb_p( 0x04, gr_port_reg ); /* Now, the graphics controller */ + outb_p( 0x02, gr_port_val ); /* select map 2 */ + outb_p( 0x05, gr_port_reg ); + outb_p( 0x00, gr_port_val ); /* disable odd-even addressing */ + outb_p( 0x06, gr_port_reg ); + outb_p( 0x00, gr_port_val ); /* map start at A000:0000 */ + sti(); + + if (arg) { + if (set) + for (i=0; i<cmapsz ; i++) + vga_writeb(arg[i], charmap + i); + else + for (i=0; i<cmapsz ; i++) + arg[i] = vga_readb(charmap + i); + + /* + * In 512-character mode, the character map is not contiguous if + * we want to remain EGA compatible -- which we do + */ + + if (ch512) { + charmap += 2*cmapsz; + arg += cmapsz; + if (set) + for (i=0; i<cmapsz ; i++) + vga_writeb(arg[i], charmap+i); + else + for (i=0; i<cmapsz ; i++) + arg[i] = vga_readb(charmap+i); + } + } + + cli(); + outb_p( 0x00, seq_port_reg ); /* First, the sequencer */ + outb_p( 0x01, seq_port_val ); /* Synchronous reset */ + outb_p( 0x02, seq_port_reg ); + outb_p( 0x03, seq_port_val ); /* CPU writes to maps 0 and 1 */ + outb_p( 0x04, seq_port_reg ); + outb_p( 0x03, seq_port_val ); /* odd-even addressing */ + if (set) { + outb_p( 0x03, seq_port_reg ); /* Character Map Select */ + outb_p( font_select, seq_port_val ); + } + outb_p( 0x00, seq_port_reg ); + outb_p( 0x03, seq_port_val ); /* clear synchronous reset */ + + outb_p( 0x04, gr_port_reg ); /* Now, the graphics controller */ + outb_p( 0x00, gr_port_val ); /* select map 0 for CPU */ + outb_p( 0x05, gr_port_reg ); + outb_p( 0x10, gr_port_val ); /* enable even-odd addressing */ + outb_p( 0x06, gr_port_reg ); + outb_p( beg, gr_port_val ); /* map starts at b800:0 or b000:0 */ + + /* if 512 char mode is already enabled don't re-enable it. */ + if ((set)&&(ch512!=vga_512_chars)) { /* attribute controller */ + int i; + for(i=0; i<MAX_NR_CONSOLES; i++) { + struct vc_data *c = vc_cons[i].d; + if (c && c->vc_sw == &vga_con) + c->vc_hi_font_mask = ch512 ? 0x0800 : 0; + } + vga_512_chars=ch512; + /* 256-char: enable intensity bit + 512-char: disable intensity bit */ + inb_p( video_port_status ); /* clear address flip-flop */ + outb_p ( 0x12, attrib_port ); /* color plane enable register */ + outb_p ( ch512 ? 0x07 : 0x0f, attrib_port ); + /* Wilton (1987) mentions the following; I don't know what + it means, but it works, and it appears necessary */ + inb_p( video_port_status ); + outb_p ( 0x20, attrib_port ); + } + sti(); + + return 0; +} + +/* + * Adjust the screen to fit a font of a certain height + */ +static int +vgacon_adjust_height(unsigned fontheight) { - /* TODO */ - return -ENOSYS; + int rows, maxscan; + unsigned char ovr, vde, fsr; + + if (fontheight == vga_video_font_height) + return 0; + + vga_video_font_height = video_font_height = fontheight; + + rows = video_scan_lines/fontheight; /* Number of video rows we end up with */ + maxscan = rows*fontheight - 1; /* Scan lines to actually display-1 */ + + /* Reprogram the CRTC for the new font size + Note: the attempt to read the overflow register will fail + on an EGA, but using 0xff for the previous value appears to + be OK for EGA text modes in the range 257-512 scan lines, so I + guess we don't need to worry about it. + + The same applies for the spill bits in the font size and cursor + registers; they are write-only on EGA, but it appears that they + are all don't care bits on EGA, so I guess it doesn't matter. */ + + cli(); + outb_p( 0x07, vga_video_port_reg ); /* CRTC overflow register */ + ovr = inb_p(vga_video_port_val); + outb_p( 0x09, vga_video_port_reg ); /* Font size register */ + fsr = inb_p(vga_video_port_val); + sti(); + + vde = maxscan & 0xff; /* Vertical display end reg */ + ovr = (ovr & 0xbd) + /* Overflow register */ + ((maxscan & 0x100) >> 7) + + ((maxscan & 0x200) >> 3); + fsr = (fsr & 0xe0) + (fontheight-1); /* Font size register */ + + cli(); + outb_p( 0x07, vga_video_port_reg ); /* CRTC overflow register */ + outb_p( ovr, vga_video_port_val ); + outb_p( 0x09, vga_video_port_reg ); /* Font size */ + outb_p( fsr, vga_video_port_val ); + outb_p( 0x12, vga_video_port_reg ); /* Vertical display limit */ + outb_p( vde, vga_video_port_val ); + sti(); + + vc_resize_all(rows, 0); /* Adjust console size */ + return 0; } -static int vgacon_set_palette(struct vc_data *conp, unsigned char *table) +static int vgacon_font_op(struct vc_data *c, struct console_font_op *op) { - int i, j ; + int rc; - if (vga_video_type != VIDEO_TYPE_VGAC || console_blanked || - vt_cons[fg_console]->vc_mode == KD_GRAPHICS) + if (vga_video_type < VIDEO_TYPE_EGAM) return -EINVAL; - for (i=j=0; i<16; i++) { - outb_p (table[i], dac_reg) ; - outb_p (vc_cons[fg_console].d->vc_palette[j++]>>2, dac_val) ; - outb_p (vc_cons[fg_console].d->vc_palette[j++]>>2, dac_val) ; - outb_p (vc_cons[fg_console].d->vc_palette[j++]>>2, dac_val) ; - } - return 0; + if (op->op == KD_FONT_OP_SET) { + if (op->width != 8 || (op->charcount != 256 && op->charcount != 512)) + return -EINVAL; + rc = vgacon_do_font_op(op->data, 1, op->charcount == 512); + if (!rc && !(op->flags & KD_FONT_FLAG_DONT_RECALC)) + rc = vgacon_adjust_height(op->height); + } else if (op->op == KD_FONT_OP_GET) { + op->width = 8; + op->height = vga_video_font_height; + op->charcount = vga_512_chars ? 512 : 256; + if (!op->data) return 0; + rc = vgacon_do_font_op(op->data, 0, 0); + } else + rc = -ENOSYS; + return rc; } -static int vgacon_scrolldelta(int lines) +#else + +static int vgacon_font_op(struct vc_data *c, struct console_font_op *op) { - /* TODO */ - return -ENOSYS; + return -ENOSYS; } -static int vgacon_set_mode(struct vc_data *conp, int mode) +#endif + +static int vgacon_scrolldelta(struct vc_data *c, int lines) { - return -ENOSYS; + if (!lines) /* Turn scrollback off */ + c->vc_visible_origin = c->vc_origin; + else { + int p = c->vc_visible_origin - vga_vram_base; + int margin = c->vc_rows/4 * c->vc_size_row; + p += lines * c->vc_size_row; + if (lines < 0 && p < margin) + p = 0; + c->vc_visible_origin = p + vga_vram_base; + if (lines > 0 && c->vc_visible_origin > c->vc_origin - margin) + c->vc_visible_origin = c->vc_origin; + } + vga_set_mem_top(c); + return 1; } +static int vgacon_set_origin(struct vc_data *c) +{ + if (vga_is_gfx || /* We don't play origin tricks in graphic modes */ + (console_blanked && !vga_palette_blanked)) /* Nor we write to blanked screens */ + return 0; + c->vc_origin = c->vc_visible_origin = vga_vram_base; + vga_set_mem_top(c); + return 1; +} -__initfunc(static int vgacon_show_logo( void )) +static void vgacon_save_screen(struct vc_data *c) { - int height = 0; - char *p; - - printk(linux_serial_image); - for (p = linux_serial_image; *p; p++) - if (*p == '\n') - height++; - return height; + static int vga_bootup_console = 0; + + if (!vga_bootup_console) { + /* This is a gross hack, but here is the only place we can + * set bootup console parameters without messing up generic + * console initialization routines. + */ + vga_bootup_console = 1; + c->vc_x = ORIG_X; + c->vc_y = ORIG_Y; + } + if (vga_is_gfx) + return; + scr_memcpyw_from((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin, c->vc_screenbuf_size); } +static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, int lines) +{ + unsigned long oldo; + unsigned int delta; + + if (t || b != c->vc_rows || vga_is_gfx) + return 0; + + if (c->vc_origin != c->vc_visible_origin) + vgacon_scrolldelta(c, 0); + + if (!vga_hardscroll_enabled || lines >= c->vc_rows/2) + return 0; + + oldo = c->vc_origin; + delta = lines * c->vc_size_row; + if (dir == SM_UP) { + if (c->vc_scr_end + delta >= vga_vram_end) { + scr_memcpyw((u16 *)vga_vram_base, + (u16 *)(oldo + delta), + c->vc_screenbuf_size - delta); + c->vc_origin = vga_vram_base; + } else + c->vc_origin += delta; + scr_memsetw((u16 *)(c->vc_origin + c->vc_screenbuf_size - delta), c->vc_video_erase_char, delta); + } else { + if (oldo - delta < vga_vram_base) { + scr_memmovew((u16 *)(vga_vram_end - c->vc_screenbuf_size + delta), + (u16 *)oldo, + c->vc_screenbuf_size - delta); + c->vc_origin = vga_vram_end - c->vc_screenbuf_size; + } else + c->vc_origin -= delta; + c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size; + scr_memsetw((u16 *)(c->vc_origin), c->vc_video_erase_char, delta); + } + c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size; + c->vc_visible_origin = c->vc_origin; + vga_set_mem_top(c); + c->vc_pos = (c->vc_pos - oldo) + c->vc_origin; + return 1; +} /* * The console `switch' structure for the VGA based console */ +static int vgacon_dummy(struct vc_data *c) +{ + return 0; +} + +#define DUMMY (void *) vgacon_dummy + 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_set_mode + vgacon_startup, + vgacon_init, + vgacon_deinit, + DUMMY, /* con_clear */ + DUMMY, /* con_putc */ + DUMMY, /* con_putcs */ + vgacon_cursor, + vgacon_scroll, /* con_scroll */ + DUMMY, /* con_bmove */ + vgacon_switch, + vgacon_blank, + vgacon_font_op, + vgacon_set_palette, + vgacon_scrolldelta, + vgacon_set_origin, + vgacon_save_screen, + vgacon_build_attr, + vgacon_invert_region }; diff --git a/drivers/video/vgafb.c b/drivers/video/vgafb.c new file mode 100644 index 000000000..c8fc4c9a0 --- /dev/null +++ b/drivers/video/vgafb.c @@ -0,0 +1,764 @@ +/* + * linux/drivers/video/vgafb.c -- VGA frame buffer device + * + * Created 28 Mar 1998 by Geert Uytterhoeven + * Hardware cursor support added on 14 Apr 1998 by Emmanuel Marty + * + * This file is heavily based on vgacon.c. Read about its contributors there. + * + * 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. + */ + + + + +/* KNOWN PROBLEMS/TO DO ===================================================== * + * + * - add support for loadable fonts and VESA blanking + * + * - for now only VGA _text_ mode is supported + * + * KNOWN PROBLEMS/TO DO ==================================================== */ + + +#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/ioport.h> +#include <linux/init.h> +#include <linux/selection.h> +#include <linux/console.h> +#include <linux/vt_kern.h> + +#include <asm/io.h> +#include <asm/uaccess.h> + +#include "fbcon.h" +#include "fbcon-vga.h" + + +#define BLANK 0x0020 + +#define CAN_LOAD_EGA_FONTS /* undefine if the user must not do this */ +#define CAN_LOAD_PALETTE /* undefine if the user must not do this */ + +#define dac_reg (0x3c8) +#define dac_val (0x3c9) + +#ifdef __powerpc__ +#define VGA_OFFSET _ISA_MEM_BASE; +#else +#define VGA_OFFSET 0x0 +#endif + + +static int currcon = 0; +static struct display disp; +static struct fb_info fb_info; +static struct { u_char red, green, blue, pad; } palette[16]; + +static struct fb_fix_screeninfo fb_fix = { { 0, } }; +static struct fb_var_screeninfo fb_var = { 0, }; + + +/* Description of the hardware situation */ +static unsigned char vga_video_type; +static unsigned long vga_video_mem_base; /* Base of video memory */ +static unsigned long vga_video_mem_term; /* End of video memory */ +static u16 vga_video_port_reg; /* Video register select port */ +static u16 vga_video_port_val; /* Video register value port */ +static unsigned long vga_video_num_columns; /* Number of text columns */ +static unsigned long vga_video_num_lines; /* Number of text lines */ +static int vga_can_do_color = 0; + + + /* + * VGA screen access + */ + +static inline void vga_writew(u16 val, u16 *addr) +{ +#ifdef __powerpc__ + st_le16(addr, val); +#else + writew(val, (unsigned long)addr); +#endif /* !__powerpc__ */ +} + +static inline u16 vga_readw(u16 *addr) +{ +#ifdef __powerpc__ + return ld_le16(addr); +#else + return readw((unsigned long)addr); +#endif /* !__powerpc__ */ +} + +/* + * By replacing the four outb_p with two back to back outw, we can reduce + * the window of opportunity to see text mislocated to the RHS of the + * console during heavy scrolling activity. However there is the remote + * possibility that some pre-dinosaur hardware won't like the back to back + * I/O. Since the Xservers get away with it, we should be able to as well. + */ +static inline void write_vga(unsigned char reg, unsigned int val) +{ +#ifndef SLOW_VGA + unsigned int v1, v2; + + v1 = reg + (val & 0xff00); + v2 = reg + 1 + ((val << 8) & 0xff00); + outw(v1, vga_video_port_reg); + outw(v2, vga_video_port_reg); +#else + outb_p(reg, vga_video_port_reg); + outb_p(val >> 8, vga_video_port_val); + outb_p(reg+1, vga_video_port_reg); + outb_p(val & 0xff, vga_video_port_val); +#endif +} + +static inline void vga_set_origin(unsigned short location) +{ + write_vga(12, location >> 1); +} + +static inline void vga_set_cursor(int location) +{ + write_vga(14, location >> 1); +} + +static void vga_set_split(unsigned short linenum) +{ + unsigned long flags; + unsigned char overflow, fontsize; + + if (vga_video_type != VIDEO_TYPE_VGAC) { + return; + } + + save_flags(flags); cli(); + + outb_p(0x07, vga_video_port_reg); + overflow = inb_p(vga_video_port_val); + + outb_p(0x09, vga_video_port_reg); + fontsize = inb_p(vga_video_port_val); + + overflow &= ~0x10; overflow |= (linenum & 0x100) ? 0x10 : 0; + fontsize &= ~0x40; fontsize |= (linenum & 0x200) ? 0x40 : 0; + linenum &= 0xff; + + outb_p(0x18, vga_video_port_reg); + outb_p(linenum, vga_video_port_val); + + outb_p(0x07, vga_video_port_reg); + outb_p(overflow, vga_video_port_val); + + outb_p(0x09, vga_video_port_reg); + outb_p(fontsize, vga_video_port_val); + + restore_flags(flags); +} + +static inline void vga_set_palreg(u_int regno, u_int red, + u_int green, u_int blue) +{ + unsigned long flags; + + save_flags(flags); cli(); + + outb_p(regno, dac_reg); + outb_p(red, dac_val); + outb_p(green, dac_val); + outb_p(blue, dac_val); + + restore_flags(flags); +} + + + /* + * Interface used by the world + */ + +static int vgafb_open(struct fb_info *info, int user); +static int vgafb_release(struct fb_info *info, int user); +static int vgafb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int vgafb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int vgafb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int vgafb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int vgafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int vgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int vgafb_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 + */ + +void vgafb_init(void); +void vgafb_setup(char *options, int *ints); +static int vgafbcon_switch(int con, struct fb_info *info); +static int vgafbcon_updatevar(int con, struct fb_info *info); +static void vgafbcon_blank(int blank, struct fb_info *info); + + + /* + * VGA text console with hardware cursor + */ + +static struct display_switch fbcon_vgafb; + + + /* + * Internal routines + */ + +static int vgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, + u_int *transp, struct fb_info *info); +static int vgafb_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 vgafb_ops = { + vgafb_open, vgafb_release, vgafb_get_fix, vgafb_get_var, vgafb_set_var, + vgafb_get_cmap, vgafb_set_cmap, vgafb_pan_display, vgafb_ioctl +}; + + + /* + * Open/Release the frame buffer device + */ + +static int vgafb_open(struct fb_info *info, int user) + +{ + /* + * Nothing, only a usage count for the moment + */ + + MOD_INC_USE_COUNT; + return(0); +} + +static int vgafb_release(struct fb_info *info, int user) +{ + MOD_DEC_USE_COUNT; + return(0); +} + + + /* + * Get the Fixed Part of the Display + */ + +static int vgafb_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 vgafb_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 vgafb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct display *display; + int oldbpp = -1, err; + + if (con >= 0) + display = &fb_display[con]; + else + display = &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 || + var->nonstd || !(var->accel_flags & FB_ACCELF_TEXT) || + (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) + return -EINVAL; + memcpy(var, &fb_var, sizeof(fb_var)); + + if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { + oldbpp = display->var.bits_per_pixel; + display->var = *var; + vga_set_origin(var->yoffset/video_font_height*fb_fix.line_length); + } + + 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 vgafb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + if (var->xoffset || var->yoffset+var->yres > var->yres_virtual) + return -EINVAL; + + vga_set_origin(var->yoffset/video_font_height*fb_fix.line_length); + return 0; +} + + + /* + * Get the Colormap + */ + +static int vgafb_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, vgafb_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 vgafb_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? */ + err = fb_set_cmap(cmap, &fb_display[con].var, kspc, vgafb_setcolreg, + info); + return err; + } else + fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); + return 0; +} + + +static int vgafb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info) +{ + return -EINVAL; +} + + + /* + * Move hardware vga cursor + */ + +static void fbcon_vgafb_cursor(struct display *p, int mode, int x, int y) +{ + switch (mode) { + case CM_ERASE: + vga_set_cursor(vga_video_mem_term - vga_video_mem_base - 1); + break; + + case CM_MOVE: + case CM_DRAW: + vga_set_cursor(y*p->next_line + (x << 1)); + break; + } +} + + + /* + * Initialisation + */ + +__initfunc(void vgafb_init(void)) +{ + u16 saved; + u16 *p; + + if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB) + return; + + vga_video_num_lines = ORIG_VIDEO_LINES; + vga_video_num_columns = ORIG_VIDEO_COLS; + + if (ORIG_VIDEO_MODE == 7) { /* Is this a monochrome display? */ + vga_video_mem_base = 0xb0000 + VGA_OFFSET; + vga_video_port_reg = 0x3b4; + vga_video_port_val = 0x3b5; + if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { + vga_video_type = VIDEO_TYPE_EGAM; + vga_video_mem_term = 0xb8000 + VGA_OFFSET; + strcpy(fb_fix.id, "EGA+"); + request_region(0x3b0, 16, "ega"); + } else { + vga_video_type = VIDEO_TYPE_MDA; + vga_video_mem_term = 0xb1000 + VGA_OFFSET; + strcpy(fb_fix.id, "*MDA"); + request_region(0x3b0, 12, "mda"); + request_region(0x3bf, 1, "mda"); + } + } else { /* If not, it is color. */ + vga_can_do_color = 1; + vga_video_mem_base = 0xb8000 + VGA_OFFSET; + vga_video_port_reg = 0x3d4; + vga_video_port_val = 0x3d5; + if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { + int i; + + vga_video_mem_term = 0xc0000 + VGA_OFFSET; + + if (!ORIG_VIDEO_ISVGA) { + vga_video_type = VIDEO_TYPE_EGAC; + strcpy(fb_fix.id, "EGA"); + request_region(0x3c0, 32, "ega"); + } else { + vga_video_type = VIDEO_TYPE_VGAC; + strcpy(fb_fix.id, "VGA+"); + request_region(0x3c0, 32, "vga+"); + +#ifdef VGA_CAN_DO_64KB + /* + * get 64K rather than 32K of video RAM. + * This doesn't actually work on all "VGA" + * controllers (it seems like setting MM=01 + * and COE=1 isn't necessarily a good idea) + */ + vga_video_mem_base = 0xa0000 + VGA_OFFSET; + vga_video_mem_term = 0xb0000 + VGA_OFFSET; + outb_p(6, 0x3ce); + outb_p(6, 0x3cf); +#endif + + /* + * Normalise the palette registers, to point + * the 16 screen colours to the first 16 + * DAC entries. + */ + + for (i = 0; i < 16; i++) { + inb_p(0x3da); + outb_p(i, 0x3c0); + outb_p(i, 0x3c0); + } + outb_p(0x20, 0x3c0); + + /* now set the DAC registers back to their + * default values */ + + for (i = 0; i < 16; i++) { + vga_set_palreg(color_table[i], default_red[i], + default_grn[i], default_blu[i]); + } + } + } else { + vga_video_type = VIDEO_TYPE_CGA; + vga_video_mem_term = 0xba000 + VGA_OFFSET; + strcpy(fb_fix.id, "*CGA"); + request_region(0x3d4, 2, "cga"); + } + } + + /* + * Find out if there is a graphics card present. + * Are there smarter methods around? + */ + p = (u16 *)vga_video_mem_base; + saved = vga_readw(p); + vga_writew(0xAA55, p); + if (vga_readw(p) != 0xAA55) { + vga_writew(saved, p); + return; + } + vga_writew(0x55AA, p); + if (vga_readw(p) != 0x55AA) { + vga_writew(saved, p); + return; + } + vga_writew(saved, p); + + if (vga_video_type == VIDEO_TYPE_VGAC + || vga_video_type == VIDEO_TYPE_EGAC + || vga_video_type == VIDEO_TYPE_EGAM) { + video_font_height = ORIG_VIDEO_POINTS; + } else { + video_font_height = 16; + } + + /* This may be suboptimal but is a safe bet - go with it */ + video_scan_lines = video_font_height * vga_video_num_lines; + + fb_fix.smem_start = (char *) vga_video_mem_base; + fb_fix.smem_len = vga_video_mem_term - vga_video_mem_base; + fb_fix.type = FB_TYPE_TEXT; + fb_fix.type_aux = vga_can_do_color ? FB_AUX_TEXT_CGA : FB_AUX_TEXT_MDA; + fb_fix.visual = FB_VISUAL_PSEUDOCOLOR; + fb_fix.xpanstep = 0; + fb_fix.ypanstep = video_font_height; + fb_fix.ywrapstep = 0; + fb_fix.line_length = 2*vga_video_num_columns; + fb_fix.mmio_start = NULL; + fb_fix.mmio_len = 0; + fb_fix.accel = FB_ACCEL_NONE; + + fb_var.xres = vga_video_num_columns*8; + fb_var.yres = vga_video_num_lines*video_font_height; + fb_var.xres_virtual = fb_var.xres; + /* the cursor is put at the end of the video memory, hence the -2 */ + fb_var.yres_virtual = ((fb_fix.smem_len-2)/fb_fix.line_length)* + video_font_height; + + fb_var.xoffset = fb_var.yoffset = 0; + fb_var.bits_per_pixel = vga_can_do_color ? 4 : 1; + fb_var.grayscale = !vga_can_do_color; + fb_var.red.offset = 0; + fb_var.red.length = 6; + fb_var.red.msb_right = 0; + fb_var.green.offset = 0; + fb_var.green.length = 6; + fb_var.green.msb_right = 0; + fb_var.blue.offset = 0; + fb_var.blue.length = 6; + fb_var.blue.msb_right = 0; + fb_var.transp.offset = 0; + fb_var.transp.length = 0; + fb_var.transp.msb_right = 0; + fb_var.nonstd = 0; + fb_var.activate = 0; + fb_var.height = fb_var.width = -1; + fb_var.accel_flags = FB_ACCELF_TEXT; + fb_var.pixclock = 39722; /* 25.175 MHz */ + fb_var.left_margin = 40; + fb_var.right_margin = 24; + fb_var.upper_margin = 39; + fb_var.lower_margin = 9; + fb_var.hsync_len = 96; + fb_var.vsync_len = 2; + 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 = NULL; + disp.cmap.green = NULL; + disp.cmap.blue = NULL; + disp.cmap.transp = NULL; + +#ifdef __i386__ + disp.screen_base = ioremap((unsigned long) fb_fix.smem_start, + fb_fix.smem_len); +#else + disp.screen_base = bus_to_virt((unsigned long) fb_fix.smem_start); +#endif + disp.visual = fb_fix.visual; + disp.type = fb_fix.type; + disp.type_aux = fb_fix.type_aux; + disp.ypanstep = fb_fix.ypanstep; + disp.ywrapstep = fb_fix.ywrapstep; + disp.line_length = fb_fix.line_length; + disp.can_soft_blank = vga_can_do_color; + disp.inverse = 0; + disp.dispsw = &fbcon_vgafb; + + strcpy(fb_info.modename, fb_fix.id); + fb_info.node = -1; + fb_info.fbops = &vgafb_ops; + fb_info.disp = &disp; + fb_info.fontname[0] = '\0'; + fb_info.changevar = NULL; + fb_info.switch_con = &vgafbcon_switch; + fb_info.updatevar = &vgafbcon_updatevar; + fb_info.blank = &vgafbcon_blank; + + vgafb_set_var(&fb_var, -1, &fb_info); + + if (register_framebuffer(&fb_info) < 0) + return; + + printk("fb%d: VGA frame buffer device, using %dK of video memory\n", + GET_FB_IDX(fb_info.node), fb_fix.smem_len>>10); +} + +__initfunc(void vgafb_setup(char *options, int *ints)) +{ + /* nothing yet */ +} + + /* + * Update the `var' structure (called by fbcon.c) + */ + +static int vgafbcon_updatevar(int con, struct fb_info *info) +{ + if (con == currcon) { + struct fb_var_screeninfo *var = &fb_display[currcon].var; + + /* hardware scrolling */ + + vga_set_origin(var->yoffset / video_font_height * + fb_fix.line_length); + + vga_set_split(var->yres - ((var->vmode & FB_VMODE_YWRAP) ? + var->yoffset+1 : 0)); + } + + return 0; +} + +static int vgafbcon_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, + vgafb_getcolreg, info); + + currcon = con; + /* Install new colormap */ + do_install_cmap(con, info); + vgafbcon_updatevar(con, info); + return 0; +} + + /* + * Blank the display. + */ + +static void vgafbcon_blank(int blank, struct fb_info *info) +{ + int i; + + if (blank) + for (i = 0; i < 16; i++) { + vga_set_palreg(i, 0, 0, 0); + } + else + for (i = 0; i < 16; i++) { + vga_set_palreg(i, palette[i].red, palette[i].green, + palette[i].blue); + } +} + + + /* + * Read a single color register and split it into + * colors/transparent. Return != 0 for invalid regno. + */ + +static int vgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, + u_int *transp, struct fb_info *info) +{ + if (regno > 15) + 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 vgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + if (regno > 15) + return 1; + palette[regno].red = red; + palette[regno].green = green; + palette[regno].blue = blue; + + vga_set_palreg(regno, red, green, blue); + + 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, + vgafb_setcolreg, info); + else + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), + &fb_display[con].var, 1, vgafb_setcolreg, + info); +} + + + /* + * VGA text console with hardware cursor + */ + +static struct display_switch fbcon_vgafb = { + fbcon_vga_setup, fbcon_vga_bmove, fbcon_vga_clear, fbcon_vga_putc, + fbcon_vga_putcs, fbcon_vga_revc, fbcon_vgafb_cursor, NULL, NULL, + FONTWIDTH(8) +}; + + +#ifdef MODULE +int init_module(void) +{ + vgafb_init(); + return 0; +} + +void cleanup_module(void) +{ + unregister_framebuffer(&fb_info); +} +#endif /* MODULE */ diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c index d08e4a722..927fbb46d 100644 --- a/drivers/video/virgefb.c +++ b/drivers/video/virgefb.c @@ -16,7 +16,6 @@ #undef VIRGEFBDEBUG -#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -90,6 +89,7 @@ struct virgefb_par { int xres; int yres; int bpp; + int accel; }; static struct virgefb_par current_par; @@ -163,49 +163,49 @@ 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, + 0, 0, -1, -1, FB_ACCELF_TEXT, 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, + 0, 0, -1, -1, FB_ACCELF_TEXT, 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, + 0, 0, -1, -1, FB_ACCELF_TEXT, 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, + 0, 0, -1, -1, FB_ACCELF_TEXT, 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, + 0, 0, -1, -1, FB_ACCELF_TEXT, 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, + 0, 0, -1, -1, FB_ACCELF_TEXT, 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, + 0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2, FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED } } @@ -237,8 +237,8 @@ static struct fb_var_screeninfo virgefb_default; 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_open(struct fb_info *info, int user); +static int virgefb_release(struct fb_info *info, int user); 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 @@ -259,7 +259,7 @@ static int virgefb_ioctl(struct inode *inode, struct file *file, u_int cmd, * Interface to the low level console driver */ -unsigned long virgefb_init(unsigned long mem_start); +void virgefb_init(void); 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); @@ -269,7 +269,7 @@ static void Cyberfb_blank(int blank, struct fb_info *info); * Text console acceleration */ -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 static struct display_switch fbcon_virge8; #endif @@ -370,12 +370,11 @@ static int Cyber_init(void) static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, struct virgefb_par *par) { - int i; - + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, virgefb_name); - fix->smem_start = (caddr_t)CyberMem; + fix->smem_start = (char *)CyberMem; fix->smem_len = CyberSize; - fix->mmio_start = (unsigned char *)CyberRegs; + fix->mmio_start = (char *)CyberRegs; fix->mmio_len = 0x10000; /* TODO: verify this for the CV64/3D */ fix->type = FB_TYPE_PACKED_PIXELS; @@ -389,10 +388,7 @@ static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, fix->ypanstep = 0; fix->ywrapstep = 0; fix->line_length = 0; - - for (i = 0; i < arraysize(fix->reserved); i++) - fix->reserved[i] = 0; - + fix->accel = FB_ACCEL_S3_VIRGE; return(0); } @@ -409,6 +405,10 @@ static int Cyber_decode_var(struct fb_var_screeninfo *var, par->xres = var->xres; par->yres = var->yres; par->bpp = var->bits_per_pixel; + if (var->accel_flags & FB_ACCELF_TEXT) + par->accel = FB_ACCELF_TEXT; + else + par->accel = 0; #else if (Cyberfb_Cyber8) { par->xres = VIRGE8_WIDTH; @@ -432,8 +432,7 @@ static int Cyber_decode_var(struct fb_var_screeninfo *var, static int Cyber_encode_var(struct fb_var_screeninfo *var, struct virgefb_par *par) { - int i; - + memset(var, 0, sizeof(struct fb_var_screeninfo)); var->xres = par->xres; var->yres = par->yres; var->xres_virtual = par->xres; @@ -470,7 +469,7 @@ static int Cyber_encode_var(struct fb_var_screeninfo *var, var->height = -1; var->width = -1; - var->accel = FB_ACCEL_S3VIRGE; + var->accel_flags = (par->accel && par->bpp == 8) ? FB_ACCELF_TEXT : 0; DPRINTK("accel CV64/3D\n"); var->vmode = FB_VMODE_NONINTERLACED; @@ -489,9 +488,6 @@ static int Cyber_encode_var(struct fb_var_screeninfo *var, var->hsync_len = 112; var->vsync_len = 2; - for (i = 0; i < arraysize(var->reserved); i++) - var->reserved[i] = 0; - return(0); } @@ -768,7 +764,7 @@ static void do_install_cmap(int con, struct fb_info *info) * Open/Release the frame buffer device */ -static int virgefb_open(struct fb_info *info) +static int virgefb_open(struct fb_info *info, int user) { /* * Nothing, only a usage count for the moment @@ -778,7 +774,7 @@ static int virgefb_open(struct fb_info *info) return(0); } -static int virgefb_release(struct fb_info *info) +static int virgefb_release(struct fb_info *info, int user) { MOD_DEC_USE_COUNT; return(0); @@ -841,7 +837,7 @@ static void virgefb_set_disp(int con, struct fb_info *info) virgefb_get_fix(&fix, con, info); if (con == -1) con = 0; - display->screen_base = (u_char *)fix.smem_start; + display->screen_base = fix.smem_start; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; @@ -850,12 +846,16 @@ static void virgefb_set_disp(int con, struct fb_info *info) display->can_soft_blank = 1; display->inverse = Cyberfb_inverse; switch (display->var.bits_per_pixel) { -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 case 8: - display->dispsw = &fbcon_virge8; + if (display->var.accel_flags & FB_ACCELF_TEXT) { + display->dispsw = &fbcon_virge8; +#warning FIXME: We should reinit the graphics engine here + } else + display->dispsw = &fbcon_virge8; break; #endif -#ifdef CONFIG_FBCON_CFB16 +#ifdef FBCON_HAS_CFB16 case 16: display->dispsw = &fbcon_cfb16; break; @@ -874,7 +874,7 @@ static void virgefb_set_disp(int con, struct fb_info *info) static int virgefb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) { - int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp; + int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel; if ((err = do_fb_set_var(var, con == currcon))) return(err); @@ -884,11 +884,13 @@ static int virgefb_set_var(struct fb_var_screeninfo *var, int con, oldvxres = fb_display[con].var.xres_virtual; oldvyres = fb_display[con].var.yres_virtual; oldbpp = fb_display[con].var.bits_per_pixel; + oldaccel = fb_display[con].var.accel_flags; 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) { + oldbpp != var->bits_per_pixel || + oldaccel != var->accel_flags) { virgefb_set_disp(con, info); (*fb_info.changevar)(con); fb_alloc_cmap(&fb_display[con].cmap, 0, 0); @@ -969,7 +971,7 @@ static int virgefb_ioctl(struct inode *inode, struct file *file, 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 + virgefb_pan_display, virgefb_ioctl }; @@ -1007,15 +1009,14 @@ __initfunc(void virgefb_setup(char *options, int *ints)) * Initialization */ -__initfunc(unsigned long virgefb_init(unsigned long mem_start)) +__initfunc(void virgefb_init(void)) { - 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; + return; cd = zorro_get_board (CyberKey); zorro_config_board (CyberKey, 0); @@ -1030,22 +1031,17 @@ __initfunc(unsigned long virgefb_init(unsigned long mem_start)) CyberMem = ZTWO_VADDR(board_addr); printk("CV3D detected running in Z2 mode ... not yet supported!\n"); - return -ENODEV; + return; } else { - CyberVGARegs = kernel_map(board_addr +0x0c000000, - 0x00010000, - KERNELMAP_NOCACHE_SER, - &mem_start); + CyberVGARegs = kernel_map(board_addr +0x0c000000, 0x00010000, + KERNELMAP_NOCACHE_SER, NULL); 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); + KERNELMAP_NOCACHE_SER, NULL); + CyberMem = kernel_map(board_addr + 0x04800000, 0x00400000, + KERNELMAP_NOCACHE_SER, NULL); printk("CV3D detected running in Z3 mode\n"); } @@ -1060,10 +1056,6 @@ __initfunc(unsigned long virgefb_init(unsigned long mem_start)) 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); @@ -1073,13 +1065,14 @@ __initfunc(unsigned long virgefb_init(unsigned long mem_start)) virgefb_set_disp(-1, &fb_info); do_install_cmap(0, &fb_info); + if (register_framebuffer(&fb_info) < 0) + return; + 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; } @@ -1145,7 +1138,7 @@ __initfunc(static int get_video_mode(const char *name)) * Text console acceleration */ -#ifdef CONFIG_FBCON_CFB8 +#ifdef FBCON_HAS_CFB8 static void fbcon_virge8_bmove(struct display *p, int sy, int sx, int dy, int dx, int height, int width) { @@ -1169,7 +1162,8 @@ static void fbcon_virge8_clear(struct vc_data *conp, struct display *p, int sy, static struct display_switch fbcon_virge8 = { fbcon_cfb8_setup, fbcon_virge8_bmove, fbcon_virge8_clear, fbcon_cfb8_putc, - fbcon_cfb8_putcs, fbcon_cfb8_revc + fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins, + FONTWIDTH(8) }; #endif @@ -1177,7 +1171,8 @@ static struct display_switch fbcon_virge8 = { #ifdef MODULE int init_module(void) { - return(virgefb_init(NULL)); + virgefb_init(); + return 0; } void cleanup_module(void) |