summaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Config.in74
-rw-r--r--drivers/video/Makefile123
-rw-r--r--drivers/video/S3triofb.c50
-rw-r--r--drivers/video/acornfb.c38
-rw-r--r--drivers/video/amifb.c152
-rw-r--r--drivers/video/atafb.c137
-rw-r--r--drivers/video/ati-gt.h203
-rw-r--r--drivers/video/ati-gx.h122
-rw-r--r--drivers/video/ati-vt.h147
-rw-r--r--drivers/video/aty.h16
-rw-r--r--drivers/video/atyfb.c1188
-rw-r--r--drivers/video/bwtwofb.c22
-rw-r--r--drivers/video/cgfourteenfb.c384
-rw-r--r--drivers/video/cgsixfb.c197
-rw-r--r--drivers/video/cgthreefb.c8
-rw-r--r--drivers/video/chipsfb.c239
-rw-r--r--drivers/video/clgenfb.c208
-rw-r--r--drivers/video/controlfb.c191
-rw-r--r--drivers/video/controlfb.h8
-rw-r--r--drivers/video/creatorfb.c419
-rw-r--r--drivers/video/cvppcfb.c606
-rw-r--r--drivers/video/cyberfb.c2066
-rw-r--r--drivers/video/cyberfb.h444
-rw-r--r--drivers/video/dnfb.c5
-rw-r--r--drivers/video/fbcmap.c22
-rw-r--r--drivers/video/fbcon-afb.c52
-rw-r--r--drivers/video/fbcon-afb.h27
-rw-r--r--drivers/video/fbcon-cfb16.c192
-rw-r--r--drivers/video/fbcon-cfb16.h29
-rw-r--r--drivers/video/fbcon-cfb2.c30
-rw-r--r--drivers/video/fbcon-cfb2.h27
-rw-r--r--drivers/video/fbcon-cfb24.c210
-rw-r--r--drivers/video/fbcon-cfb24.h29
-rw-r--r--drivers/video/fbcon-cfb32.c192
-rw-r--r--drivers/video/fbcon-cfb32.h29
-rw-r--r--drivers/video/fbcon-cfb4.c36
-rw-r--r--drivers/video/fbcon-cfb4.h27
-rw-r--r--drivers/video/fbcon-cfb8.c127
-rw-r--r--drivers/video/fbcon-cfb8.h28
-rw-r--r--drivers/video/fbcon-ilbm.c52
-rw-r--r--drivers/video/fbcon-ilbm.h27
-rw-r--r--drivers/video/fbcon-iplan2p2.c102
-rw-r--r--drivers/video/fbcon-iplan2p2.h27
-rw-r--r--drivers/video/fbcon-iplan2p4.c102
-rw-r--r--drivers/video/fbcon-iplan2p4.h27
-rw-r--r--drivers/video/fbcon-iplan2p8.c104
-rw-r--r--drivers/video/fbcon-iplan2p8.h27
-rw-r--r--drivers/video/fbcon-mac.c60
-rw-r--r--drivers/video/fbcon-mac.h27
-rw-r--r--drivers/video/fbcon-mfb.c77
-rw-r--r--drivers/video/fbcon-mfb.h27
-rw-r--r--drivers/video/fbcon-vga.c4
-rw-r--r--drivers/video/fbcon-vga.h27
-rw-r--r--drivers/video/fbcon.c767
-rw-r--r--drivers/video/fbcon.h414
-rw-r--r--drivers/video/fbgen.c23
-rw-r--r--drivers/video/fbmem.c725
-rw-r--r--drivers/video/font.h51
-rw-r--r--drivers/video/font_6x11.c2
-rw-r--r--drivers/video/font_8x16.c2
-rw-r--r--drivers/video/font_8x8.c2
-rw-r--r--drivers/video/font_acorn_8x8.c2
-rw-r--r--drivers/video/font_pearl_8x8.c2
-rw-r--r--drivers/video/font_sun12x22.c2
-rw-r--r--drivers/video/font_sun8x16.c2
-rw-r--r--drivers/video/fonts.c4
-rw-r--r--drivers/video/hpfb.c9
-rw-r--r--drivers/video/iga.h27
-rw-r--r--drivers/video/igafb.c783
-rw-r--r--drivers/video/imsttfb.c1818
-rw-r--r--drivers/video/leofb.c582
-rw-r--r--drivers/video/macfb.c16
-rw-r--r--drivers/video/macmodes.c6
-rw-r--r--drivers/video/macmodes.h60
-rw-r--r--drivers/video/matroxfb.c5381
-rw-r--r--drivers/video/mdacon.c617
-rw-r--r--drivers/video/mdafb.c480
-rw-r--r--drivers/video/offb.c597
-rw-r--r--drivers/video/platinumfb.c1190
-rw-r--r--drivers/video/platinumfb.h33
-rw-r--r--drivers/video/promcon.c4
-rw-r--r--drivers/video/retz3fb.c726
-rw-r--r--drivers/video/retz3fb.h28
-rw-r--r--drivers/video/s3blit.h74
-rw-r--r--drivers/video/sbusfb.c144
-rw-r--r--drivers/video/sbusfb.h116
-rw-r--r--drivers/video/skeletonfb.c132
-rw-r--r--drivers/video/tcxfb.c31
-rw-r--r--drivers/video/tgafb.c100
-rw-r--r--drivers/video/valkyriefb.c896
-rw-r--r--drivers/video/valkyriefb.h186
-rw-r--r--drivers/video/vesafb.c311
-rw-r--r--drivers/video/vfb.c58
-rw-r--r--drivers/video/vgacon.c50
-rw-r--r--drivers/video/vgafb.c764
-rw-r--r--drivers/video/virgefb.c104
96 files changed, 19210 insertions, 6905 deletions
diff --git a/drivers/video/Config.in b/drivers/video/Config.in
index f3cb63093..7c1887c1c 100644
--- a/drivers/video/Config.in
+++ b/drivers/video/Config.in
@@ -22,6 +22,7 @@ if [ "$CONFIG_FB" = "y" ]; then
tristate 'Amiga CyberVision support' CONFIG_FB_CYBER
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool 'Amiga CyberVision3D support (experimental)' CONFIG_FB_VIRGE
+ bool 'Amiga CyberVisionPPC support (experimental)' CONFIG_FB_CVPPC
tristate 'Amiga RetinaZ3 support' CONFIG_FB_RETINAZ3
tristate 'Amiga CLgen driver' CONFIG_FB_CLGEN
fi
@@ -35,9 +36,9 @@ if [ "$CONFIG_FB" = "y" ]; then
if [ "$CONFIG_FB_OF" = "y" ]; then
bool 'Apple "control" display support' CONFIG_FB_CONTROL
bool 'Apple "platinum" display support' CONFIG_FB_PLATINUM
-# bool 'Apple "valkyrie" display support' CONFIG_FB_VALKYRIE
+ bool '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 'IMS Twin Turbo display support' CONFIG_FB_IMSTT
bool 'Chips 65550 display support' CONFIG_FB_CT65550
bool 'S3 Trio display support' CONFIG_FB_S3TRIO
fi
@@ -48,21 +49,24 @@ if [ "$CONFIG_FB" = "y" ]; then
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 'Deprecated almost-VGA support (text only - use normal VGA console instead)' 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 [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ if [ "$CONFIG_PCI" != "n" ]; then
+ tristate 'Matrox acceleration' CONFIG_FB_MATROX
+ if [ "$CONFIG_FB_MATROX" != "n" ]; then
+ bool ' Millennium I/II support' CONFIG_FB_MATROX_MILLENIUM
+ bool ' Mystique support' CONFIG_FB_MATROX_MYSTIQUE
+ bool ' G100/G200 support' CONFIG_FB_MATROX_G100
+ bool ' Multihead support' CONFIG_FB_MATROX_MULTIHEAD
+ fi
+ bool 'ATI Mach64 display support' CONFIG_FB_ATY
+ fi
fi
if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
bool 'SBUS and UPA framebuffers' CONFIG_FB_SBUS
@@ -75,6 +79,16 @@ if [ "$CONFIG_FB" = "y" ]; then
bool ' CGthree support' CONFIG_FB_CGTHREE
if [ "$ARCH" = "sparc" ]; then
bool ' TCX (SS4/SS5 only) support' CONFIG_FB_TCX
+ bool ' CGfourteen (SX) support' CONFIG_FB_CGFOURTEEN
+ fi
+ bool ' Leo (ZX) support' CONFIG_FB_LEO
+ fi
+ fi
+ if [ "$ARCH" = "sparc" ]; then
+ if [ "$CONFIG_PCI" != "n" ]; then
+ bool 'PCI framebuffers' CONFIG_FB_PCI
+ if [ "$CONFIG_FB_PCI" != "n" ]; then
+ bool ' IGA 168x display support' CONFIG_FB_IGA
fi
fi
fi
@@ -139,48 +153,68 @@ if [ "$CONFIG_FB" = "y" ]; then
"$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" -o \
- "$CONFIG_FB_G364" = "y" ]; then
+ "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
+ "$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_G364" = "y" -o \
+ "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
+ "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
+ "$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "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_ATY" = "m" -o "$CONFIG_FB_MAC" = "m" -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
+ "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
+ "$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_G364" = "m" -o \
+ "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
+ "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
+ "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "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
+ "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
+ "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
+ "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
+ "$CONFIG_FB_MATROX" = "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
+ "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
+ "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
+ "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
+ "$CONFIG_FB_MATROX" = "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
+ "$CONFIG_FB_CLGEN" = "y" -o "$CONFIG_FB_VESA" = "y" -o \
+ "$CONFIG_FB_MATROX" = "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
+ "$CONFIG_FB_CLGEN" = "m" -o "$CONFIG_FB_VESA" = "m" -o \
+ "$CONFIG_FB_MATROX" = "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
+ "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
+ "$CONFIG_FB_TGA" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
+ "$CONFIG_FB_MATROX" = "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
+ "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
+ "$CONFIG_FB_TGA" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
+ "$CONFIG_FB_MATROX" = "m" ]; then
define_bool CONFIG_FBCON_CFB32 m
fi
fi
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 27365240a..8001bdf15 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -9,9 +9,6 @@
# parent makes..
#
-GSPA = gspa
-GSPH2C = gspahextoc
-
L_TARGET := video.a
L_OBJS :=
M_OBJS :=
@@ -19,11 +16,16 @@ LX_OBJS :=
MX_OBJS :=
MOD_LIST_NAME := VIDEO_MODULES
+CONFIG_FBGEN_BUILTIN :=
+CONFIG_FBGEN_MODULE :=
+
# Frame Buffer Console
-# Nasty trick to make sure all wanted stuff is linked in
-O_TARGET = fbdev.o
-L_OBJS += fbdev.o
+ifeq ($(CONFIG_FB),y)
+ # Nasty trick to make sure all wanted stuff is linked in
+ O_TARGET = fbdev.o
+ L_OBJS += fbdev.o
+endif
ifeq ($(CONFIG_DUMMY_CONSOLE),y)
L_OBJS += dummycon.o
@@ -35,8 +37,7 @@ endif
ifeq ($(CONFIG_FB),y)
L_OBJS += fonts.o
- OX_OBJS += fbcon.o fbcmap.o
-# fbgen is not compiled by default since nobody uses it yet, except clgenfb
+ OX_OBJS += fbcon.o fbcmap.o fbmem.o
ifeq ($(CONFIG_FONT_8x8),y)
L_OBJS += font_8x8.o
endif
@@ -94,6 +95,10 @@ ifeq ($(CONFIG_FB_ATY),y)
L_OBJS += atyfb.o
endif
+ifeq ($(CONFIG_FB_IGA),y)
+L_OBJS += igafb.o
+endif
+
ifeq ($(CONFIG_FB_CONTROL),y)
L_OBJS += controlfb.o
endif
@@ -102,6 +107,10 @@ ifeq ($(CONFIG_FB_PLATINUM),y)
L_OBJS += platinumfb.o
endif
+ifeq ($(CONFIG_FB_VALKYRIE),y)
+L_OBJS += valkyriefb.o
+endif
+
ifeq ($(CONFIG_FB_CT65550),y)
L_OBJS += chipsfb.o
endif
@@ -114,6 +123,11 @@ else
endif
endif
+ifeq ($(CONFIG_FB_CVPPC),y)
+L_OBJS += cvppcfb.o
+CONFIG_FBGEN_BUILTIN = y
+endif
+
ifeq ($(CONFIG_FB_MAC),y)
L_OBJS += macfb.o
endif
@@ -126,6 +140,10 @@ ifeq ($(CONFIG_FB_OF),y)
L_OBJS += offb.o macmodes.o
endif
+ifeq ($(CONFIG_FB_IMSTT),y)
+L_OBJS += imsttfb.o
+endif
+
ifeq ($(CONFIG_FB_RETINAZ3),y)
L_OBJS += retz3fb.o
else
@@ -136,11 +154,11 @@ endif
ifeq ($(CONFIG_FB_CLGEN),y)
L_OBJS += clgenfb.o
-OX_OBJS += fbgen.o
+CONFIG_FBGEN_BUILTIN = y
else
ifeq ($(CONFIG_FB_CLGEN),m)
M_OBJS += clgenfb.o
- OX_OBJS += fbgen.o
+ CONFIG_FBGEN_MODULE = y
endif
endif
@@ -160,26 +178,10 @@ else
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)
L_OBJS += virgefb.o
else
@@ -192,6 +194,10 @@ ifdef CONFIG_FB_G364
L_OBJS := $(L_OBJS) g364fb.o
endif
+ifdef CONFIG_FB_G364
+L_OBJS := $(L_OBJS) g364fb.o
+endif
+
ifeq ($(CONFIG_FB_SBUS),y)
L_OBJS += sbusfb.o
ifeq ($(CONFIG_FB_CREATOR),y)
@@ -229,6 +235,20 @@ L_OBJS += sbusfb.o
M_OBJS += tcxfb.o
endif
endif
+ ifeq ($(CONFIG_FB_CGFOURTEEN),y)
+ L_OBJS += cgfourteenfb.o
+ else
+ ifeq ($(CONFIG_FB_CGFOURTEEN),m)
+ M_OBJS += cgfourteenfb.o
+ endif
+ endif
+ ifeq ($(CONFIG_FB_LEO),y)
+ L_OBJS += leofb.o
+ else
+ ifeq ($(CONFIG_FB_LEO),m)
+ M_OBJS += leofb.o
+ endif
+ endif
else
ifeq ($(CONFIG_FB_SBUS),m)
M_OBJS += sbusfb.o
@@ -267,6 +287,20 @@ else
M_OBJS += tcxfb.o
endif
endif
+ ifeq ($(CONFIG_FB_CGFOURTEEN),y)
+ M_OBJS += cgfourteenfb.o
+ else
+ ifeq ($(CONFIG_FB_CGFOURTEEN),m)
+ M_OBJS += cgfourteenfb.o
+ endif
+ endif
+ ifeq ($(CONFIG_FB_LEO),y)
+ M_OBJS += leofb.o
+ else
+ ifeq ($(CONFIG_FB_LEO),m)
+ M_OBJS += leofb.o
+ endif
+ endif
endif
endif
@@ -278,6 +312,22 @@ else
endif
endif
+ifdef CONFIG_FBGEN_BUILTIN
+OX_OBJS += fbgen.o
+else
+ ifdef CONFIG_FBGEN_MODULE
+ MX_OBJS += fbgen.o
+ endif
+endif
+
+ifeq ($(CONFIG_FB_MATROX),y)
+L_OBJS += matroxfb.o
+else
+ ifeq ($(CONFIG_FB_MATROX),m)
+ M_OBJS += matroxfb.o
+ endif
+endif
+
# Generic Low Level Drivers
ifeq ($(CONFIG_FBCON_AFB),y)
@@ -400,17 +450,22 @@ else
endif
endif
-
-ifdef CONFIG_AMIGA_GSP
-L_OBJS += gspcon.o gspcore.o
-endif
-
# VGA Text Console
ifdef CONFIG_VGA_CONSOLE
L_OBJS += vgacon.o
endif
+# MDA Text Console
+
+ifeq ($(CONFIG_MDA_CONSOLE),y)
+L_OBJS += mdacon.o
+else
+ ifeq ($(CONFIG_MDA_CONSOLE),m)
+ M_OBJS += mdacon.o
+ endif
+endif
+
# Newport Text Console
ifdef CONFIG_SGI
@@ -419,11 +474,7 @@ endif
include $(TOPDIR)/Rules.make
-gspcore.c: gspcore.gsp
- $(GSPA) $< > $*.hex
- $(GSPH2C) $*.hex > gspcore.c
-
-promcon_tbl.c: prom.uni
+promcon_tbl.c: prom.uni ../char/conmakehash
../char/conmakehash prom.uni | \
sed -e '/#include <[^>]*>/p' -e 's/types/init/' \
-e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > promcon_tbl.c
diff --git a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c
index eb94dec73..c83c83c96 100644
--- a/drivers/video/S3triofb.c
+++ b/drivers/video/S3triofb.c
@@ -45,9 +45,9 @@
#include <asm/vc_ioctl.h>
#endif
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "s3blit.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/s3blit.h>
#define mem_in8(addr) in_8((void *)(addr))
@@ -250,8 +250,7 @@ static int s3trio_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
if (con == currcon) /* current console? */
- return fb_get_cmap(cmap, &fb_display[con].var, kspc, s3trio_getcolreg,
- info);
+ return fb_get_cmap(cmap, kspc, s3trio_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
@@ -276,8 +275,7 @@ static int s3trio_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return err;
}
if (con == currcon) /* current console? */
- return fb_set_cmap(cmap, &fb_display[con].var, kspc, s3trio_setcolreg,
- info);
+ return fb_set_cmap(cmap, kspc, s3trio_setcolreg, info);
else
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
@@ -574,7 +572,7 @@ __initfunc(void s3triofb_init_of(struct device_node *dp))
else
disp.dispsw = &fbcon_cfb8;
#else
- disp.dispsw = NULL;
+ disp.dispsw = &fbcon_dummy;
#endif
disp.scrollmode = fb_var.accel_flags & FB_ACCELF_TEXT ? 0 : SCROLL_YREDRAW;
@@ -612,6 +610,7 @@ __initfunc(void s3triofb_init_of(struct device_node *dp))
}
#endif /* CONFIG_FB_COMPAT_XPMAC) */
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
if (register_framebuffer(&fb_info) < 0)
return;
@@ -624,8 +623,7 @@ static int s3triofbcon_switch(int con, struct fb_info *info)
{
/* Do we have to save the colormap? */
if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
- s3trio_getcolreg, info);
+ fb_get_cmap(&fb_display[currcon].cmap, 1, s3trio_getcolreg, info);
currcon = con;
/* Install new colormap */
@@ -678,17 +676,16 @@ static int s3trio_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
{
if (regno > 255)
return 1;
- *red = palette[regno].red;
- *green = palette[regno].green;
- *blue = palette[regno].blue;
+ *red = (palette[regno].red << 8) | palette[regno].red;
+ *green = (palette[regno].green << 8) | palette[regno].green;
+ *blue = (palette[regno].blue << 8) | palette[regno].blue;
+ *transp = 0;
return 0;
}
/*
- * Set a single color register. The values supplied are already
- * rounded down to the hardware's capabilities (according to the
- * entries in the var structure). Return != 0 for invalid regno.
+ * Set a single color register. Return != 0 for invalid regno.
*/
static int s3trio_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -696,6 +693,10 @@ static int s3trio_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
{
if (regno > 255)
return 1;
+
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
palette[regno].red = red;
palette[regno].green = green;
palette[regno].blue = blue;
@@ -714,11 +715,10 @@ 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,
- s3trio_setcolreg, &fb_info);
+ fb_set_cmap(&fb_display[con].cmap, 1, s3trio_setcolreg, &fb_info);
else
- fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel),
- &fb_display[con].var, 1, s3trio_setcolreg, &fb_info);
+ fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), 1,
+ s3trio_setcolreg, &fb_info);
}
void s3triofb_setup(char *options, int *ints) {
@@ -837,9 +837,9 @@ static void fbcon_trio8_bmove(struct display *p, int sy, int sx, int dy,
int dx, int height, int width)
{
sx *= 8; dx *= 8; width *= 8;
- Trio_BitBLT((u_short)sx, (u_short)(sy*p->fontheight), (u_short)dx,
- (u_short)(dy*p->fontheight), (u_short)width,
- (u_short)(height*p->fontheight), (u_short)S3_NEW);
+ Trio_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
+ (u_short)(dy*fontheight(p)), (u_short)width,
+ (u_short)(height*fontheight(p)), (u_short)S3_NEW);
}
static void fbcon_trio8_clear(struct vc_data *conp, struct display *p, int sy,
@@ -850,9 +850,9 @@ static void fbcon_trio8_clear(struct vc_data *conp, struct display *p, int sy,
sx *= 8; width *= 8;
bg = attr_bgcol_ec(p,conp);
Trio_RectFill((u_short)sx,
- (u_short)(sy*p->fontheight),
+ (u_short)(sy*fontheight(p)),
(u_short)width,
- (u_short)(height*p->fontheight),
+ (u_short)(height*fontheight(p)),
(u_short)S3_NEW,
(u_short)bg);
}
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 52fb4487a..a20259904 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -21,10 +21,10 @@
#include <asm/irq.h>
#include <asm/uaccess.h>
-#include "fbcon-mfb.h"
-#include "fbcon-cfb2.h"
-#include "fbcon-cfb4.h"
-#include "fbcon-cfb8.h"
+#include <video/fbcon-mfb.h>
+#include <video/fbcon-cfb2.h>
+#include <video/fbcon-cfb4.h>
+#include <video/fbcon-cfb8.h>
#define MAX_VIDC20_PALETTE 256
#define MAX_VIDC_PALETTE 16
@@ -220,7 +220,7 @@ acornfb_set_disp(int con)
break;
#endif
default:
- display->dispsw = NULL;
+ display->dispsw = &fbcon_dummy;
break;
}
}
@@ -228,12 +228,19 @@ acornfb_set_disp(int con)
static int
acornfb_vidc20_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *trans, struct fb_info *info)
{
+ int t;
+
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;
+ t = current_par.palette.vidc20[regno].d.red;
+ *red = (t << 8) | t;
+ t = current_par.palette.vidc20[regno].d.green;
+ *green = (t << 8) | t;
+ t = current_par.palette.vidc20[regno].d.blue;
+ *blue = (t << 8) | t;
+ t = current_par.palette.vidc20[regno].d.ext;
+ t |= t << 4;
+ *transp = (t << 8) | t;
return 0;
}
@@ -243,6 +250,9 @@ acornfb_vidc20_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int
if (regno >= current_par.palette_size)
return 1;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
current_par.palette.vidc20[regno].p = 0;
current_par.palette.vidc20[regno].d.red = red;
current_par.palette.vidc20[regno].d.green = green;
@@ -261,8 +271,7 @@ acornfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
int err = 0;
if (con == currcon)
- err = fb_get_cmap(cmap, &fb_display[con].var,
- kspc, acornfb_vidc20_getcolreg, info);
+ err = fb_get_cmap(cmap, kspc, acornfb_vidc20_getcolreg, info);
else if (fb_display[con].cmap.len)
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
@@ -282,8 +291,8 @@ acornfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
current_par.palette_size, 0);
if (!err) {
if (con == currcon)
- err = fb_set_cmap(cmap, &fb_display[con].var,
- kspc, acornfb_vidc20_setcolreg, info);
+ err = fb_set_cmap(cmap, kspc, acornfb_vidc20_setcolreg,
+ info);
else
fb_copy_cmap(cmap, &fb_display[con].cmap,
kspc ? 0 : 1);
@@ -372,9 +381,10 @@ acornfb_init(unsigned long mem_start))
fb_info.switch_con = acornfb_switch;
fb_info.updatevar = acornfb_update_var;
fb_info.blank = acornfb_blank;
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
acornfb_set_disp(-1);
- fb_set_cmap(fb_default_cmap(current_par.palette_size), &fb_display[0].var,
+ fb_set_cmap(fb_default_cmap(current_par.palette_size),
1, acornfb_vidc20_setcolreg, &fb_info);
register_framebuffer(&fb_info);
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 840d23c03..ed588ab0d 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -60,10 +60,12 @@
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <asm/setup.h>
+#include <asm/io.h>
-#include "fbcon-afb.h"
-#include "fbcon-ilbm.h"
-#include "fbcon-mfb.h"
+#include <video/fbcon.h>
+#include <video/fbcon-afb.h>
+#include <video/fbcon-ilbm.h>
+#include <video/fbcon-mfb.h>
#define DEBUG
@@ -756,8 +758,9 @@ extern volatile u_short amiga_audio_min_period;
/*
* Since we can't read the palette on OCS/ECS, and since reading one
- * single color palette entry require 5 expensive custom chip bus accesses
+ * single color palette entry requires 5 expensive custom chip bus accesses
* on AGA, we keep a copy of the current palette.
+ * Note that the entries are always 24 bit!
*/
#if defined(CONFIG_FB_AMIGA_AGA)
@@ -1077,13 +1080,13 @@ static struct fb_var_screeninfo amifb_default;
/* colour */
#define rgb2hw8_high(red, green, blue) \
- (((red)<<4 & 0xf00) | ((green) & 0x0f0) | ((blue)>>4 & 0x00f))
+ (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4))
#define rgb2hw8_low(red, green, blue) \
- (((red)<<8 & 0xf00) | ((green)<<4 & 0x0f0) | ((blue) & 0x00f))
+ (((red & 0x0f)<<8) | ((green & 0x0f)<<4) | (blue & 0x0f))
#define rgb2hw4(red, green, blue) \
- (((red)<<8 & 0xf00) | ((green)<<4 & 0x0f0) | ((blue) & 0x00f))
+ (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4))
#define rgb2hw2(red, green, blue) \
- (((red)<<10 & 0xc00) | ((green)<<6 & 0x0c0) | ((blue)<<2 & 0x00c))
+ (((red & 0xc0)<<4) | (green & 0xc0) | ((blue & 0xc0)>>4))
/* sprpos/sprctl (sprite positioning) */
@@ -1476,7 +1479,8 @@ static int amifb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_fix_screeninfo fix;
ami_encode_fix(&fix, &par);
- display->screen_base = fix.smem_start;
+ display->screen_base =
+ phys_to_virt ((unsigned long) fix.smem_start);
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
@@ -1502,7 +1506,7 @@ static int amifb_set_var(struct fb_var_screeninfo *var, int con,
break;
#endif
default:
- display->dispsw = NULL;
+ display->dispsw = &fbcon_dummy;
}
if (fb_info.changevar)
(*fb_info.changevar)(con);
@@ -1558,8 +1562,7 @@ static int amifb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
if (con == currcon) /* current console? */
- return fb_get_cmap(cmap, &fb_display[con].var, kspc,
- ami_getcolreg, info);
+ return fb_get_cmap(cmap, kspc, ami_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
@@ -1584,8 +1587,7 @@ static int amifb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return err;
}
if (con == currcon) /* current console? */
- return fb_set_cmap(cmap, &fb_display[con].var, kspc,
- ami_setcolreg, info);
+ return fb_set_cmap(cmap, kspc, ami_setcolreg, info);
else
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
@@ -1858,6 +1860,7 @@ default_chipset:
fb_info.switch_con = &amifbcon_switch;
fb_info.updatevar = &amifbcon_updatevar;
fb_info.blank = &amifbcon_blank;
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
chipptr = chipalloc(videomemorysize+
SPRITEMEMSIZE+
@@ -1916,8 +1919,7 @@ static int amifbcon_switch(int con, struct fb_info *info)
{
/* Do we have to save the colormap? */
if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap,
- &fb_display[currcon].var, 1, ami_getcolreg, info);
+ fb_get_cmap(&fb_display[currcon].cmap, 1, ami_getcolreg, info);
currcon = con;
ami_set_var(&fb_display[con].var);
@@ -1954,12 +1956,10 @@ static void do_install_cmap(int con, struct fb_info *info)
if (con != currcon)
return;
if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
- ami_setcolreg, info);
+ fb_set_cmap(&fb_display[con].cmap, 1, ami_setcolreg, info);
else
fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
- &fb_display[con].var, 1,
- ami_setcolreg, info);
+ 1, ami_setcolreg, info);
}
static int flash_cursor(void)
@@ -2126,7 +2126,7 @@ static int ami_encode_fix(struct fb_fix_screeninfo *fix,
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, amifb_name);
- fix->smem_start = (char *)videomemory;
+ fix->smem_start = (char*) virt_to_phys((void *)videomemory);
fix->smem_len = videomemorysize;
#ifdef FBCON_HAS_MFB
@@ -2767,17 +2767,34 @@ static int ami_update_par(void)
static int ami_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info)
{
+ int len, tr, tg, tb;
+
if (IS_AGA) {
if (regno > 255)
return 1;
+ len = 8;
+ } else if (currentpar.bplcon0 & BPC0_SHRES) {
+ if (regno > 3)
+ return 1;
+ len = 2;
} else {
if (regno > 31)
return 1;
- }
-
- *red = palette[regno].red;
- *green = palette[regno].green;
- *blue = palette[regno].blue;
+ len = 4;
+ }
+ tr = palette[regno].red>>(8-len);
+ tg = palette[regno].green>>(8-len);
+ tb = palette[regno].blue>>(8-len);
+ while (len < 16) {
+ tr |= tr<<len;
+ tg |= tg<<len;
+ tb |= tb<<len;
+ len <<= 1;
+ }
+ *red = tr;
+ *green = tg;
+ *blue = tb;
+ *transp = 0;
return 0;
}
@@ -2791,16 +2808,22 @@ static int ami_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
static int ami_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
-#if defined(CONFIG_FB_AMIGA_AGA)
- u_short bplcon3 = currentpar.bplcon3;
-
if (IS_AGA) {
if (regno > 255)
return 1;
- } else
-#endif
+ } else if (currentpar.bplcon0 & BPC0_SHRES) {
+ if (regno > 3)
+ return 1;
+ } else {
if (regno > 31)
return 1;
+ }
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ palette[regno].red = red;
+ palette[regno].green = green;
+ palette[regno].blue = blue;
/*
* Update the corresponding Hardware Color Register, unless it's Color
@@ -2810,13 +2833,10 @@ static int ami_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* being changed by ami_do_blank() during the VBlank.
*/
- palette[regno].red = red;
- palette[regno].green = green;
- palette[regno].blue = blue;
-
if (regno || !is_blanked) {
#if defined(CONFIG_FB_AMIGA_AGA)
if (IS_AGA) {
+ u_short bplcon3 = currentpar.bplcon3;
VBlankOff();
custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000);
custom.color[regno&31] = rgb2hw8_high(red, green, blue);
@@ -2826,26 +2846,24 @@ static int ami_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
VBlankOn();
} else
#endif
- {
#if defined(CONFIG_FB_AMIGA_ECS)
- if (currentpar.bplcon0 & BPC0_SHRES) {
- u_short color, mask;
- int i;
-
- mask = 0x3333;
- color = rgb2hw2(red, green, blue);
- VBlankOff();
- for (i = regno+12; i >= (int)regno; i -= 4)
- custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
- mask <<=2; color >>= 2;
- regno = down16(regno)+mul4(mod4(regno));
- for (i = regno+3; i >= (int)regno; i--)
- custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
- VBlankOn();
- } else
+ if (currentpar.bplcon0 & BPC0_SHRES) {
+ u_short color, mask;
+ int i;
+
+ mask = 0x3333;
+ color = rgb2hw2(red, green, blue);
+ VBlankOff();
+ for (i = regno+12; i >= (int)regno; i -= 4)
+ custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+ mask <<=2; color >>= 2;
+ regno = down16(regno)+mul4(mod4(regno));
+ for (i = regno+3; i >= (int)regno; i--)
+ custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+ VBlankOn();
+ } else
#endif
- custom.color[regno] = rgb2hw4(red, green, blue);
- }
+ custom.color[regno] = rgb2hw4(red, green, blue);
}
return 0;
}
@@ -2982,23 +3000,21 @@ static void ami_do_blank(void)
custom.bplcon3 = bplcon3;
} else
#endif
- {
#if defined(CONFIG_FB_AMIGA_ECS)
- if (par->bplcon0 & BPC0_SHRES) {
- u_short color, mask;
- int i;
-
- mask = 0x3333;
- color = rgb2hw2(red, green, blue);
- for (i = 12; i >= 0; i -= 4)
- custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
- mask <<=2; color >>= 2;
- for (i = 3; i >= 0; i--)
- custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
- } else
+ if (par->bplcon0 & BPC0_SHRES) {
+ u_short color, mask;
+ int i;
+
+ mask = 0x3333;
+ color = rgb2hw2(red, green, blue);
+ for (i = 12; i >= 0; i -= 4)
+ custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+ mask <<=2; color >>= 2;
+ for (i = 3; i >= 0; i--)
+ custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+ } else
#endif
- custom.color[0] = rgb2hw4(red, green, blue);
- }
+ custom.color[0] = rgb2hw4(red, green, blue);
is_blanked = do_blank > 0 ? do_blank : 0;
}
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index a64eaf1fa..68c2a6fb2 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -70,12 +70,12 @@
#include <linux/fb.h>
#include <asm/atarikb.h>
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-#include "fbcon-iplan2p2.h"
-#include "fbcon-iplan2p4.h"
-#include "fbcon-iplan2p8.h"
-#include "fbcon-mfb.h"
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-iplan2p2.h>
+#include <video/fbcon-iplan2p4.h>
+#include <video/fbcon-iplan2p8.h>
+#include <video/fbcon-mfb.h>
#define SWITCH_ACIA 0x01 /* modes for switch on OverScan */
@@ -682,32 +682,44 @@ static void tt_set_par( struct atafb_par *par )
}
-static int tt_getcolreg( unsigned regno, unsigned *red,
- unsigned *green, unsigned *blue,
- unsigned *transp, struct fb_info *info )
+static int tt_getcolreg(unsigned regno, unsigned *red,
+ unsigned *green, unsigned *blue,
+ unsigned *transp, struct fb_info *info)
{
+ int t, col;
+
if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
regno += 254;
if (regno > 255)
return 1;
- *blue = tt_palette[regno];
- *green = (*blue >> 4) & 0xf;
- *red = (*blue >> 8) & 0xf;
- *blue &= 0xf;
+ t = tt_palette[regno];
+ col = t & 15;
+ col |= col << 4;
+ col |= col << 8;
+ *blue = col;
+ col = (t >> 4) & 15;
+ col |= col << 4;
+ col |= col << 8;
+ *green = col;
+ col = (t >> 8) & 15;
+ col |= col << 4;
+ col |= col << 8;
+ *red = col;
*transp = 0;
return 0;
}
-static int tt_setcolreg( unsigned regno, unsigned red,
- unsigned green, unsigned blue,
- unsigned transp, struct fb_info *info )
+static int tt_setcolreg(unsigned regno, unsigned red,
+ unsigned green, unsigned blue,
+ unsigned transp, struct fb_info *info)
{
if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
regno += 254;
if (regno > 255)
return 1;
- tt_palette[regno] = (red << 8) | (green << 4) | blue;
+ tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
+ (blue >> 12));
if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
TT_SHIFTER_STHIGH && regno == 254)
tt_palette[0] = 0;
@@ -770,6 +782,9 @@ static int vdl_prescale[4][3] = {{4,2,1}, {4,2,1}, {4,2,2}, {4,2,1}};
/* Default hsync timing [mon_type] in picoseconds */
static long h_syncs[4] = {3000000, 4875000, 4000000, 4875000};
+#ifdef FBCON_HAS_CFB16
+static u16 fbcon_cfb16_cmap[16];
+#endif
static inline int hxx_prescale(struct falcon_hw *hw)
{
@@ -1621,9 +1636,9 @@ static int falcon_getcolreg( unsigned regno, unsigned *red,
* Even with hicolor r/g/b=5/6/5 bit!
*/
col = f030_col[regno];
- *red = (col >> 26) & 0x3f;
- *green = (col >> 18) & 0x3f;
- *blue = (col >> 2) & 0x3f;
+ *red = (col >> 16) & 0xff00;
+ *green = (col >> 8) & 0xff00;
+ *blue = (col << 8) & 0xff00;
*transp = 0;
return 0;
}
@@ -1635,14 +1650,18 @@ static int falcon_setcolreg( unsigned regno, unsigned red,
{
if (regno > 255)
return 1;
- f030_col[regno] = (red << 26) | (green << 18) | (blue << 2);
+ f030_col[regno] = (((red & 0xfc00) << 16) |
+ ((green & 0xfc00) << 8) |
+ ((blue & 0xfc00) >> 8));
if (regno < 16) {
shifter_tt.color_reg[regno] =
- (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
- (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) |
- ((blue & 0xe) >> 1) | ((blue & 1) << 3);
+ (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |
+ (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |
+ ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);
#ifdef FBCON_HAS_CFB16
- fbcon_cfb16_cmap[regno] = (red << 11) | (green << 5) | blue;
+ fbcon_cfb16_cmap[regno] = ((red & 0xf800) |
+ ((green & 0xfc00) >> 5) |
+ ((blue & 0xf800) >> 11));
#endif
}
return 0;
@@ -1923,35 +1942,51 @@ static void stste_set_par( struct atafb_par *par )
}
-static int stste_getcolreg( unsigned regno, unsigned *red,
- unsigned *green, unsigned *blue,
- unsigned *transp, struct fb_info *info )
-{ unsigned col;
+static int stste_getcolreg(unsigned regno, unsigned *red,
+ unsigned *green, unsigned *blue,
+ unsigned *transp, struct fb_info *info)
+{
+ unsigned col, t;
if (regno > 15)
return 1;
col = shifter_tt.color_reg[regno];
if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
- *red = ((col >> 7) & 0xe) | ((col >> 11) & 1);
- *green = ((col >> 3) & 0xe) | ((col >> 7) & 1);
- *blue = ((col << 1) & 0xe) | ((col >> 3) & 1);
+ t = ((col >> 7) & 0xe) | ((col >> 11) & 1);
+ t |= t << 4;
+ *red = t | (t << 8);
+ t = ((col >> 3) & 0xe) | ((col >> 7) & 1);
+ t |= t << 4;
+ *green = t | (t << 8);
+ t = ((col << 1) & 0xe) | ((col >> 3) & 1);
+ t |= t << 4;
+ *blue = t | (t << 8);
}
else {
- *red = (col >> 8) & 0x7;
- *green = (col >> 4) & 0x7;
- *blue = col & 0x7;
+ t = (col >> 7) & 0xe;
+ t |= t << 4;
+ *red = t | (t << 8);
+ t = (col >> 3) & 0xe;
+ t |= t << 4;
+ *green = t | (t << 8);
+ t = (col << 1) & 0xe;
+ t |= t << 4;
+ *blue = t | (t << 8);
}
*transp = 0;
return 0;
}
-static int stste_setcolreg( unsigned regno, unsigned red,
- unsigned green, unsigned blue,
- unsigned transp, struct fb_info *info )
+static int stste_setcolreg(unsigned regno, unsigned red,
+ unsigned green, unsigned blue,
+ unsigned transp, struct fb_info *info)
{
if (regno > 15)
return 1;
+ red >>= 12;
+ blue >>= 12;
+ green >>= 12;
if (ATARIHW_PRESENT(EXTD_SHIFTER))
shifter_tt.color_reg[regno] =
(((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
@@ -1959,9 +1994,9 @@ static int stste_setcolreg( unsigned regno, unsigned red,
((blue & 0xe) >> 1) | ((blue & 1) << 3);
else
shifter_tt.color_reg[regno] =
- ((red & 0x7) << 8) |
- ((green & 0x7) << 4) |
- (blue & 0x7);
+ ((red & 0xe) << 7) |
+ ((green & 0xe) << 3) |
+ ((blue & 0xe) >> 1);
return 0;
}
@@ -2383,12 +2418,10 @@ do_install_cmap(int con, struct fb_info *info)
if (con != currcon)
return;
if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, &(fb_display[con].var), 1,
- fbhw->setcolreg, info);
+ fb_set_cmap(&fb_display[con].cmap, 1, fbhw->setcolreg, info);
else
fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
- &(fb_display[con].var), 1,
- fbhw->setcolreg, info);
+ 1, fbhw->setcolreg, info);
}
@@ -2503,6 +2536,7 @@ atafb_set_disp(int con, struct fb_info *info)
#ifdef FBCON_HAS_CFB16
case 16:
display->dispsw = &fbcon_cfb16;
+ display->dispsw_data = fbcon_cfb16_cmap;
break;
#endif
}
@@ -2546,8 +2580,7 @@ static int
atafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
{
if (con == currcon) /* current console ? */
- return fb_get_cmap(cmap, &(fb_display[con].var), kspc,
- fbhw->getcolreg, info);
+ return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info);
else
if (fb_display[con].cmap.len) /* non default colormap ? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
@@ -2568,8 +2601,7 @@ atafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
return err;
}
if (con == currcon) /* current console ? */
- return fb_set_cmap(cmap, &(fb_display[con].var), kspc,
- fbhw->setcolreg, info);
+ return fb_set_cmap(cmap, kspc, fbhw->setcolreg, info);
else
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
@@ -2675,8 +2707,7 @@ atafb_switch(int con, struct fb_info *info)
{
/* Do we have to save the colormap ? */
if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap,
- &(fb_display[currcon].var), 1, fbhw->getcolreg,
+ fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg,
info);
do_fb_set_var(&fb_display[con].var,1);
currcon=con;
@@ -2707,8 +2738,7 @@ atafb_blank(int blank, struct fb_info *info)
cmap.transp=NULL;
cmap.start=0;
cmap.len=16;
- fb_set_cmap(&cmap, &(fb_display[currcon].var), 1,
- fbhw->setcolreg, info);
+ fb_set_cmap(&cmap, 1, fbhw->setcolreg, info);
}
else
do_install_cmap(currcon, info);
@@ -2819,6 +2849,7 @@ __initfunc(void atafb_init(void))
fb_info.switch_con = &atafb_switch;
fb_info.updatevar = &fb_update_var;
fb_info.blank = &atafb_blank;
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
do_fb_set_var(&atafb_predefined[default_par-1], 1);
strcat(fb_info.modename, fb_var_names[default_par-1][0]);
diff --git a/drivers/video/ati-gt.h b/drivers/video/ati-gt.h
deleted file mode 100644
index 32dc792b5..000000000
--- a/drivers/video/ati-gt.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/* the usage for the following structs vary from the gx and vt:
-and sdram and sgram gt's
- pll registers (sdram) 6,7,11;
- crtc_h_sync_strt_wid[3];
- dsp1[3] (sdram,sgram,unused)
- dsp2[3] (offset regbase+24, depends on colour mode);
- crtc_h_tot_disp,crtc_v_tot_disp,crtc_v_sync_strt_wid,unused;
- pll registers (sgram) 7,11;
-*/
-
-/* Register values for 1280x1024, 75Hz mode (20). no 16/32 */
-static struct aty_regvals aty_gt_reg_init_20 = {
- { 0x41, 0xf9, 0x04 },
- { 0xe02a7, 0x1401a6, 0 },
- { 0x260957, 0x2806d6, 0 },
- { 0x10006b6, 0x20006b6, 0x30006b6 },
-
- 0x9f00d2, 0x03ff0429, 0x30400, 0,
- { 0xb5, 0x04 }
-};
-
-#if 0
-/* Register values for 1280x960, 75Hz mode (19) */
-static struct aty_regvals aty_gt_reg_init_19 = {
-};
-#endif
-
-/* Register values for 1152x870, 75Hz mode (18) */
-static struct aty_regvals aty_gt_reg_init_18 = {
- { 0x41, 0xe6, 0x04 },
- { 0x300295, 0x300194, 0x300593 },
- { 0x260a1c, 0x380561, 0},
- { 0x1000744, 0x2000744, 0x3000744 },
-
- 0x8f00b5, 0x3650392, 0x230368, 0,
- { 0xe6, 0x04 }
-};
-
-/* Register values for 1024x768, 75Hz mode (17), 32 bpp untested */
-static struct aty_regvals aty_gt_reg_init_17 = {
- { 0x41, 0xb5, 0x04 },
- { 0xc0283, 0xc0182, 0xc0581 },
- { 0x36066d, 0x3806d6, 0},
- { 0xa0049e, 0x100049e, 0x200049e },
-
- 0x7f00a3, 0x2ff031f, 0x30300, 0,
- { 0xb8, 0x04 }
-};
-
-#if 0
-/* Register values for x, Hz mode (16) */
-static struct aty_regvals aty_gt_reg_init_16 = {
-};
-#endif
-
-/* Register values for 1024x768, 70Hz mode (15) */
-static struct aty_regvals aty_gt_reg_init_15 = {
- { 0x41, 0xad, 0x04 },
- { 0x310284, 0x310183, 0x310582 },
- { 0x0, 0x380727 },
- { 0x0 },
- 0x7f00a5, 0x2ff0325, 0x260302,
-};
-
-/* Register values for 1024x768, 60Hz mode (14) */
-static struct aty_regvals aty_gt_reg_init_14 = {
- { 0x40, 0xe1, 0x14 },
- { 0x310284, 0x310183, 0x310582 },
- { 0x3607c0, 0x380840, 0x0 },
- { 0xa80592, 0x1000592, 0x0 },
-
- 0x7f00a7, 0x2ff0325, 0x260302, 0,
- { 0xe1, 0x14 }
-};
-
-/* Register values for 832x624, 75Hz mode (13) */
-static struct aty_regvals aty_gt_reg_init_13 = {
- { 0x40, 0xc6, 0x14 },
- { 0x28026d, 0x28016c, 0x28056b },
- { 0x3608cf, 0x380960, 0 },
- { 0xb00655, 0x1000655, 0x2000655 },
-
- 0x67008f, 0x26f029a, 0x230270, 0,
- { 0xc6, 0x14 }
-};
-
-/* Register values for 800x600, 75Hz mode (12) */
-static struct aty_regvals aty_gt_reg_init_12 = {
- { 0x42, 0xe4, 0x04 },
- { 0xa0267, 0xa0166, 0x0a0565},
- { 0x360a33, 0x48056d, 0},
- { 0xc00755, 0x1000755, 0x02000755},
-
- 0x630083, 0x2570270, 0x30258, 0,
- { 0xe4, 0x4 }
-};
-
-/* Register values for 800x600, 72Hz mode (11) */
-static struct aty_regvals aty_gt_reg_init_11 = {
- { 0x42, 0xe6, 0x04 },
- { 0xf026c, 0xf016b, 0xf056a },
- { 0x360a1d, 0x480561, 0},
- { 0xc00745, 0x1000745, 0x2000745 },
-
- 0x630081, 0x02570299, 0x6027c
-};
-
-/* Register values for 800x600, 60Hz mode (10) */
-static struct aty_regvals aty_gt_reg_init_10 = {
- { 0x42, 0xb8, 0x04 },
- { 0x10026a, 0x100169, 0x100568 },
- { 0x460652, 0x4806ba, 0},
- { 0x68048b, 0xa0048b, 0x100048b },
-
- 0x630083, 0x02570273, 0x40258, 0,
- { 0xb8, 0x4 }
-};
-
-/* Register values for 800x600, 56Hz mode (9) */
-static struct aty_regvals aty_gt_reg_init_9 = {
- { 0x42, 0xf9, 0x14 },
- { 0x90268, 0x90167, 0x090566 },
- { 0x460701, 0x480774, 0},
- { 0x700509, 0xa80509, 0x1000509 },
-
- 0x63007f, 0x2570270, 0x20258
-};
-
-#if 0
-/* Register values for 768x576, 50Hz mode (8) */
-static struct aty_regvals aty_gt_reg_init_8 = {
-};
-
-/* Register values for 640x870, 75Hz Full Page Display (7) */
-static struct aty_regvals aty_gt_reg_init_7 = {
-};
-#endif
-
-/* Register values for 640x480, 67Hz mode (6) */
-static struct aty_regvals aty_gt_reg_init_6 = {
- { 0x42, 0xd1, 0x14 },
- { 0x280259, 0x280158, 0x280557 },
- { 0x460858, 0x4808e2, 0},
- { 0x780600, 0xb00600, 0x1000600 },
-
- 0x4f006b, 0x1df020c, 0x2301e2, 0,
- { 0x8b, 0x4 }
-};
-
-/* Register values for 640x480, 60Hz mode (5) */
-static struct aty_regvals aty_gt_reg_init_5 = {
- { 0x43, 0xe8, 0x04 },
- { 0x2c0253, 0x2c0152, 0x2c0551 },
- { 0x460a06, 0x580555, 0},
- { 0x880734, 0xc00734, 0x1000734 },
-
- 0x4f0063, 0x1df020c, 0x2201e9, 0,
- { 0xe8, 0x04 }
-};
-
-#if 0
-/* Register values for x, Hz mode (4) */
-static struct aty_regvals aty_gt_reg_init_4 = {
-};
-
-/* Register values for x, Hz mode (3) */
-static struct aty_regvals aty_gt_reg_init_3 = {
-};
-
-/* Register values for x, Hz mode (2) */
-static struct aty_regvals aty_gt_reg_init_2 = {
-};
-
-/* Register values for x, Hz mode (1) */
-static struct aty_regvals aty_gt_reg_init_1 = {
-};
-#endif
-
-/* yikes, more data structures (dsp2)
- * XXX kludge for sgram
- */
-static int sgram_dsp[20][3] = {
- {0,0,0},
- {0,0,0},
- {0,0,0},
- {0,0,0},
- {0x5203d7,0x7803d9,0xb803dd}, //5
- {0x940666,0xe0066a,0x1700672}, //6
- {0,0,0},
- {0,0,0},
- {0x88055f,0xd80563,0x170056b}, //9
- {0x8404d9,0xb804dd,0x17004e5}, //10
- {0x7803e2,0xb803e6,0x17003ee}, //11
- {0x7803eb,0xb803ef,0x17003f7}, //12
- {0xe806c5,0x17006cd,0x2e006dd}, //13
- {0xe005f6,0x17005fe,0x2e0060e}, //14
- {0xd8052c,0x1700534,0x2e00544}, //15
- {0,0,0},
- {0xb804f2,0x17004e5,0x2e0050a}, //17
- {0xb803e6,0x17003ee,0x2e003fe}, //18
- {0,0,0},
- {0,0,0},
-};
diff --git a/drivers/video/ati-gx.h b/drivers/video/ati-gx.h
deleted file mode 100644
index df48c1865..000000000
--- a/drivers/video/ati-gx.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* Register values for 1280x1024, 75Hz (WAS 60) mode (20) */
-static struct aty_regvals aty_gx_reg_init_20 = {
- { 0x200, 0x200, 0x200 },
-
- { 0x1200a5, 0x1200a3, 0x1200a3 },
- { 0x30c0200, 0x30e0300, 0x30e0300 },
- { 0x2, 0x3, 0x3 },
-
- 0x9f00d2, 0x3ff0429, 0x30400, 0x28100040,
- { 0xd4, 0x9 }
-};
-
-/* Register values for 1152x870, 75Hz mode (18) */
-static struct aty_regvals aty_gx_reg_init_18 = {
- { 0x200, 0x200, 0x200 },
-
- { 0x300097, 0x300095, 0x300094 },
- { 0x3090200, 0x30e0300, 0x30e0600 },
- { 0x2, 0x3, 0x6 },
-
- 0x8f00b5, 0x3650392, 0x230368, 0x24100040,
- { 0x53, 0x3 }
-};
-
-/* Register values for 1024x768, 75Hz mode (17) */
-static struct aty_regvals aty_gx_reg_init_17 = {
- { 0x200, 0x200, 0x200 },
-
- { 0x2c0087, 0x2c0085, 0x2c0084 },
- { 0x3070200, 0x30e0300, 0x30e0600 },
- { 0x2, 0x3, 0x6 },
-
- 0x7f00a5, 0x2ff0323, 0x230302, 0x20100000,
- { 0x42, 0x3 }
-};
-
-/* Register values for 1024x768, 72Hz mode (15) */
-static struct aty_regvals aty_gx_reg_init_15 = {
- { 0, 0, 0 },
-
- { 0x310086, 0x310084, 0x310084 },
- { 0x3070200, 0x30e0300, 0x30e0300 },
- { 0x2002312, 0x3002312, 0x3002312 },
-
- 0x7f00a5, 0x2ff0325, 0x260302, 0x20100000,
- { 0x88, 0x7 }
-};
-
-/* Register values for 1024x768, 60Hz mode (14) */
-static struct aty_regvals aty_gx_reg_init_14 = {
- { 0, 0, 0 },
-
- { 0x310086, 0x310084, 0x310084 },
- { 0x3060200, 0x30d0300, 0x30d0300 },
- { 0x2002312, 0x3002312, 0x3002312 },
-
- 0x7f00a7, 0x2ff0325, 0x260302, 0x20100000,
- { 0x6c, 0x6 }
-};
-
-/* Register values for 832x624, 75Hz mode (13) */
-static struct aty_regvals aty_gx_reg_init_13 = {
- { 0x200, 0x200, 0x200 },
-
- { 0x28006f, 0x28006d, 0x28006c },
- { 0x3050200, 0x30b0300, 0x30e0600 },
- { 0x2, 0x3, 0x6 },
-
- 0x67008f, 0x26f029a, 0x230270, 0x1a100040,
- { 0x4f, 0x5 }
-};
-
-#if 0 /* not filled in yet */
-/* Register values for 800x600, 75Hz mode (12) */
-static struct aty_regvals aty_gx_reg_init_12 = {
- { 0x10, 0x28, 0x50 },
- { },
- { } /* pixel clock = 49.11MHz for V=74.40Hz */
-};
-
-/* Register values for 800x600, 72Hz mode (11) */
-static struct aty_regvals aty_gx_reg_init_11 = {
- { 0x10, 0x28, 0x50 },
- { },
- { } /* pixel clock = 49.63MHz for V=71.66Hz */
-};
-
-/* Register values for 800x600, 60Hz mode (10) */
-static struct aty_regvals aty_gx_reg_init_10 = {
- { 0x10, 0x28, 0x50 },
- { },
- { } /* pixel clock = 41.41MHz for V=59.78Hz */
-};
-
-/* Register values for 640x870, 75Hz Full Page Display (7) */
-static struct aty_regvals aty_gx_reg_init_7 = {
- { 0x10, 0x30, 0x68 },
- { },
- { } /* pixel clock = 57.29MHz for V=75.01Hz */
-};
-#endif
-
-/* Register values for 640x480, 67Hz mode (6) */
-static struct aty_regvals aty_gx_reg_init_6 = {
- { 0x200, 0x200, 0x200 },
-
- { 0x28005b, 0x280059, 0x280058 },
- { 0x3040200, 0x3060300, 0x30c0600 },
- { 0x2002312, 0x3002312, 0x6002312 },
-
- 0x4f006b, 0x1df020c, 0x2301e2, 0x14100040,
- { 0x35, 0x07 }
-};
-
-#if 0 /* not filled in yet */
-/* Register values for 640x480, 60Hz mode (5) */
-static struct aty_regvals aty_gx_reg_init_5 = {
- { 0x200, 0x200, 0x200 },
- { },
- { 0x35, 0x07 }
-};
-#endif
diff --git a/drivers/video/ati-vt.h b/drivers/video/ati-vt.h
deleted file mode 100644
index 3b25d6d5d..000000000
--- a/drivers/video/ati-vt.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/* Register values for 1280x1024, 60Hz mode (20) */
-static struct aty_regvals aty_vt_reg_init_20 = {
- { 0, 0, 0 },
-
- { 0x002e02a7, 0x002e02a7, 0 },
- { 0x03070200, 0x03070200, 0 },
- { 0x0a00cb22, 0x0b00cb23, 0 },
-
- 0x009f00d2, 0x03ff0429, 0x00030400, 0x28000000,
- { 0x00, 0xaa }
-};
-
-/* Register values for 1280x960, 75Hz mode (19) */
-static struct aty_regvals aty_vt_reg_init_19 = {
- { 0, 0, 0 },
- { 0x003202a3, 0x003201a2, 0 },
- { 0x030b0200, 0x030b0300, 0 },
- { 0x0a00cb22, 0x0b00cb23, 0 },
-
- 0x009f00d1, 0x03bf03e7, 0x000303c0, 0x28000000,
- { 0x00, 0xc6 }
-};
-
-/* Register values for 1152x870, 75Hz mode (18) */
-static struct aty_regvals aty_vt_reg_init_18 = {
- { 0, 0, 0 },
-
- { 0x00300295, 0x00300194, 0 },
- { 0x03080200, 0x03080300, 0 },
- { 0x0a00cb21, 0x0b00cb22, 0 },
-
- 0x008f00b5, 0x03650392, 0x00230368, 0x24000000,
- { 0x00, 0x9d }
-};
-
-/* Register values for 1024x768, 75Hz mode (17) */
-static struct aty_regvals aty_vt_reg_init_17 = {
- { 0, 0, 0 },
-
- { 0x002c0283, 0x002c0182, 0 },
- { 0x03080200, 0x03080300, 0 },
- { 0x0a00cb21, 0x0b00cb22, 0 },
-
- 0x007f00a3, 0x02ff031f, 0x00030300, 0x20000000,
- { 0x01, 0xf7 }
-};
-
-/* Register values for 1024x768, 70Hz mode (15) */
-static struct aty_regvals aty_vt_reg_init_15 = {
- { 0, 0, 0 },
- { 0x00310284, 0x00310183, 0 },
- { 0x03080200, 0x03080300, 0 },
- { 0x0a00cb21, 0x0b00cb22, 0 },
-
- 0x007f00a5, 0x02ff0325, 0x00260302, 0x20000000,
- { 0x01, 0xeb }
-};
-
-/* Register values for 1024x768, 60Hz mode (14) */
-static struct aty_regvals aty_vt_reg_init_14 = {
- { 0, 0, 0 },
-
- { 0x00310284, 0x00310183, 0x00310582 }, /* 32 bit 0x00310582 */
- { 0x03080200, 0x03080300, 0x03070600 }, /* 32 bit 0x03070600 */
- { 0x0a00cb21, 0x0b00cb22, 0x0e00cb23 },
-
- 0x007f00a7, 0x02ff0325, 0x00260302, 0x20000000,
- { 0x01, 0xcc }
-};
-
-/* Register values for 832x624, 75Hz mode (13) */
-static struct aty_regvals aty_vt_reg_init_13 = {
- { 0, 0, 0 },
-
- { 0x0028026d, 0x0028016c, 0x0028056b },
- { 0x03080200, 0x03070300, 0x03090600 },
- { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 },
-
- 0x0067008f, 0x026f029a, 0x00230270, 0x1a000000,
- { 0x01, 0xb4 }
-};
-
-/* Register values for 800x600, 75Hz mode (12) */
-static struct aty_regvals aty_vt_reg_init_12 = {
- { 0, 0, 0 },
-
- { 0x002a0267, 0x002a0166, 0x002a0565 },
- { 0x03040200, 0x03060300, 0x03070600 },
- { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 },
-
- 0x00630083, 0x02570270, 0x00030258, 0x19000000,
- { 0x01, 0x9c }
-};
-
-/* Register values for 800x600, 72Hz mode (11) */
-static struct aty_regvals aty_vt_reg_init_11 = {
- { 0, 0, 0 },
-
- { 0x002f026c, 0x002f016b, 0x002f056a },
- { 0x03050200, 0x03070300, 0x03090600 },
- { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 },
-
- 0x00630081, 0x02570299, 0x0006027c, 0x19000000,
- { 0x01, 0x9d }
-};
-
-/* Register values for 800x600, 60Hz mode (10) */
-static struct aty_regvals aty_vt_reg_init_10 = {
- { 0, 0, 0 },
-
- { 0x0030026a, 0x00300169, 0x00300568 },
- { 0x03050200, 0x03070300, 0x03090600 },
- { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 },
-
- 0x00630083, 0x02570273, 0x00040258, 0x19000000,
- { 0x02, 0xfb }
-};
-
-/* Register values for 640x480, 67Hz mode (6) */
-static struct aty_regvals aty_vt_reg_init_6 = {
- { 0, 0, 0 },
-
- { 0x00280259, 0x00280158, 0x00280557 },
- { 0x03050200, 0x03070300, 0x030a0600 },
- { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 },
-
- 0x004f006b, 0x01df020c, 0x002301e2, 0x14000000,
- { 0x02, 0xbe }
-};
-
-/* Register values for 640x480, 60Hz mode (5) */
-static struct aty_regvals aty_vt_reg_init_5 = {
- { 0, 0, 0 },
-
- { 0x002c0253, 0x002c0152, 0x002c0551 },
- { 0x03050200, 0x03070300, 0x03090600 },
- { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 },
-
- 0x004f0063, 0x01df020c, 0x002201e9, 0x14000000,
- { 0x02, 0x9e }
-};
- /* 8 bit 15 bit 32 bit */
-static int vt_mem_cntl[3][3] = { { 0x0A00CB21, 0x0B00CB21, 0x0E00CB21 }, /* 1 MB VRAM */
- { 0x0A00CB22, 0x0B00CB22, 0x0E00CB22 }, /* 2 MB VRAM */
- { 0x0200053B, 0x0300053B, 0x0600053B } /* 4 M B VRAM */
- };
-
diff --git a/drivers/video/aty.h b/drivers/video/aty.h
index 517b500c5..667e7c3ec 100644
--- a/drivers/video/aty.h
+++ b/drivers/video/aty.h
@@ -718,12 +718,20 @@
/* mach64CT family / mach64VT class */
#define VT_CHIP_ID 0x5654 /* mach64VT (ATI264VT) */
#define VU_CHIP_ID 0x5655 /* mach64VTB (ATI264VTB) */
+#define VV_CHIP_ID 0x5656 /* mach64VT4 (ATI264VT4) */
/* 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 LB_CHIP_ID 0x4c42 /* RAGE LT PRO, AGP */
+#define LD_CHIP_ID 0x4c44 /* RAGE LT PRO */
+#define LG_CHIP_ID 0x4c47 /* RAGE LT PRO */
+#define LI_CHIP_ID 0x4c49 /* RAGE LT PRO */
+#define LP_CHIP_ID 0x4c50 /* RAGE LT PRO */
+#define LT_CHIP_ID 0x4c54 /* RAGE LT */
+#define GT_CHIP_ID 0x4754 /* RAGE (GT) */
+#define GU_CHIP_ID 0x4755 /* RAGE II/II+ (GTB) */
+#define GV_CHIP_ID 0x4756 /* RAGE IIC, PCI */
+#define GW_CHIP_ID 0x4757 /* RAGE IIC, AGP */
+#define GZ_CHIP_ID 0x475a /* RAGE IIC, AGP */
#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 */
diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c
index 7d271bc29..e3f1b1d8d 100644
--- a/drivers/video/atyfb.c
+++ b/drivers/video/atyfb.c
@@ -1,9 +1,9 @@
-/*
+/* $Id: atyfb.c,v 1.90 1998/11/20 12:27:03 geert Exp $
* linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
*
- * Copyright (C) 1997-1998 Geert Uytterhoeven
- * Copyright (C) 1998 Bernd Harries
- * Copyright (C) 1998 Eddie C. Dost
+ * Copyright (C) 1997-1998 Geert Uytterhoeven
+ * Copyright (C) 1998 Bernd Harries
+ * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
*
* This driver is partly based on the PowerMac console driver:
*
@@ -26,15 +26,12 @@
TODO:
- (ecd):
-
- - fix initialization of cursor timer.
-
- - add code to support cursor on all cards and all ramdacs.
+ - cursor support on all cards and all ramdacs.
+ - cursor parameters controlable via ioctl()s.
+ - guess PLL and MCLK based on the original PLL register values initialized
+ by the BIOS or Open Firmware (if they are initialized).
- - make cursor parameters controllable via ioctl()s.
-
- (Anyone to help with all this?)
+ (Anyone to help with this?)
******************************************************************************/
@@ -65,29 +62,33 @@
#include <asm/io.h>
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
#include <asm/prom.h>
#include <asm/pci-bridge.h>
-#include "macmodes.h"
+#include <video/macmodes.h>
#endif
#ifdef __sparc__
#include <asm/pbm.h>
+#include <asm/fbio.h>
+#include <asm/uaccess.h>
#endif
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+
#include "aty.h"
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-#include "fbcon-cfb24.h"
-#include "fbcon-cfb32.h"
-#define GUI_RESERVE 0x00001000
+/*
+ * Debug flags.
+ */
+#undef DEBUG
-#define CLASS_GX 1
-#define CLASS_CT 2
-#define CLASS_VT 3
-#define CLASS_GT 4
+
+#define GUI_RESERVE 0x00001000
#ifndef __powerpc__
@@ -166,6 +167,7 @@ struct pci_mmap_map {
};
#define DEFAULT_CURSOR_BLINK_RATE (20)
+#define CURSOR_DRAW_DELAY (2)
struct aty_cursor {
int enable;
@@ -179,6 +181,7 @@ struct aty_cursor {
u32 color[2];
u8 bits[8][64];
u8 mask[8][64];
+ u8 *ram;
struct timer_list *timer;
};
@@ -188,8 +191,6 @@ struct fb_info_aty {
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;
@@ -208,6 +209,19 @@ struct fb_info_aty {
u8 dac_type;
u8 clk_type;
u8 mem_refresh_rate;
+ struct display disp;
+ struct display_switch dispsw;
+ union {
+#ifdef FBCON_HAS_CFB16
+ u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+ u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u32 cfb32[16];
+#endif
+ } fbcon_cmap;
#ifdef __sparc__
u8 open;
u8 mmaped;
@@ -299,6 +313,7 @@ static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
*/
static int aty_init(struct fb_info_aty *info, const char *name);
+static struct aty_cursor *aty_init_cursor(struct fb_info_aty *fb);
#ifdef CONFIG_ATARI
static int store_video_par(char *videopar, unsigned char m64_num);
static char *strtoke(char *s, const char *ct);
@@ -309,6 +324,9 @@ 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);
+#if defined(__sparc__) || defined(DEBUG)
+static u8 aty_ld_pll(int offset, const struct fb_info_aty *info);
+#endif
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,
@@ -319,22 +337,17 @@ 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 int aty_var_to_pll_18818(u32 vclk_per, struct pll_gx *pll);
+static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll);
+static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per);
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 int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
+ u8 bpp, struct pll_ct *pll);
+static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per);
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,
@@ -348,12 +361,14 @@ static void set_off_pitch(struct atyfb_par *par,
static int encode_fix(struct fb_fix_screeninfo *fix,
const struct atyfb_par *par,
const struct fb_info_aty *info);
+static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
+ int bpp, int accel);
static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
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 *fb);
static void do_install_cmap(int con, struct fb_info *info);
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
static int read_aty_sense(const struct fb_info_aty *info);
#endif
@@ -383,12 +398,17 @@ static struct fb_ops atyfb_ops = {
static char atyfb_name[16] = "ATY Mach64";
static char fontname[40] __initdata = { 0 };
+static char curblink __initdata = 1;
+static char noaccel __initdata = 0;
+static u32 default_vram __initdata = 0;
+static int default_pll __initdata = 0;
+static int default_mclk __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;
+#if defined(CONFIG_PPC)
+static int default_vmode __initdata = VMODE_NVRAM;
+static int default_cmode __initdata = CMODE_NVRAM;
#endif
#ifdef CONFIG_ATARI
@@ -415,14 +435,20 @@ static struct aty_features {
/* mach64CT family / mach64VT class */
{ 0x5654, 0x5654, "mach64VT (ATI264VT)" },
{ 0x5655, 0x5655, "mach64VTB (ATI264VTB)" },
-/* { 0x5656, 0x5656, "mach64VT4 (ATI264VT4)" }, */
+ { 0x5656, 0x5656, "mach64VT4 (ATI264VT4)" },
/* mach64CT family / mach64GT (3D RAGE) class */
+ { 0x4c42, 0x4c42, "3D RAGE LT PRO (AGP)" },
+ { 0x4c42, 0x4c44, "3D RAGE LT PRO" },
+ { 0x4c42, 0x4c47, "3D RAGE LT PRO" },
+ { 0x4c42, 0x4c49, "3D RAGE LT PRO" },
+ { 0x4c42, 0x4c50, "3D RAGE LT PRO" },
{ 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" }, */
+ { 0x4756, 0x4756, "3D RAGE IIC (PCI)" },
+ { 0x4757, 0x4757, "3D RAGE IIC (AGP)" },
+ { 0x475a, 0x475a, "3D RAGE IIC (AGP)" },
{ 0x4742, 0x4742, "3D RAGE PRO (BGA, AGP)" },
{ 0x4744, 0x4744, "3D RAGE PRO (BGA, AGP, 1x only)" },
{ 0x4749, 0x4749, "3D RAGE PRO (BGA, PCI)" },
@@ -430,6 +456,14 @@ static struct aty_features {
{ 0x4751, 0x4751, "3D RAGE PRO (PQFP, PCI, limited 3D)" },
};
+static const char *aty_gx_ram[8] __initdata = {
+ "DRAM", "VRAM", "VRAM", "DRAM", "DRAM", "VRAM", "VRAM", "RESV"
+};
+
+static const char *aty_ct_ram[8] __initdata = {
+ "OFF", "DRAM", "EDO", "EDO", "SDRAM", "SGRAM", "WRAM", "RESV"
+};
+
static inline u32 aty_ld_le32(volatile unsigned int regindex,
const struct fb_info_aty *info)
@@ -620,6 +654,12 @@ static void init_engine(const struct atyfb_par *par,
aty_st_le32(DP_PIX_WIDTH, par->crtc.dp_pix_width, info);
aty_st_le32(DP_CHAIN_MASK, par->crtc.dp_chain_mask, info);
+ wait_for_fifo(5, info);
+ aty_st_le32(SCALE_3D_CNTL, 0, info);
+ aty_st_le32(Z_CNTL, 0, info);
+ aty_st_le32(CRTC_INT_CNTL, aty_ld_le32(CRTC_INT_CNTL, info) & ~0x20, info);
+ aty_st_le32(GUI_TRAJ_CNTL, 0x100023, info);
+
/* insure engine is idle before leaving */
wait_for_idle(info);
}
@@ -648,22 +688,22 @@ static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info)
aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
}
-#if 0 /* ecd debug */
+#if defined(__sparc__) || defined(DEBUG)
static u8 aty_ld_pll(int offset, const struct fb_info_aty *info)
{
- u8 val;
+ u8 res;
/* 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);
+ res = aty_ld_8(CLOCK_CNTL + 2, info);
eieio();
- return val;
+ return res;
}
-#endif /* ecd debug */
+#endif
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
/*
* Apple monitor sense
@@ -703,7 +743,7 @@ static int read_aty_sense(const struct fb_info_aty *info)
return sense;
}
-#endif /* defined(CONFIG_PMAC) || defined(CONFIG_CHRP) */
+#endif /* defined(CONFIG_PPC) */
/* ------------------------------------------------------------------------- */
@@ -768,8 +808,7 @@ aty_set_cursor_shape(struct fb_info_aty *fb)
return;
#endif
- ram = (u8 *)(fb->frame_buffer + c->offset);
-
+ ram = c->ram;
for (y = 0; y < c->size.y; y++) {
for (x = 0; x < c->size.x >> 2; x++) {
m = c->mask[x][y];
@@ -788,8 +827,9 @@ aty_set_cursor_shape(struct fb_info_aty *fb)
}
static void
-aty_set_cursor(struct fb_info_aty *fb)
+aty_set_cursor(struct fb_info_aty *fb, int on)
{
+ struct atyfb_par *par = &fb->current_par;
struct aty_cursor *c = fb->cursor;
u16 xoff, yoff;
int x, y;
@@ -802,8 +842,8 @@ aty_set_cursor(struct fb_info_aty *fb)
return;
#endif
- if (c->on) {
- x = c->pos.x - c->hot.x;
+ if (on) {
+ x = c->pos.x - c->hot.x - par->crtc.xoffset;
if (x < 0) {
xoff = -x;
x = 0;
@@ -811,7 +851,7 @@ aty_set_cursor(struct fb_info_aty *fb)
xoff = 0;
}
- y = c->pos.y - c->hot.y;
+ y = c->pos.y - c->hot.y - par->crtc.yoffset;
if (y < 0) {
yoff = -y;
y = 0;
@@ -827,11 +867,12 @@ aty_set_cursor(struct fb_info_aty *fb)
aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, fb)
| HWCURSOR_ENABLE, fb);
} else {
- wait_for_fifo(4, fb);
+ wait_for_fifo(1, fb);
aty_st_le32(GEN_TEST_CNTL,
aty_ld_le32(GEN_TEST_CNTL, fb) & ~HWCURSOR_ENABLE,
fb);
}
+ wait_for_idle(fb);
}
static void
@@ -847,7 +888,7 @@ aty_cursor_timer_handler(unsigned long dev_addr)
if (fb->cursor->vbl_cnt && --fb->cursor->vbl_cnt == 0) {
fb->cursor->on ^= 1;
- aty_set_cursor(fb);
+ aty_set_cursor(fb, fb->cursor->on);
fb->cursor->vbl_cnt = fb->cursor->blink_rate;
}
@@ -857,9 +898,9 @@ out:
}
static void
-atyfb_cursor(struct display *d, int mode, int x, int y)
+atyfb_cursor(struct display *p, int mode, int x, int y)
{
- struct fb_info_aty *fb = (struct fb_info_aty *)d->fb_info;
+ struct fb_info_aty *fb = (struct fb_info_aty *)p->fb_info;
struct aty_cursor *c = fb->cursor;
if (!c)
@@ -870,44 +911,82 @@ atyfb_cursor(struct display *d, int mode, int x, int y)
return;
#endif
- x *= d->fontwidth;
- y *= d->fontheight;
- if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->on)
+ x *= fontwidth(p);
+ y *= fontheight(p);
+ if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable)
return;
c->enable = 0;
+ if (c->on)
+ aty_set_cursor(fb, 0);
c->pos.x = x;
c->pos.y = y;
switch (mode) {
case CM_ERASE:
c->on = 0;
- aty_set_cursor(fb);
break;
case CM_DRAW:
case CM_MOVE:
- c->on = 1;
- aty_set_cursor(fb);
+ if (c->on)
+ aty_set_cursor(fb, 1);
+ else
+ c->vbl_cnt = CURSOR_DRAW_DELAY;
+ c->enable = 1;
+ break;
+ }
+}
- if (!c->timer) {
- c->timer = kmalloc(sizeof(*c->timer), GFP_KERNEL);
- if (!c->timer)
- return;
+__initfunc(static struct aty_cursor *
+aty_init_cursor(struct fb_info_aty *fb))
+{
+ struct aty_cursor *cursor;
+ unsigned long addr;
- c->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
+ cursor = kmalloc(sizeof(struct aty_cursor), GFP_ATOMIC);
+ if (!cursor)
+ return 0;
+ memset(cursor, 0, sizeof(*cursor));
- 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);
- }
+ cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL);
+ if (!cursor->timer) {
+ kfree(cursor);
+ return 0;
+ }
+ memset(cursor->timer, 0, sizeof(*cursor->timer));
- c->vbl_cnt = c->blink_rate;
- c->enable = 1;
- break;
+ cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
+ fb->total_vram -= PAGE_SIZE;
+ cursor->offset = fb->total_vram;
+
+#ifdef __sparc__
+ addr = fb->frame_buffer - 0x800000 + cursor->offset;
+ cursor->ram = (u8 *)addr;
+#else
+#ifdef __BIG_ENDIAN
+ addr = fb->frame_buffer_phys - 0x800000 + cursor->offset;
+ cursor->ram = (u8 *)ioremap(addr, 1024);
+#else
+ addr = fb->frame_buffer + cursor->offset;
+ cursor->ram = (u8 *)addr;
+#endif
+#endif
+
+ if (! cursor->ram) {
+ kfree(cursor);
+ return NULL;
+ }
+
+ if (curblink) {
+ init_timer(cursor->timer);
+ cursor->timer->expires = jiffies + (HZ / 50);
+ cursor->timer->data = (unsigned long)fb;
+ cursor->timer->function = aty_cursor_timer_handler;
+ add_timer(cursor->timer);
}
+
+ return cursor;
}
static int
@@ -923,7 +1002,6 @@ atyfb_set_font(struct display *d, int width, int height)
height = 16;
}
- c->offset = fb->total_vram - 0x1000;
c->hot.x = 0;
c->hot.y = 0;
c->size.x = width;
@@ -972,7 +1050,7 @@ static int aty_var_to_crtc(const struct fb_info_aty *info,
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 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
u32 pix_width, dp_pix_width, dp_chain_mask;
/* input */
@@ -1029,6 +1107,8 @@ static int aty_var_to_crtc(const struct fb_info_aty *info,
FAIL("v_total too large");
v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+ c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
+
if (bpp <= 8) {
bpp = 8;
pix_width = CRTC_PIX_WIDTH_8BPP;
@@ -1073,10 +1153,9 @@ static int aty_var_to_crtc(const struct fb_info_aty *info,
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;
+ crtc->gen_cntl = pix_width | c_sync | 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))) {
+ ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07))) {
/* Not VTB/GTB */
/* FIXME: magic FIFO values */
crtc->gen_cntl |= aty_ld_le32(CRTC_GEN_CNTL, info) & 0x000e0000;
@@ -1129,7 +1208,7 @@ static int aty_crtc_to_var(const struct crtc *crtc,
{
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 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
u32 pix_width;
/* input */
@@ -1145,19 +1224,21 @@ static int aty_crtc_to_var(const struct crtc *crtc,
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;
+ c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
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;
+ right = (h_sync_strt-h_disp)*8+h_sync_dly;
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);
+ (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
+ (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
switch (pix_width) {
#if 0
@@ -1277,13 +1358,12 @@ static void aty_set_pll_gx(const struct fb_info_aty *info,
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 */
+ aty_st_514(0x21, pll->n, info); /* F1 / N0 */
break;
}
}
-static int aty_var_to_pll_18818(const struct fb_var_screeninfo *var,
- struct pll_gx *pll)
+static int aty_var_to_pll_18818(u32 vclk_per, struct pll_gx *pll)
{
/*
* FIXME: use real calculations instead of using fixed values from the old
@@ -1329,7 +1409,7 @@ static int aty_var_to_pll_18818(const struct fb_var_screeninfo *var,
for (set = 0; set < sizeof(ATI18818_clocks)/sizeof(*ATI18818_clocks);
set++)
- if (var->pixclock <= ATI18818_clocks[set].ps_lim) {
+ if (vclk_per <= ATI18818_clocks[set].ps_lim) {
pll->m = ATI18818_clocks[set].mode;
pll->n = ATI18818_clocks[set].prog;
return 0;
@@ -1337,8 +1417,7 @@ static int aty_var_to_pll_18818(const struct fb_var_screeninfo *var,
return -EINVAL;
}
-static int aty_var_to_pll_514(const struct fb_var_screeninfo *var,
- struct pll_gx *pll)
+static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll)
{
/*
* FIXME: use real calculations instead of using fixed values from the old
@@ -1360,7 +1439,7 @@ static int aty_var_to_pll_514(const struct fb_var_screeninfo *var,
int i;
for (i = 0; i < sizeof(RGB514_clocks)/sizeof(*RGB514_clocks); i++)
- if (var->pixclock <= RGB514_clocks[i].limit) {
+ if (vclk_per <= RGB514_clocks[i].limit) {
pll->m = RGB514_clocks[i].m;
pll->n = RGB514_clocks[i].n;
return 0;
@@ -1370,8 +1449,7 @@ static int aty_var_to_pll_514(const struct fb_var_screeninfo *var,
/* FIXME: ATI18818?? */
-static int aty_pll_gx_to_var(const struct pll_gx *pll,
- struct fb_var_screeninfo *var)
+static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per)
{
u8 df, vco_div_count, ref_div_count;
@@ -1379,7 +1457,7 @@ static int aty_pll_gx_to_var(const struct pll_gx *pll,
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);
+ *vclk_per = (ref_clk_per*(vco_div_count+65)/ref_div_count)>>(3-df);
return 0;
}
@@ -1392,22 +1470,6 @@ static int aty_pll_gx_to_var(const struct pll_gx *pll,
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);
@@ -1416,10 +1478,9 @@ printk("PLL_EXT_CNTL: %02x (%02x)\n",
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 (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
+ Gx == ET_CHIP_ID ||
+ ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)))) {
if (info->ram_type >= SDRAM)
aty_st_pll(DLL_CNTL, 0xa6, info);
else
@@ -1442,7 +1503,15 @@ static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div,
(vclk_fb_div*mclk_post_div*bpp);
if (xclks_per_row < (1<<11))
FAIL("Dotclock to high");
- fifo_size = 24;
+ if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == VT_CHIP_ID ||
+ Gx == VU_CHIP_ID || Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
+ Gx == GZ_CHIP_ID) {
+ fifo_size = 24;
+ dsp_loop_latency = 0;
+ } else {
+ fifo_size = 32;
+ dsp_loop_latency = 2;
+ }
dsp_precision = 0;
y = (xclks_per_row*fifo_size)>>11;
while (y) {
@@ -1456,21 +1525,21 @@ static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div,
if (info->total_vram > 1*1024*1024) {
if (info->ram_type >= SDRAM) {
/* >1 MB SDRAM */
- dsp_loop_latency = 8;
+ dsp_loop_latency += 8;
page_size = 8;
} else {
/* >1 MB DRAM */
- dsp_loop_latency = 6;
+ dsp_loop_latency += 6;
page_size = 9;
}
} else {
if (info->ram_type >= SDRAM) {
/* <2 MB SDRAM */
- dsp_loop_latency = 9;
+ dsp_loop_latency += 9;
page_size = 10;
} else {
/* <2 MB DRAM */
- dsp_loop_latency = 8;
+ dsp_loop_latency += 8;
page_size = 10;
}
}
@@ -1491,11 +1560,10 @@ static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div,
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)
+static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
+ u8 bpp, struct pll_ct *pll)
{
- u32 vclk_per, q, x; /* x is a workaround for sparc64-linux-gcc */
+ u32 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;
@@ -1505,7 +1573,6 @@ static int aty_var_to_pll_ct(const struct fb_info_aty *info,
pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
- vclk_per = var->pixclock;
pll_ref_div = info->pll_per*2*255/ref_clk_per;
/* FIXME: use the VTB/GTB /3 post divider if it's better suited */
@@ -1537,7 +1604,7 @@ static int aty_var_to_pll_ct(const struct fb_info_aty *info,
vclk_fb_div = q*vclk_post_div/8;
if ((err = aty_dsp_gt(info, mclk_fb_div, mclk_post_div, vclk_fb_div,
- vclk_post_div, var->bits_per_pixel, pll)))
+ vclk_post_div, bpp, pll)))
return err;
if ((((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) ||
@@ -1609,8 +1676,7 @@ static int aty_var_to_pll_ct(const struct fb_info_aty *info,
return 0;
}
-static int aty_pll_ct_to_var(const struct pll_ct *pll,
- struct fb_var_screeninfo *var)
+static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per)
{
u8 pll_ref_div = pll->pll_ref_div;
u8 vclk_fb_div = pll->vclk_fb_div;
@@ -1624,7 +1690,7 @@ static int aty_pll_ct_to_var(const struct pll_ct *pll,
(vclk_post_div & 3)];
if (vpostdiv == 0)
return -EINVAL;
- var->pixclock = pll_ref_div*vpostdiv*ref_clk_per/vclk_fb_div/2;
+ *vclk_per = pll_ref_div*vpostdiv*ref_clk_per/vclk_fb_div/2;
return 0;
}
@@ -1657,7 +1723,7 @@ static void atyfb_set_par(const struct atyfb_par *par,
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;
+ i |= info->mem_refresh_rate << 20;
switch (par->crtc.bpp) {
case 8:
case 24:
@@ -1680,7 +1746,8 @@ static void atyfb_set_par(const struct atyfb_par *par,
/* 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(EXT_MEM_CNTL,
+ aty_ld_le32(EXT_MEM_CNTL, info) | 0x5000001, info);
}
aty_st_le32(MEM_CNTL, i, info);
}
@@ -1720,17 +1787,18 @@ static int atyfb_decode_var(const struct fb_var_screeninfo *var,
if ((err = aty_var_to_crtc(info, var, &par->crtc)))
return err;
- if ((Gx == GX_PCI_ID) || (Gx == CX_PCI_ID))
+ if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
switch (info->clk_type) {
case CLK_ATI18818_1:
- err = aty_var_to_pll_18818(var, &par->pll.gx);
+ err = aty_var_to_pll_18818(var->pixclock, &par->pll.gx);
break;
case CLK_IBMRGB514:
- err = aty_var_to_pll_514(var, &par->pll.gx);
+ err = aty_var_to_pll_514(var->pixclock, &par->pll.gx);
break;
}
else
- err = aty_var_to_pll_ct(info, var, &par->pll.ct);
+ err = aty_var_to_pll_ct(info, var->pixclock, par->crtc.bpp,
+ &par->pll.ct);
if (err)
return err;
@@ -1740,7 +1808,7 @@ static int atyfb_decode_var(const struct fb_var_screeninfo *var,
par->accel_flags = 0;
#if 0
- if (!fbmon_valid_timings(pixclock, htotal, vtotal, info))
+ if (!fbmon_valid_timings(var->pixclock, htotal, vtotal, info))
return -EINVAL;
#endif
@@ -1757,10 +1825,10 @@ static int atyfb_encode_var(struct fb_var_screeninfo *var,
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);
+ if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
+ err = aty_pll_gx_to_var(&par->pll.gx, &var->pixclock);
else
- err = aty_pll_ct_to_var(&par->pll.ct, var);
+ err = aty_pll_ct_to_var(&par->pll.ct, &var->pixclock);
if (err)
return err;
@@ -1853,15 +1921,15 @@ static int encode_fix(struct fb_fix_screeninfo *fix,
* 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)) {
+ 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)) {
+ } 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)) {
+ } else if (Gx == VT_CHIP_ID || Gx == VU_CHIP_ID || Gx == VV_CHIP_ID) {
fix->mmio_start = (char *)(info->ati_regbase_phys-0x400);
fix->mmio_len = 0x800;
fix->accel = FB_ACCEL_ATI_MACH64VT;
@@ -1891,32 +1959,6 @@ struct fb_var_screeninfo default_var = {
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
@@ -1954,6 +1996,47 @@ static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
}
+static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
+ int bpp, int accel)
+{
+ switch (bpp) {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ info->dispsw = accel ? fbcon_aty8 : fbcon_cfb8;
+ disp->dispsw = &info->dispsw;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ info->dispsw = accel ? fbcon_aty16 : fbcon_cfb16;
+ disp->dispsw = &info->dispsw;
+ disp->dispsw_data = info->fbcon_cmap.cfb16;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ info->dispsw = accel ? fbcon_aty24 : fbcon_cfb24;
+ disp->dispsw = &info->dispsw;
+ disp->dispsw_data = info->fbcon_cmap.cfb24;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ info->dispsw = accel ? fbcon_aty32 : fbcon_cfb32;
+ disp->dispsw = &info->dispsw;
+ disp->dispsw_data = info->fbcon_cmap.cfb32;
+ break;
+#endif
+ default:
+ disp->dispsw = &fbcon_dummy;
+ }
+ if (info->cursor) {
+ info->dispsw.cursor = atyfb_cursor;
+ info->dispsw.set_font = atyfb_set_font;
+ }
+}
+
+
/*
* Set the User Defined Part of the Display
*/
@@ -2001,38 +2084,13 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
display->can_soft_blank = 1;
display->inverse = 0;
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;
-#endif
-#ifdef FBCON_HAS_CFB24
- case 24:
- *display->dispsw = accel ? fbcon_aty24 : fbcon_cfb24;
- break;
-#endif
-#ifdef FBCON_HAS_CFB32
- case 32:
- *display->dispsw = accel ? fbcon_aty32 : fbcon_cfb32;
- break;
-#endif
- default:
- display->dispsw = NULL;
- break;
- }
- display->scrollmode = accel ? 0 : SCROLL_YREDRAW;
+ atyfb_set_disp(display, info, par.crtc.bpp, accel);
+ if (accel)
+ display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0;
+ else
+ display->scrollmode = 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, info);
@@ -2080,8 +2138,7 @@ static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
if (con == currcon) /* current console? */
- return fb_get_cmap(cmap, &fb_display[con].var, kspc, atyfb_getcolreg,
- info);
+ return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else {
@@ -2106,8 +2163,7 @@ static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return err;
}
if (con == currcon) /* current console? */
- return fb_set_cmap(cmap, &fb_display[con].var, kspc, atyfb_setcolreg,
- info);
+ return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info);
else
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
@@ -2117,7 +2173,27 @@ static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
u_long arg, int con, struct fb_info *info)
{
+#ifdef __sparc__
+ struct fb_info_aty *fb = (struct fb_info_aty *)info;
+ struct fbtype fbtyp;
+
+ switch (cmd) {
+ case FBIOGTYPE:
+ fbtyp.fb_type = FBTYPE_PCI_GENERIC;
+ fbtyp.fb_width = fb->current_par.crtc.vxres;
+ fbtyp.fb_height = fb->current_par.crtc.vyres;
+ fbtyp.fb_depth = fb->current_par.crtc.bpp;
+ fbtyp.fb_cmsize = fb_display[con].cmap.len;
+ fbtyp.fb_size = fb->total_vram;
+ copy_to_user_ret((struct fbtype *)arg, &fbtyp, sizeof(fbtyp), -EFAULT);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+#else
return -EINVAL;
+#endif
}
#ifdef __sparc__
@@ -2139,10 +2215,15 @@ static int atyfb_mmap(struct fb_info *info, struct file *file,
/* To stop the swapper from even considering these pages. */
vma->vm_flags |= (VM_SHM | VM_LOCKED);
+ if (((vma->vm_offset == 0) && (size == fb->total_vram)) ||
+ ((vma->vm_offset == fb->total_vram) && (size == PAGE_SIZE)))
+ vma->vm_offset += 0x8000000000000000UL;
+
#ifdef __sparc_v9__
/* Align it as much as desirable */
{
- int j, max = -1, align;
+ unsigned long j, align;
+ int max = -1;
map_offset = vma->vm_offset+size;
for (i = 0; fb->mmap_map[i].size; i++) {
@@ -2193,7 +2274,7 @@ static int atyfb_mmap(struct fb_info *info, struct file *file,
if (start > offset)
continue;
- if (offset > end)
+ if (offset >= end)
continue;
map_size = fb->mmap_map[i].size - (offset - start);
@@ -2237,6 +2318,78 @@ static int atyfb_mmap(struct fb_info *info, struct file *file,
}
return 0;
}
+
+static struct {
+ u32 yoffset;
+ u8 r[2][256];
+ u8 g[2][256];
+ u8 b[2][256];
+} atyfb_save;
+
+static void atyfb_save_palette(struct fb_info *fb, int enter)
+{
+ struct fb_info_aty *info = (struct fb_info_aty *)fb;
+ int i, tmp, scale;
+
+ for (i = 0; i < 256; i++) {
+ tmp = 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))
+ tmp |= 0x2;
+ aty_st_8(DAC_CNTL, tmp, info);
+ aty_st_8(DAC_MASK, 0xff, info);
+ eieio();
+ scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) &&
+ (info->current_par.crtc.bpp == 16)) ? 3 : 0;
+ info->aty_cmap_regs->rindex = i << scale;
+ eieio();
+ atyfb_save.r[enter][i] = info->aty_cmap_regs->lut;
+ eieio();
+ atyfb_save.g[enter][i] = info->aty_cmap_regs->lut;
+ eieio();
+ atyfb_save.b[enter][i] = info->aty_cmap_regs->lut;
+ eieio();
+ info->aty_cmap_regs->windex = i << scale;
+ eieio();
+ info->aty_cmap_regs->lut = atyfb_save.r[1-enter][i];
+ eieio();
+ info->aty_cmap_regs->lut = atyfb_save.g[1-enter][i];
+ eieio();
+ info->aty_cmap_regs->lut = atyfb_save.b[1-enter][i];
+ eieio();
+ }
+}
+
+static void atyfb_palette(int enter)
+{
+ struct fb_info_aty *info;
+ struct atyfb_par *par;
+ struct display *d;
+ int i;
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ d = &fb_display[i];
+ if (d->fb_info &&
+ d->fb_info->fbops == &atyfb_ops &&
+ d->fb_info->display_fg &&
+ d->fb_info->display_fg->vc_num == i) {
+ atyfb_save_palette(d->fb_info, enter);
+ info = (struct fb_info_aty *)d->fb_info;
+ par = &info->current_par;
+ if (enter) {
+ atyfb_save.yoffset = par->crtc.yoffset;
+ par->crtc.yoffset = 0;
+ set_off_pitch(par, info);
+ } else {
+ par->crtc.yoffset = atyfb_save.yoffset;
+ set_off_pitch(par, info);
+ }
+ break;
+ }
+ }
+}
#endif /* __sparc__ */
/*
@@ -2250,9 +2403,9 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
int j, k;
struct fb_var_screeninfo var;
struct display *disp;
- const char *chipname = NULL;
- int pll, mclk;
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+ const char *chipname = NULL, *ramname = NULL;
+ int pll, mclk, gtb_memsize;
+#if defined(CONFIG_PPC)
int sense;
#endif
@@ -2269,10 +2422,11 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
printk("atyfb: Unknown mach64 0x%04x\n", Gx);
return 0;
} else
- printk("atyfb: %s [0x%04x rev 0x%2x] ", chipname, Gx, Rev);
+ printk("atyfb: %s [0x%04x rev 0x%02x] ", 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;
+ ramname = aty_gx_ram[info->ram_type];
/* FIXME: clockchip/RAMDAC probing? */
#ifdef CONFIG_ATARI
info->dac_type = DAC_ATI68860_B;
@@ -2287,6 +2441,7 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
} else {
info->bus_type = PCI;
info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) & 0x07);
+ ramname = aty_ct_ram[info->ram_type];
info->dac_type = DAC_INTERNAL;
info->clk_type = CLK_INTERNAL;
if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) {
@@ -2315,10 +2470,14 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
(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 */
+ } else if (Gx == GB_CHIP_ID || Gx == GD_CHIP_ID ||
+ Gx == GI_CHIP_ID || Gx == GP_CHIP_ID ||
+ Gx == GQ_CHIP_ID || Gx == VV_CHIP_ID ||
+ Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
+ Gx == GZ_CHIP_ID || Gx == LD_CHIP_ID ||
+ Gx == LG_CHIP_ID || Gx == LB_CHIP_ID ||
+ Gx == LI_CHIP_ID || Gx == LP_CHIP_ID) {
+ /* RAGE PRO or IIC */
pll = 230;
} else {
/* other RAGE */
@@ -2327,31 +2486,12 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
}
}
}
- 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))
+ gtb_memsize = !(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
+ Gx == ET_CHIP_ID ||
+ ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)));
+ if (gtb_memsize)
switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */
case MEM_SIZE_512K:
info->total_vram = 0x80000;
@@ -2398,21 +2538,93 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
info->total_vram = 0x80000;
}
+ if (Gx == GI_CHIP_ID) {
+ if (aty_ld_le32(CONFIG_STAT1, info) & 0x40000000)
+ info->total_vram += 0x400000;
+ }
+
+ if (default_vram) {
+ info->total_vram = default_vram*1024;
+ i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
+ if (info->total_vram <= 0x80000)
+ i |= MEM_SIZE_512K;
+ else if (info->total_vram <= 0x100000)
+ i |= MEM_SIZE_1M;
+ else if (info->total_vram <= 0x200000)
+ i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
+ else if (info->total_vram <= 0x400000)
+ i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
+ else if (info->total_vram <= 0x600000)
+ i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
+ else
+ i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
+ aty_st_le32(MEM_CNTL, i, info);
+ }
+ if (default_pll)
+ pll = default_pll;
+ if (default_mclk)
+ mclk = default_mclk;
+
+ printk("%d%c %s, %d MHz PLL, %d Mhz MCLK\n",
+ info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20),
+ info->total_vram == 0x80000 ? 'K' : 'M', ramname, pll, mclk);
+
+ 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 */
+ info->pll_per = 1000000/pll;
+ info->mclk_per = 1000000/mclk;
+
+#ifdef DEBUG
+ if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
+ int i;
+ printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
+ "DSP_CONFIG DSP_ON_OFF\n"
+ "%08x %08x %08x %08x %08x %08x %08x\n"
+ "PLL",
+ aty_ld_le32(BUS_CNTL, info), aty_ld_le32(DAC_CNTL, info),
+ aty_ld_le32(MEM_CNTL, info), aty_ld_le32(EXT_MEM_CNTL, info),
+ aty_ld_le32(CRTC_GEN_CNTL, info), aty_ld_le32(DSP_CONFIG, info),
+ aty_ld_le32(DSP_ON_OFF, info));
+ for (i = 0; i < 16; i++)
+ printk(" %02x", aty_ld_pll(i, info));
+ printk("\n");
+ }
+#endif
+
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 defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
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 (Gx == LG_CHIP_ID)
+ /* G3 PowerBook with 1024x768 LCD */
+ default_vmode = VMODE_1024_768_60;
+ else {
+ 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;
@@ -2422,24 +2634,26 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
default_cmode = CMODE_8;
if (mac_vmode_to_var(default_vmode, default_cmode, &var))
var = default_var;
-#else /* !CONFIG_PMAC && !CONFIG_CHRP */
+#else /* !CONFIG_PPC */
var = default_var;
-#endif /* !CONFIG_PMAC && !CONFIG_CHRP */
- var.accel_flags |= FB_ACCELF_TEXT;
+#endif /* !CONFIG_PPC */
+ if (noaccel)
+ var.accel_flags &= ~FB_ACCELF_TEXT;
+ else
+ var.accel_flags |= FB_ACCELF_TEXT;
+
+ if (var.yres == var.yres_virtual) {
+ u32 vram = (info->total_vram - (PAGE_SIZE << 2));
+ var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / var.xres_virtual;
+ if (var.yres_virtual < var.yres)
+ var.yres_virtual = var.yres;
+ }
+
if (atyfb_decode_var(&var, &info->default_par, info)) {
printk("atyfb: can't set default video mode\n");
return 0;
}
- 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);
@@ -2451,7 +2665,11 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
info->fb_info.switch_con = &atyfbcon_switch;
info->fb_info.updatevar = &atyfbcon_updatevar;
info->fb_info.blank = &atyfbcon_blank;
+ info->fb_info.flags = FBINFO_FLAG_DEFAULT;
+#ifdef __sparc__
+ atyfb_save_palette(&info->fb_info, 0);
+#endif
for (j = 0; j < 16; j++) {
k = color_table[j];
info->palette[j].red = default_red[k];
@@ -2459,16 +2677,14 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
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));
+ if (Gx != GX_CHIP_ID && Gx != CX_CHIP_ID) {
+ info->cursor = aty_init_cursor(info);
+ if (info->cursor) {
+ info->dispsw.cursor = atyfb_cursor;
+ info->dispsw.set_font = atyfb_set_font;
+ }
}
-
- disp->dispsw = &info->dispsw;
+
atyfb_set_var(&var, -1, &info->fb_info);
if (register_framebuffer(&info->fb_info) < 0)
@@ -2489,8 +2705,12 @@ __initfunc(void atyfb_init(void))
struct fb_info_aty *info;
unsigned long addr;
#ifdef __sparc__
+ extern void (*prom_palette) (int);
extern int con_is_present(void);
- u32 chip_id;
+ struct pcidev_cookie *pcp;
+ char prop[128];
+ int node, len;
+ u32 mem, chip_id;
int i, j;
/* Do not attach when we have a serial console. */
@@ -2536,16 +2756,17 @@ __initfunc(void atyfb_init(void))
*/
for (i = 0; i < 6 && pdev->base_address[i]; i++)
/* nothing */;
- j = i + 1;
+ j = i + 3;
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);
+ return;
}
-
memset(info->mmap_map, 0, j * sizeof(*info->mmap_map));
- for (i = j = 0; i < 6 && pdev->base_address[i]; i++) {
+
+ for (i = 0, j = 2; i < 6 && pdev->base_address[i]; i++) {
int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
unsigned long base;
u32 size, pbase;
@@ -2564,8 +2785,7 @@ __initfunc(void atyfb_init(void))
size = ~(size) + 1;
if (base == addr) {
- info->mmap_map[j].voff = (pbase + 0x800000)
- & PAGE_MASK;
+ 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;
@@ -2586,9 +2806,10 @@ __initfunc(void atyfb_init(void))
/*
* 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);
+ mem = aty_ld_le32(MEM_CNTL, info);
+ chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
+ if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) &&
+ !((chip_id >> 24) & 1)) {
switch (mem & 0x0f) {
case 3:
mem = (mem & ~(0x0f)) | 2;
@@ -2606,53 +2827,93 @@ __initfunc(void atyfb_init(void))
break;
}
if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM)
- mem &= ~(0x00f00000);
- aty_st_le32(MEM_CNTL, mem, info);
+ mem &= ~(0x00700000);
}
+ mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */
+ aty_st_le32(MEM_CNTL, mem, info);
/*
- * Set default vmode and cmode from PROM properties.
+ * If this is the console device, we will set default video
+ * settings to what the PROM left us with.
*/
- {
- 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;
+ node = prom_getchild(prom_root_node);
+ node = prom_searchsiblings(node, "aliases");
+ if (node) {
+ len = prom_getproperty(node, "screen", prop, sizeof(prop));
+ if (len > 0) {
+ prop[len] = '\0';
+ node = prom_finddevice(prop);
+ } else {
+ node = 0;
}
+ }
- 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;
- }
+ pcp = pdev->sysdata;
+ if (node == pcp->prom_node) {
+
+ struct fb_var_screeninfo *var = &default_var;
+ unsigned int N, P, Q, M, T;
+ u32 v_total, h_total;
+ struct crtc crtc;
+ u8 pll_regs[16];
+ u8 clock_cntl;
+
+ crtc.vxres = prom_getintdefault(node, "width", 1024);
+ crtc.vyres = prom_getintdefault(node, "height", 768);
+ crtc.bpp = prom_getintdefault(node, "depth", 8);
+ crtc.xoffset = crtc.yoffset = 0;
+ crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, info);
+ crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, info);
+ crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, info);
+ crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, info);
+ crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, info);
+ aty_crtc_to_var(&crtc, var);
+
+ h_total = var->xres + var->right_margin +
+ var->hsync_len + var->left_margin;
+ v_total = var->yres + var->lower_margin +
+ var->vsync_len + var->upper_margin;
+
+ /*
+ * Read the PLL to figure actual Refresh Rate.
+ */
+ clock_cntl = aty_ld_8(CLOCK_CNTL, info);
+ /* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */
+ for (i = 0; i < 16; i++)
+ pll_regs[i] = aty_ld_pll(i, info);
+
+ /*
+ * PLL Reference Devider M:
+ */
+ M = pll_regs[2];
+
+ /*
+ * PLL Feedback Devider N (Dependant on CLOCK_CNTL):
+ */
+ N = pll_regs[7 + (clock_cntl & 3)];
+
+ /*
+ * PLL Post Devider P (Dependant on CLOCK_CNTL):
+ */
+ P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
+
+ /*
+ * PLL Devider Q:
+ */
+ Q = N / P;
+
+ /*
+ * Target Frequency:
+ *
+ * T * M
+ * Q = -------
+ * 2 * R
+ *
+ * where R is XTALIN (= 14318 kHz).
+ */
+ T = 2 * Q * 14318 / M;
+
+ default_var.pixclock = 1000000000 / T;
}
#else /* __sparc__ */
@@ -2661,6 +2922,11 @@ __initfunc(void atyfb_init(void))
info->ati_regbase = (unsigned long)
ioremap(info->ati_regbase_phys, 0x1000);
+ if(!info->ati_regbase) {
+ kfree(info);
+ return;
+ }
+
info->ati_regbase_phys += 0xc00;
info->ati_regbase += 0xc00;
@@ -2683,13 +2949,38 @@ __initfunc(void atyfb_init(void))
info->frame_buffer_phys = addr;
info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
+ if(!info->frame_buffer) {
+ kfree(info);
+ return;
+ }
+
#endif /* __sparc__ */
if (!aty_init(info, "PCI")) {
if (info->mmap_map)
kfree(info->mmap_map);
kfree(info);
+ return;
}
+
+#ifdef __sparc__
+ if (!prom_palette)
+ prom_palette = atyfb_palette;
+
+ /*
+ * Add /dev/fb mmap values.
+ */
+ info->mmap_map[0].voff = 0x8000000000000000UL;
+ info->mmap_map[0].poff = __pa(info->frame_buffer & PAGE_MASK);
+ info->mmap_map[0].size = info->total_vram;
+ info->mmap_map[0].prot_mask = _PAGE_CACHE;
+ info->mmap_map[0].prot_flag = _PAGE_E;
+ info->mmap_map[1].voff = info->mmap_map[0].voff + info->total_vram;
+ info->mmap_map[1].poff = __pa(info->ati_regbase & PAGE_MASK);
+ info->mmap_map[1].size = PAGE_SIZE;
+ info->mmap_map[1].prot_mask = _PAGE_CACHE;
+ info->mmap_map[1].prot_flag = _PAGE_E;
+#endif /* __sparc__ */
}
}
#elif defined(CONFIG_ATARI)
@@ -2705,6 +2996,11 @@ __initfunc(void atyfb_init(void))
}
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));
/*
* Map the video memory (physical address given) to somewhere in the
@@ -2736,63 +3032,78 @@ __initfunc(void atyfb_of_init(struct device_node *dp))
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 (dp->n_addrs) {
+ case 1:
+ case 2:
+ 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");
+ return;
+ }
- info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
+ info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
+ if (!info) {
+ printk("atyfb_of_init: can't alloc fb_info_aty\n");
+ return;
+ }
+ memset(info, 0, sizeof(struct fb_info_aty));
- 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,
+ 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);
- }
+
+ if(! info->ati_regbase) {
+ printk("atyfb_init: ioremap() returned NULL\n");
+ kfree(info);
+ return;
+ }
+
+ 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;
+ /* 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);
+ /* Map in frame buffer */
+ info->frame_buffer_phys = addr;
+ info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
- if (!aty_init(info, dp->full_name)) {
+ if(! info->frame_buffer) {
+ printk("atyfb_init: ioremap() returned NULL\n");
kfree(info);
return;
- }
+ }
+
+ if (!aty_init(info, dp->full_name)) {
+ kfree(info);
+ return;
+ }
#ifdef CONFIG_FB_COMPAT_XPMAC
- if (!console_fb_info)
- console_fb_info = &info->fb_info;
+ if (!console_fb_info)
+ console_fb_info = &info->fb_info;
#endif /* CONFIG_FB_COMPAT_XPMAC */
- }
}
#endif /* CONFIG_FB_OF */
@@ -2816,25 +3127,35 @@ __initfunc(void atyfb_setup(char *options, int *ints))
break;
memcpy(fontname, this_opt + 5, i);
fontname[i] = 0;
- }
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
- if (!strncmp(this_opt, "vmode:", 6)) {
- int vmode = simple_strtoul(this_opt+6, NULL, 0);
+ } else if (!strncmp(this_opt, "noblink", 7)) {
+ curblink = 0;
+ } else if (!strncmp(this_opt, "noaccel", 7)) {
+ noaccel = 1;
+ } else if (!strncmp(this_opt, "vram:", 5))
+ default_vram = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "pll:", 4))
+ default_pll = simple_strtoul(this_opt+4, NULL, 0);
+ else if (!strncmp(this_opt, "mclk:", 5))
+ default_mclk = simple_strtoul(this_opt+5, NULL, 0);
+#if defined(CONFIG_PPC)
+ else if (!strncmp(this_opt, "vmode:", 6)) {
+ unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
if (vmode > 0 && vmode <= VMODE_MAX)
default_vmode = vmode;
} else if (!strncmp(this_opt, "cmode:", 6)) {
- int depth = simple_strtoul(this_opt+6, NULL, 0);
- switch (depth) {
+ unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
+ switch (cmode) {
+ case 0:
case 8:
- default_cmode = 0;
+ default_cmode = CMODE_8;
break;
case 15:
case 16:
- default_cmode = 1;
+ default_cmode = CMODE_16;
break;
case 24:
case 32:
- default_cmode = 2;
+ default_cmode = CMODE_32;
break;
}
}
@@ -2844,7 +3165,7 @@ __initfunc(void atyfb_setup(char *options, int *ints))
* 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))) {
+ else 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);
@@ -2914,8 +3235,7 @@ static int atyfbcon_switch(int con, struct fb_info *fb)
/* 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, fb);
+ fb_get_cmap(&fb_display[currcon].cmap, 1, atyfb_getcolreg, fb);
/* Erase HW Cursor */
if (info->cursor)
@@ -2926,6 +3246,8 @@ static int atyfbcon_switch(int con, struct fb_info *fb)
atyfb_decode_var(&fb_display[con].var, &par, info);
atyfb_set_par(&par, info);
+ atyfb_set_disp(&fb_display[con], info, par.crtc.bpp,
+ par.accel_flags & FB_ACCELF_TEXT);
/* Install new colormap */
do_install_cmap(con, fb);
@@ -2940,19 +3262,6 @@ static int atyfbcon_switch(int con, struct fb_info *fb)
}
/*
- * Update the `var' structure (called by fbcon.c)
- */
-
-static int atyfbcon_updatevar(int con, struct fb_info *fb)
-{
- 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;
-}
-
- /*
* Blank the display.
*/
@@ -2995,9 +3304,10 @@ static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
if (regno > 255)
return 1;
- *red = info->palette[regno].red;
- *green = info->palette[regno].green;
- *blue = info->palette[regno].blue;
+ *red = (info->palette[regno].red<<8) | info->palette[regno].red;
+ *green = (info->palette[regno].green<<8) | info->palette[regno].green;
+ *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue;
+ *transp = 0;
return 0;
}
@@ -3016,6 +3326,9 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
if (regno > 255)
return 1;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
info->palette[regno].red = red;
info->palette[regno].green = green;
info->palette[regno].blue = blue;
@@ -3025,30 +3338,39 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
(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);
+ aty_st_8(DAC_MASK, 0xff, info);
eieio();
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();
- info->aty_cmap_regs->lut = red << scale;
+ info->aty_cmap_regs->lut = red;
eieio();
- info->aty_cmap_regs->lut = green << scale;
+ info->aty_cmap_regs->lut = green;
eieio();
- info->aty_cmap_regs->lut = blue << scale;
+ info->aty_cmap_regs->lut = blue;
eieio();
- if (regno < 16) {
+ if (regno < 16)
+ switch (info->current_par.crtc.bpp) {
#ifdef FBCON_HAS_CFB16
- fbcon_cfb16_cmap[regno] = (regno << 10) | (regno << 5) | regno;
+ case 16:
+ info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
+ regno;
+ break;
#endif
#ifdef FBCON_HAS_CFB24
- fbcon_cfb24_cmap[regno] = (regno << 16) | (regno << 8) | regno;
+ case 24:
+ info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) |
+ regno;
+ break;
#endif
#ifdef FBCON_HAS_CFB32
- fbcon_cfb32_cmap[regno] = (regno << 24) | (regno << 16) |
- (regno << 8) | regno;
+ case 32:
+ i = (regno << 8) | regno;
+ info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
+ break;
#endif
- }
+ }
return 0;
}
@@ -3058,12 +3380,10 @@ static void do_install_cmap(int con, struct fb_info *info)
if (con != currcon)
return;
if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
- atyfb_setcolreg, info);
+ fb_set_cmap(&fb_display[con].cmap, 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);
+ fb_set_cmap(fb_default_cmap(size), 1, atyfb_setcolreg, info);
}
}
@@ -3113,14 +3433,8 @@ static inline void aty_rectcopy(int srcx, int srcy, int dstx, int dsty,
} else
direction |= DST_X_LEFT_TO_RIGHT;
- wait_for_fifo(5, info);
+ wait_for_fifo(4, info);
aty_st_le32(DP_SRC, FRGD_SRC_BLIT, info);
- /*
- * ++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(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);
@@ -3149,6 +3463,50 @@ static inline void aty_rectfill(int dstx, int dsty, u_int width, u_int height,
draw_rect(dstx, dsty, width, height, info);
}
+ /*
+ * Update the `var' structure (called by fbcon.c)
+ */
+
+static int atyfbcon_updatevar(int con, struct fb_info *fb)
+{
+ struct fb_info_aty *info = (struct fb_info_aty *)fb;
+ struct atyfb_par *par = &info->current_par;
+ struct display *p = &fb_display[con];
+ struct vc_data *conp = p->conp;
+ u32 yres, yoffset, sy, height;
+
+ yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;
+ yoffset = fb_display[con].var.yoffset;
+
+ sy = (conp->vc_rows + p->yscroll) * fontheight(p);
+ height = yres - conp->vc_rows * fontheight(p);
+
+ if (height && (yoffset + yres > sy)) {
+ u32 xres, xoffset;
+ u32 bgx;
+
+ xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
+ xoffset = fb_display[con].var.xoffset;
+
+
+ bgx = attr_bgcol_ec(p, conp);
+ bgx |= (bgx << 8);
+ bgx |= (bgx << 16);
+
+ if (sy + height > par->crtc.vyres) {
+ wait_for_fifo(1, info);
+ aty_st_le32(SC_BOTTOM, sy + height - 1, info);
+ }
+ aty_rectfill(xoffset, sy, xres, height, bgx, info);
+ }
+
+ if (info->cursor && (yoffset + yres <= sy))
+ atyfb_cursor(p, CM_ERASE, info->cursor->pos.x, info->cursor->pos.y);
+
+ info->current_par.crtc.yoffset = yoffset;
+ set_off_pitch(&info->current_par, info);
+ return 0;
+}
/*
* Text console acceleration
@@ -3164,12 +3522,12 @@ static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx,
return;
#endif
- sx *= p->fontwidth;
- sy *= p->fontheight;
- dx *= p->fontwidth;
- dy *= p->fontheight;
- width *= p->fontwidth;
- height *= p->fontheight;
+ sx *= fontwidth(p);
+ sy *= fontheight(p);
+ dx *= fontwidth(p);
+ dy *= fontheight(p);
+ width *= fontwidth(p);
+ height *= fontheight(p);
aty_rectcopy(sx, sy, dx, dy, width, height,
(struct fb_info_aty *)p->fb_info);
@@ -3190,10 +3548,10 @@ static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy,
bgx |= (bgx << 8);
bgx |= (bgx << 16);
- sx *= p->fontwidth;
- sy *= p->fontheight;
- width *= p->fontwidth;
- height *= p->fontheight;
+ sx *= fontwidth(p);
+ sy *= fontheight(p);
+ width *= fontwidth(p);
+ height *= fontheight(p);
aty_rectfill(sx, sy, width, height, bgx,
(struct fb_info_aty *)p->fb_info);
diff --git a/drivers/video/bwtwofb.c b/drivers/video/bwtwofb.c
index a907fc2d1..00db47d10 100644
--- a/drivers/video/bwtwofb.c
+++ b/drivers/video/bwtwofb.c
@@ -1,4 +1,4 @@
-/* $Id: bwtwofb.c,v 1.1 1998/07/21 14:50:48 jj Exp $
+/* $Id: bwtwofb.c,v 1.6 1998/09/15 15:45:35 jj Exp $
* bwtwofb.c: BWtwo frame buffer driver
*
* Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -23,13 +23,13 @@
#include <linux/init.h>
#include <linux/selection.h>
-#include "sbusfb.h"
+#include <video/sbusfb.h>
#include <asm/io.h>
#ifndef __sparc_v9__
#include <asm/sun4paddr.h>
#endif
-#include "fbcon-mfb.h"
+#include <video/fbcon-mfb.h>
/* OBio addresses for the bwtwo registers */
#define BWTWO_REGISTER_OFFSET 0x400000
@@ -63,6 +63,7 @@ struct bw2_regs {
#define BWTWO_SR_ID_MONO 0x02
#define BWTWO_SR_ID_MONO_ECL 0x03
#define BWTWO_SR_ID_MSYNC 0x04
+#define BWTWO_SR_ID_NOCONN 0x0a
/* Control Register Constants */
#define BWTWO_CTL_ENABLE_INTS 0x80
@@ -94,7 +95,7 @@ static void bw2_unblank (struct fb_info_sbusfb *fb)
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;
+ p->screen_base += (y_margin - fb->y_margin) * p->line_length + ((x_margin - fb->x_margin) >> 3);
}
static u8 bw2regs_1600[] __initdata = {
@@ -134,13 +135,13 @@ static u8 bw2regs_66hz[] __initdata = {
static char idstring[60] __initdata = { 0 };
-__initfunc(char *bwtwofb_init(struct fb_info_sbusfb *fb))
+char __init *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;
+ unsigned long phys = sun4_bwtwo_physaddr;
#else
unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
#endif
@@ -152,7 +153,7 @@ __initfunc(char *bwtwofb_init(struct fb_info_sbusfb *fb))
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")) {
+ if ((!ARCH_SUN4) && (!prom_getbool(fb->prom_node, "width"))) {
/* Ugh, broken PROM didn't initialize us.
* Let's deal with this ourselves.
*/
@@ -182,6 +183,8 @@ __initfunc(char *bwtwofb_init(struct fb_info_sbusfb *fb))
else
p = bw2regs_66hz;
break;
+ case BWTWO_SR_ID_NOCONN:
+ return NULL;
default:
prom_printf("bw2: can't handle SR %02x\n",
status);
@@ -198,15 +201,18 @@ __initfunc(char *bwtwofb_init(struct fb_info_sbusfb *fb))
fix->line_length = fb->var.xres_virtual>>3;
disp->scrollmode = SCROLL_YREDRAW;
+ disp->inverse = 1;
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;
+ disp->screen_base += fix->line_length * fb->y_margin + (fb->x_margin >> 3);
fb->dispsw = fbcon_mfb;
fix->visual = FB_VISUAL_MONO01;
+#ifndef CONFIG_SUN4
fb->blank = bw2_blank;
fb->unblank = bw2_unblank;
+#endif
fb->margins = bw2_margins;
fb->physbase = phys;
diff --git a/drivers/video/cgfourteenfb.c b/drivers/video/cgfourteenfb.c
new file mode 100644
index 000000000..f22389921
--- /dev/null
+++ b/drivers/video/cgfourteenfb.c
@@ -0,0 +1,384 @@
+/* $Id: cgfourteenfb.c,v 1.3 1998/09/04 15:43:41 jj Exp $
+ * cgfourteenfb.c: CGfourteen frame buffer driver
+ *
+ * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ */
+
+#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 <video/sbusfb.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+
+#include <video/fbcon-cfb8.h>
+
+#define CG14_MCR_INTENABLE_SHIFT 7
+#define CG14_MCR_INTENABLE_MASK 0x80
+#define CG14_MCR_VIDENABLE_SHIFT 6
+#define CG14_MCR_VIDENABLE_MASK 0x40
+#define CG14_MCR_PIXMODE_SHIFT 4
+#define CG14_MCR_PIXMODE_MASK 0x30
+#define CG14_MCR_TMR_SHIFT 2
+#define CG14_MCR_TMR_MASK 0x0c
+#define CG14_MCR_TMENABLE_SHIFT 1
+#define CG14_MCR_TMENABLE_MASK 0x02
+#define CG14_MCR_RESET_SHIFT 0
+#define CG14_MCR_RESET_MASK 0x01
+#define CG14_REV_REVISION_SHIFT 4
+#define CG14_REV_REVISION_MASK 0xf0
+#define CG14_REV_IMPL_SHIFT 0
+#define CG14_REV_IMPL_MASK 0x0f
+#define CG14_VBR_FRAMEBASE_SHIFT 12
+#define CG14_VBR_FRAMEBASE_MASK 0x00fff000
+#define CG14_VMCR1_SETUP_SHIFT 0
+#define CG14_VMCR1_SETUP_MASK 0x000001ff
+#define CG14_VMCR1_VCONFIG_SHIFT 9
+#define CG14_VMCR1_VCONFIG_MASK 0x00000e00
+#define CG14_VMCR2_REFRESH_SHIFT 0
+#define CG14_VMCR2_REFRESH_MASK 0x00000001
+#define CG14_VMCR2_TESTROWCNT_SHIFT 1
+#define CG14_VMCR2_TESTROWCNT_MASK 0x00000002
+#define CG14_VMCR2_FBCONFIG_SHIFT 2
+#define CG14_VMCR2_FBCONFIG_MASK 0x0000000c
+#define CG14_VCR_REFRESHREQ_SHIFT 0
+#define CG14_VCR_REFRESHREQ_MASK 0x000003ff
+#define CG14_VCR1_REFRESHENA_SHIFT 10
+#define CG14_VCR1_REFRESHENA_MASK 0x00000400
+#define CG14_VCA_CAD_SHIFT 0
+#define CG14_VCA_CAD_MASK 0x000003ff
+#define CG14_VCA_VERS_SHIFT 10
+#define CG14_VCA_VERS_MASK 0x00000c00
+#define CG14_VCA_RAMSPEED_SHIFT 12
+#define CG14_VCA_RAMSPEED_MASK 0x00001000
+#define CG14_VCA_8MB_SHIFT 13
+#define CG14_VCA_8MB_MASK 0x00002000
+
+#define CG14_MCR_PIXMODE_8 0
+#define CG14_MCR_PIXMODE_16 2
+#define CG14_MCR_PIXMODE_32 3
+
+struct cg14_regs{
+ volatile u8 mcr; /* Master Control Reg */
+ volatile u8 ppr; /* Packed Pixel Reg */
+ volatile u8 tms[2]; /* Test Mode Status Regs */
+ volatile u8 msr; /* Master Status Reg */
+ volatile u8 fsr; /* Fault Status Reg */
+ volatile u8 rev; /* Revision & Impl */
+ volatile u8 ccr; /* Clock Control Reg */
+ volatile u32 tmr; /* Test Mode Read Back */
+ volatile u8 mod; /* Monitor Operation Data Reg */
+ volatile u8 acr; /* Aux Control */
+ u8 xxx0[6];
+ volatile u16 hct; /* Hor Counter */
+ volatile u16 vct; /* Vert Counter */
+ volatile u16 hbs; /* Hor Blank Start */
+ volatile u16 hbc; /* Hor Blank Clear */
+ volatile u16 hss; /* Hor Sync Start */
+ volatile u16 hsc; /* Hor Sync Clear */
+ volatile u16 csc; /* Composite Sync Clear */
+ volatile u16 vbs; /* Vert Blank Start */
+ volatile u16 vbc; /* Vert Blank Clear */
+ volatile u16 vss; /* Vert Sync Start */
+ volatile u16 vsc; /* Vert Sync Clear */
+ volatile u16 xcs;
+ volatile u16 xcc;
+ volatile u16 fsa; /* Fault Status Address */
+ volatile u16 adr; /* Address Registers */
+ u8 xxx1[0xce];
+ volatile u8 pcg[0x100]; /* Pixel Clock Generator */
+ volatile u32 vbr; /* Frame Base Row */
+ volatile u32 vmcr; /* VBC Master Control */
+ volatile u32 vcr; /* VBC refresh */
+ volatile u32 vca; /* VBC Config */
+};
+
+#define CG14_CCR_ENABLE 0x04
+#define CG14_CCR_SELECT 0x02 /* HW/Full screen */
+
+struct cg14_cursor {
+ volatile u32 cpl0[32]; /* Enable plane 0 */
+ volatile u32 cpl1[32]; /* Color selection plane */
+ volatile u8 ccr; /* Cursor Control Reg */
+ u8 xxx0[3];
+ volatile u16 cursx; /* Cursor x,y position */
+ volatile u16 cursy; /* Cursor x,y position */
+ volatile u32 color0;
+ volatile u32 color1;
+ u32 xxx1[0x1bc];
+ volatile u32 cpl0i[32]; /* Enable plane 0 autoinc */
+ volatile u32 cpl1i[32]; /* Color selection autoinc */
+};
+
+struct cg14_dac {
+ volatile u8 addr; /* Address Register */
+ u8 xxx0[255];
+ volatile u8 glut; /* Gamma table */
+ u8 xxx1[255];
+ volatile u8 select; /* Register Select */
+ u8 xxx2[255];
+ volatile u8 mode; /* Mode Register */
+};
+
+struct cg14_xlut{
+ volatile u8 x_xlut [256];
+ volatile u8 x_xlutd [256];
+ u8 xxx0[0x600];
+ volatile u8 x_xlut_inc [256];
+ volatile u8 x_xlutd_inc [256];
+};
+
+/* Color look up table (clut) */
+/* Each one of these arrays hold the color lookup table (for 256
+ * colors) for each MDI page (I assume then there should be 4 MDI
+ * pages, I still wonder what they are. I have seen NeXTStep split
+ * the screen in four parts, while operating in 24 bits mode. Each
+ * integer holds 4 values: alpha value (transparency channel, thanks
+ * go to John Stone (johns@umr.edu) from OpenBSD), red, green and blue
+ *
+ * I currently use the clut instead of the Xlut
+ */
+struct cg14_clut {
+ unsigned int c_clut [256];
+ unsigned int c_clutd [256]; /* i wonder what the 'd' is for */
+ unsigned int c_clut_inc [256];
+ unsigned int c_clutd_inc [256];
+};
+
+static struct sbus_mmap_map cg14_mmap_map[] __initdata = {
+ { CG14_REGS, 0x80000000, 0x1000 },
+ { CG14_XLUT, 0x80003000, 0x1000 },
+ { CG14_CLUT1, 0x80004000, 0x1000 },
+ { CG14_CLUT2, 0x80005000, 0x1000 },
+ { CG14_CLUT3, 0x80006000, 0x1000 },
+ { CG3_MMAP_OFFSET -
+ 0x7000, 0x80000000, 0x7000 },
+ { CG3_MMAP_OFFSET, 0x00000000, SBUS_MMAP_FBSIZE(1) },
+ { MDI_CURSOR_MAP, 0x80001000, 0x1000 },
+ { MDI_CHUNKY_BGR_MAP, 0x01000000, 0x400000 },
+ { MDI_PLANAR_X16_MAP, 0x02000000, 0x200000 },
+ { MDI_PLANAR_C16_MAP, 0x02800000, 0x200000 },
+ { MDI_PLANAR_X32_MAP, 0x03000000, 0x100000 },
+ { MDI_PLANAR_B32_MAP, 0x03400000, 0x100000 },
+ { MDI_PLANAR_G32_MAP, 0x03800000, 0x100000 },
+ { MDI_PLANAR_R32_MAP, 0x03c00000, 0x100000 },
+ { 0, 0, 0 }
+};
+
+static void cg14_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
+{
+ struct cg14_clut *clut = fb->s.cg14.clut;
+
+ for (; count--; index++)
+ clut->c_clut[index] =
+ (fb->color_map CM(index,2) << 16) |
+ (fb->color_map CM(index,1) << 8) |
+ (fb->color_map CM(index,0));
+}
+
+static void cg14_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 void cg14_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
+{
+ struct cg14_cursor *cur = fb->s.cg14.cursor;
+
+ cur->color0 = ((red[0]) | (green[0] << 8) | (blue[0] << 16));
+ cur->color1 = ((red[1]) | (green[1] << 8) | (blue[1] << 16));
+}
+
+/* Set cursor shape */
+static void cg14_setcurshape (struct fb_info_sbusfb *fb)
+{
+ struct cg14_cursor *cur = fb->s.cg14.cursor;
+ int i;
+
+ for (i = 0; i < 32; i++){
+ cur->cpl0 [i] = fb->cursor.bits[0][i];
+ cur->cpl1 [i] = fb->cursor.bits[1][i];
+ }
+}
+
+/* Load cursor information */
+static void cg14_setcursor (struct fb_info_sbusfb *fb)
+{
+ struct cg_cursor *c = &fb->cursor;
+ struct cg14_cursor *cur = fb->s.cg14.cursor;
+
+ if (c->enable)
+ cur->ccr |= CG14_CCR_ENABLE;
+ cur->cursx = ((c->cpos.fbx - c->chot.fbx) & 0xfff);
+ cur->cursy = ((c->cpos.fby - c->chot.fby) & 0xfff);
+}
+
+static void cg14_switch_from_graph (struct fb_info_sbusfb *fb)
+{
+ /* Set the 8-bpp mode */
+ if (fb->open && fb->mmaped){
+ volatile char *mcr = &fb->s.cg14.regs->mcr;
+
+ fb->s.cg14.mode = 8;
+ *mcr = (*mcr & ~(CG14_MCR_PIXMODE_MASK));
+ }
+}
+
+static void cg14_reset (struct fb_info_sbusfb *fb)
+{
+ volatile char *mcr = &fb->s.cg14.regs->mcr;
+
+ *mcr = (*mcr & ~(CG14_MCR_PIXMODE_MASK));
+}
+
+static int cg14_ioctl (struct fb_info_sbusfb *fb, unsigned int cmd, unsigned long arg)
+{
+ volatile char *mcr = &fb->s.cg14.regs->mcr;
+ struct mdi_cfginfo *mdii;
+ int mode;
+
+ switch (cmd) {
+ case MDI_RESET:
+ *mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK);
+ break;
+ case MDI_GET_CFGINFO:
+ mdii = (struct mdi_cfginfo *)arg;
+ put_user_ret(FBTYPE_MDICOLOR, &mdii->mdi_type, -EFAULT);
+ __put_user_ret(fb->type.fb_height, &mdii->mdi_height, -EFAULT);
+ __put_user_ret(fb->type.fb_width, &mdii->mdi_width, -EFAULT);
+ __put_user_ret(fb->s.cg14.mode, &mdii->mdi_mode, -EFAULT);
+ __put_user_ret(72, &mdii->mdi_pixfreq, -EFAULT); /* FIXME */
+ __put_user_ret(fb->s.cg14.ramsize, &mdii->mdi_size, -EFAULT);
+ break;
+ case MDI_SET_PIXELMODE:
+ get_user_ret(mode, (int *)arg, -EFAULT);
+ switch (mode){
+ case MDI_32_PIX:
+ *mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK) |
+ (CG14_MCR_PIXMODE_32 << CG14_MCR_PIXMODE_SHIFT);
+ break;
+ case MDI_16_PIX:
+ *mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK) | 0x20;
+ break;
+ case MDI_8_PIX:
+ *mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK);
+ break;
+ default:
+ return -ENOSYS;
+ }
+ fb->s.cg14.mode = mode;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+__initfunc(static unsigned long get_phys(unsigned long addr))
+{
+ return __get_phys(addr);
+}
+
+__initfunc(static int get_iospace(unsigned long addr))
+{
+ return __get_iospace(addr);
+}
+
+static char idstring[60] __initdata = { 0 };
+
+__initfunc(char *cgfourteenfb_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 rphys, phys;
+ u32 bases[6];
+ int is_8mb, i;
+
+#ifndef FBCON_HAS_CFB8
+ return NULL;
+#endif
+ prom_getproperty (fb->prom_node, "address", (char *) &bases[0], 8);
+ if (!bases[0]) {
+ printk("cg14 not mmaped\n");
+ return NULL;
+ }
+ if (get_iospace(bases[0]) != get_iospace(bases[1])) {
+ printk("Ugh. cg14 iospaces don't match\n");
+ return NULL;
+ }
+ fb->physbase = phys = get_phys(bases[1]);
+ rphys = get_phys(bases[0]);
+ fb->iospace = get_iospace(bases[0]);
+ fb->s.cg14.regs = (struct cg14_regs *)(unsigned long)bases[0];
+ fb->s.cg14.clut = (void *)((unsigned long)bases[0]+CG14_CLUT1);
+ fb->s.cg14.cursor = (void *)((unsigned long)bases[0]+CG14_CURSORREGS);
+ disp->screen_base = (char *)bases[1];
+
+ /* CG14_VCA_8MB_MASK is not correctly set on the 501-2482
+ * VSIMM, so we read the memory size from the PROM
+ */
+ prom_getproperty(fb->prom_node, "reg", (char *) &bases[0], 24);
+ is_8mb = bases[5] == 0x800000;
+
+ fb->mmap_map = kmalloc(sizeof(cg14_mmap_map), GFP_KERNEL);
+ if (!fb->mmap_map)
+ return NULL;
+
+ for (i = 0; ; i++) {
+ fb->mmap_map[i].voff = cg14_mmap_map[i].voff;
+ fb->mmap_map[i].poff = (cg14_mmap_map[i].poff & 0x80000000) ?
+ (cg14_mmap_map[i].poff & 0x7fffffff) + rphys - phys :
+ cg14_mmap_map[i].poff;
+ fb->mmap_map[i].size = cg14_mmap_map[i].size;
+ if (is_8mb && fb->mmap_map[i].size >= 0x100000 &&
+ fb->mmap_map[i].size <= 0x400000)
+ fb->mmap_map[i].size <<= 1;
+ if (!cg14_mmap_map[i].size)
+ break;
+ }
+
+ strcpy(fb->info.modename, "CGfourteen");
+ strcpy(fix->id, "CGfourteen");
+ fix->line_length = fb->var.xres_virtual;
+
+ disp->scrollmode = SCROLL_YREDRAW;
+ disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
+ fb->dispsw = fbcon_cfb8;
+
+ type->fb_depth = 24;
+ fb->emulations[1] = FBTYPE_SUN3COLOR;
+
+ fb->margins = cg14_margins;
+ fb->loadcmap = cg14_loadcmap;
+ fb->setcursor = cg14_setcursor;
+ fb->setcursormap = cg14_setcursormap;
+ fb->setcurshape = cg14_setcurshape;
+ fb->reset = cg14_reset;
+ fb->switch_from_graph = cg14_switch_from_graph;
+ fb->ioctl = cg14_ioctl;
+
+ fb->s.cg14.mode = 8;
+ fb->s.cg14.ramsize = (is_8mb) ? 0x800000 : 0x400000;
+
+ cg14_reset(fb);
+
+ sprintf(idstring, "cgfourteen at %x.%08lx, %dMB, rev=%d, impl=%d", fb->iospace, phys,
+ is_8mb ? 8 : 4, fb->s.cg14.regs->rev >> 4, fb->s.cg14.regs->rev & 0xf);
+
+ return idstring;
+}
diff --git a/drivers/video/cgsixfb.c b/drivers/video/cgsixfb.c
index d5fc9f495..4e0bc74ed 100644
--- a/drivers/video/cgsixfb.c
+++ b/drivers/video/cgsixfb.c
@@ -1,4 +1,4 @@
-/* $Id: cgsixfb.c,v 1.7 1998/07/22 12:44:59 jj Exp $
+/* $Id: cgsixfb.c,v 1.11 1998/09/04 15:43:42 jj Exp $
* cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
*
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -6,7 +6,6 @@
* 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>
@@ -22,7 +21,7 @@
#include <linux/init.h>
#include <linux/selection.h>
-#include "sbusfb.h"
+#include <video/sbusfb.h>
#include <asm/io.h>
/* Offset of interesting structures in the OBIO space */
@@ -246,15 +245,15 @@ static void cg6_clear(struct vc_data *conp, struct display *p, int sy, int sx,
fbc->clip = 0;
fbc->pm = ~(0);
- if (p->fontheightlog) {
- y = sy << p->fontheightlog; h = height << p->fontheightlog;
+ if (fontheightlog(p)) {
+ y = sy << fontheightlog(p); h = height << fontheightlog(p);
} else {
- y = sy * p->fontheight; h = height * p->fontheight;
+ y = sy * fontheight(p); h = height * fontheight(p);
}
- if (p->fontwidthlog) {
- x = sx << p->fontwidthlog; w = width << p->fontwidthlog;
+ if (fontwidthlog(p)) {
+ x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
} else {
- x = sx * p->fontwidth; w = width * p->fontwidth;
+ x = sx * fontwidth(p); w = width * fontwidth(p);
}
fbc->arecty = y + fb->y_margin;
fbc->arectx = x + fb->x_margin;
@@ -300,26 +299,21 @@ static void cg6_putc(struct vc_data *conp, struct display *p, int c, int yy, int
int i, x, y;
u8 *fd;
- if (p->fontheightlog) {
- y = fb->y_margin + (yy << p->fontheightlog);
- i = ((c & p->charmask) << p->fontheightlog);
+ if (fontheightlog(p)) {
+ y = fb->y_margin + (yy << fontheightlog(p));
+ i = ((c & p->charmask) << fontheightlog(p));
} else {
- y = fb->y_margin + (yy * p->fontheight);
- i = (c & p->charmask) * p->fontheight;
+ y = fb->y_margin + (yy * fontheight(p));
+ i = (c & p->charmask) * fontheight(p);
}
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
- fd = p->fontdata + i;
- x = fb->x_margin + xx * 8;
-#else
- if (p->fontwidth <= 8)
+ if (fontwidth(p) <= 8)
fd = p->fontdata + i;
else
fd = p->fontdata + (i << 1);
- if (p->fontwidthlog)
- x = fb->x_margin + (xx << p->fontwidthlog);
+ if (fontwidthlog(p))
+ x = fb->x_margin + (xx << fontwidthlog(p));
else
- x = fb->x_margin + (xx * p->fontwidth);
-#endif
+ x = fb->x_margin + (xx * fontwidth(p));
do {
i = fbc->s;
} while (i & 0x10000000);
@@ -334,21 +328,17 @@ static void cg6_putc(struct vc_data *conp, struct display *p, int c, int yy, int
fbc->incx = 0;
fbc->incy = 1;
fbc->x0 = x;
- fbc->x1 = x + p->fontwidth - 1;
+ fbc->x1 = x + fontwidth(p) - 1;
fbc->y0 = y;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
- if (p->fontwidth <= 8) {
-#endif
- for (i = 0; i < p->fontheight; i++)
+ if (fontwidth(p) <= 8) {
+ for (i = 0; i < fontheight(p); i++)
fbc->font = *fd++ << 24;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
} else {
- for (i = 0; i < p->fontheight; i++) {
+ for (i = 0; i < fontheight(p); i++) {
fbc->font = *(u16 *)fd << 16;
fd += 2;
}
}
-#endif
}
static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
@@ -372,50 +362,41 @@ static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned sh
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);
+ if (fontwidthlog(p))
+ x += (xx << fontwidthlog(p));
else
- x += xx * p->fontwidth;
-#endif
- if (p->fontheightlog)
- y += (yy << p->fontheightlog);
+ x += xx * fontwidth(p);
+ if (fontheightlog(p))
+ y += (yy << fontheightlog(p));
else
- y += (yy * p->fontheight);
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
- if (p->fontwidth <= 8) {
-#endif
+ y += (yy * fontheight(p));
+ if (fontwidth(p) <= 8) {
while (count >= 4) {
count -= 4;
fbc->incx = 0;
fbc->incy = 1;
fbc->x0 = x;
- fbc->x1 = (x += 4 * p->fontwidth) - 1;
+ fbc->x1 = (x += 4 * fontwidth(p)) - 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);
+ if (fontheightlog(p)) {
+ fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+ fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+ fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+ fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
} 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);
+ fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+ fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+ fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+ fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
}
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
- if (p->fontwidth == 8) {
-#endif
- for (i = 0; i < p->fontheight; i++)
+ if (fontwidth(p) == 8) {
+ for (i = 0; i < fontheight(p); 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++)
+ for (i = 0; i < fontheight(p); i++)
fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
- << p->fontwidth)) << p->fontwidth)) << p->fontwidth)) << (24 - 3 * p->fontwidth);
+ << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
}
}
} else {
@@ -424,48 +405,43 @@ static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned sh
fbc->incx = 0;
fbc->incy = 1;
fbc->x0 = x;
- fbc->x1 = (x += 2 * p->fontwidth) - 1;
+ fbc->x1 = (x += 2 * fontwidth(p)) - 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));
+ if (fontheightlog(p)) {
+ fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
+ fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
} else {
- fd1 = p->fontdata + (((*s++ & p->charmask) * p->fontheight) << 1);
- fd2 = p->fontdata + (((*s++ & p->charmask) * p->fontheight) << 1);
+ fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
+ fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
}
- for (i = 0; i < p->fontheight; i++) {
- fbc->font = ((((u32)*(u16 *)fd1) << p->fontwidth) | ((u32)*(u16 *)fd2)) << (16 - p->fontwidth);
+ for (i = 0; i < fontheight(p); i++) {
+ fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
fd1 += 2; fd2 += 2;
}
}
-#endif
}
while (count) {
count--;
fbc->incx = 0;
fbc->incy = 1;
fbc->x0 = x;
- fbc->x1 = (x += p->fontwidth) - 1;
+ fbc->x1 = (x += fontwidth(p)) - 1;
fbc->y0 = y;
- if (p->fontheightlog)
- i = ((*s++ & p->charmask) << p->fontheightlog);
+ if (fontheightlog(p))
+ i = ((*s++ & p->charmask) << fontheightlog(p));
else
- i = ((*s++ & p->charmask) * p->fontheight);
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
- if (p->fontwidth <= 8) {
-#endif
+ i = ((*s++ & p->charmask) * fontheight(p));
+ if (fontwidth(p) <= 8) {
fd1 = p->fontdata + i;
- for (i = 0; i < p->fontheight; i++)
+ for (i = 0; i < fontheight(p); i++)
fbc->font = *fd1++ << 24;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
} else {
fd1 = p->fontdata + (i << 1);
- for (i = 0; i < p->fontheight; i++) {
+ for (i = 0; i < fontheight(p); i++) {
fbc->font = *(u16 *)fd1 << 16;
fd1 += 2;
}
}
-#endif
}
}
@@ -474,7 +450,7 @@ 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)
+static void cg6_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
{
struct bt_regs *bt = fb->s.cg6.bt;
int i;
@@ -556,11 +532,13 @@ static void cg6_unblank (struct fb_info_sbusfb *fb)
static void cg6_reset (struct fb_info_sbusfb *fb)
{
unsigned int rev, conf;
+ struct cg6_tec *tec = fb->s.cg6.tec;
+ struct cg6_fbc *fbc = fb->s.cg6.fbc;
/* 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;
+ tec->tec_matrix = 0;
+ tec->tec_clip = 0;
+ tec->tec_vdc = 0;
/* Take care of bugs in old revisions. */
rev = (*(fb->s.cg6.fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK;
@@ -575,21 +553,21 @@ static void cg6_reset (struct fb_info_sbusfb *fb)
}
/* 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;
+ 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);
+ 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);
+ fbc->clip = 0;
+ fbc->offx = 0;
+ fbc->offy = 0;
+ fbc->clipminx = 0;
+ fbc->clipminy = 0;
+ fbc->clipmaxx = fb->type.fb_width - 1;
+ 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;
@@ -611,6 +589,7 @@ __initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb))
unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
u32 conf;
char *p;
+ struct bt_regs *bt;
strcpy(fb->info.modename, "CGsix");
@@ -631,7 +610,7 @@ __initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb))
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,
+ fb->s.cg6.bt = 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);
@@ -652,14 +631,14 @@ __initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb))
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;
+ bt->addr = 0x04 << 24; /* color planes */
+ bt->control = 0xff << 24;
+ bt->addr = 0x05 << 24;
+ bt->control = 0x00 << 24;
+ bt->addr = 0x06 << 24; /* overlay plane */
+ bt->control = 0x73 << 24;
+ bt->addr = 0x07 << 24;
+ bt->control = 0x00 << 24;
conf = *fb->s.cg6.fhc;
switch(conf & CG6_FHC_CPU_MASK) {
diff --git a/drivers/video/cgthreefb.c b/drivers/video/cgthreefb.c
index 2cab0fc25..882669d8f 100644
--- a/drivers/video/cgthreefb.c
+++ b/drivers/video/cgthreefb.c
@@ -1,4 +1,4 @@
-/* $Id: cgthreefb.c,v 1.1 1998/07/21 14:50:47 jj Exp $
+/* $Id: cgthreefb.c,v 1.3 1998/09/04 15:43:43 jj Exp $
* cgthreefb.c: CGthree frame buffer driver
*
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -21,10 +21,10 @@
#include <linux/init.h>
#include <linux/selection.h>
-#include "sbusfb.h"
+#include <video/sbusfb.h>
#include <asm/io.h>
-#include "fbcon-cfb8.h"
+#include <video/fbcon-cfb8.h>
/* Control Register Constants */
#define CG3_CR_ENABLE_INTS 0x80
@@ -85,7 +85,7 @@ static struct sbus_mmap_map cg3_mmap_map[] = {
#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)
+static void cg3_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
{
struct bt_regs *bt = &fb->s.cg3.regs->cmap;
u32 *i;
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index c13954030..699ae96ff 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -38,10 +38,10 @@
#include <asm/adb.h>
#include <asm/pmu.h>
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-#include "macmodes.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/macmodes.h>
static int currcon = 0;
@@ -62,15 +62,40 @@ struct fb_info_chips {
#ifdef CONFIG_PMAC_PBOOK
unsigned char *save_framebuffer;
#endif
+#ifdef FBCON_HAS_CFB16
+ u16 fbcon_cfb16_cmap[16];
+#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); }
-
+#define write_ind(num, val, ap, dp) do { \
+ out_8(p->io_base + (ap), (num)); out_8(p->io_base + (dp), (val)); \
+} while (0)
+#define read_ind(num, var, ap, dp) do { \
+ out_8(p->io_base + (ap), (num)); var = in_8(p->io_base + (dp)); \
+} while (0);
+
+/* extension registers */
+#define write_xr(num, val) write_ind(num, val, 0x3d6, 0x3d7)
+#define read_xr(num, var) read_ind(num, var, 0x3d6, 0x3d7)
+/* flat panel registers */
+#define write_fr(num, val) write_ind(num, val, 0x3d0, 0x3d1)
+#define read_fr(num, var) read_ind(num, var, 0x3d0, 0x3d1)
+/* CRTC registers */
+#define write_cr(num, val) write_ind(num, val, 0x3d4, 0x3d5)
+#define read_cr(num, var) read_ind(num, var, 0x3d4, 0x3d5)
+/* graphics registers */
+#define write_gr(num, val) write_ind(num, val, 0x3ce, 0x3cf)
+#define read_gr(num, var) read_ind(num, var, 0x3ce, 0x3cf)
+/* sequencer registers */
+#define write_sr(num, val) write_ind(num, val, 0x3c4, 0x3c5)
+#define read_sr(num, var) read_ind(num, var, 0x3c4, 0x3c5)
+/* attribute registers - slightly strange */
+#define write_ar(num, val) do { \
+ in_8(p->io_base + 0x3da); write_ind(num, val, 0x3c0, 0x3c0); \
+} while (0)
+#define read_ar(num, var) do { \
+ in_8(p->io_base + 0x3da); read_ind(num, var, 0x3c0, 0x3c1); \
+} while (0)
static struct fb_info_chips *all_chips;
@@ -187,8 +212,7 @@ 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);
+ return fb_get_cmap(cmap, 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
@@ -209,8 +233,7 @@ static int chips_set_cmap(struct fb_cmap *cmap, int kspc, int con,
}
if (con == currcon)
- return fb_set_cmap(cmap, &disp->var, kspc, chipsfb_setcolreg,
- info);
+ return fb_set_cmap(cmap, kspc, chipsfb_setcolreg, info);
fb_copy_cmap(cmap, &disp->cmap, kspc==0);
return 0;
}
@@ -229,9 +252,7 @@ static int chipsfb_switch(int con, struct fb_info *info)
int bit_depth;
if (fb_display[currcon].cmap.len)
- fb_get_cmap(&old_disp->cmap,
- &old_disp->var, 1, chipsfb_getcolreg,
- info);
+ fb_get_cmap(&old_disp->cmap, 1, chipsfb_getcolreg, info);
bit_depth = new_disp->var.bits_per_pixel;
if (old_disp->var.bits_per_pixel != bit_depth)
@@ -279,9 +300,10 @@ static int chipsfb_getcolreg(u_int regno, u_int *red, u_int *green,
if (regno > 255)
return 1;
- *red = p->palette[regno].red;
- *green = p->palette[regno].green;
- *blue = p->palette[regno].blue;
+ *red = (p->palette[regno].red<<8) | p->palette[regno].red;
+ *green = (p->palette[regno].green<<8) | p->palette[regno].green;
+ *blue = (p->palette[regno].blue<<8) | p->palette[regno].blue;
+ *transp = 0;
return 0;
}
@@ -289,21 +311,26 @@ 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;
+ int hr;
- if (regno > 255)
+ hr = (p->fix.visual != FB_VISUAL_PSEUDOCOLOR)? (regno << 3): regno;
+ if (hr > 255)
return 1;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
p->palette[regno].red = red;
p->palette[regno].green = green;
p->palette[regno].blue = blue;
- out_8(p->io_base + 0x3c8, regno);
+ out_8(p->io_base + 0x3c8, hr);
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;
+ if (regno < 16)
+ p->fbcon_cfb16_cmap[regno] = (red << 10) | (green << 5) | blue;
#endif
return 0;
@@ -314,18 +341,13 @@ 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);
+ fb_set_cmap(&fb_display[con].cmap, 1, chipsfb_setcolreg, info);
+ else {
+ int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+ fb_set_cmap(fb_default_cmap(size), 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;
@@ -336,12 +358,11 @@ static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, in
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;
+ fix->visual = FB_VISUAL_DIRECTCOLOR;
var->red.offset = 10;
var->green.offset = 5;
@@ -350,14 +371,14 @@ static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, in
#ifdef FBCON_HAS_CFB16
disp->dispsw = &fbcon_cfb16;
+ disp->dispsw_data = p->fbcon_cfb16_cmap;
#else
- disp->dispsw = NULL;
+ disp->dispsw = &fbcon_dummy;
#endif
- } else if (bpp == 8) {
+ } 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
}
@@ -370,7 +391,7 @@ static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, in
#ifdef FBCON_HAS_CFB8
disp->dispsw = &fbcon_cfb8;
#else
- disp->dispsw = NULL;
+ disp->dispsw = &fbcon_dummy;
#endif
}
@@ -392,11 +413,139 @@ static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, in
do_install_cmap(con, (struct fb_info *)p);
}
+struct chips_init_reg {
+ unsigned char addr;
+ unsigned char data;
+};
+
+#define N_ELTS(x) (sizeof(x) / sizeof(x[0]))
+
+static struct chips_init_reg chips_init_sr[] = {
+ { 0x00, 0x03 },
+ { 0x01, 0x01 },
+ { 0x02, 0x0f },
+ { 0x04, 0x0e }
+};
+
+static struct chips_init_reg chips_init_gr[] = {
+ { 0x05, 0x00 },
+ { 0x06, 0x0d },
+ { 0x08, 0xff }
+};
+
+static struct chips_init_reg chips_init_ar[] = {
+ { 0x10, 0x01 },
+ { 0x12, 0x0f },
+ { 0x13, 0x00 }
+};
+
+static struct chips_init_reg chips_init_cr[] = {
+ { 0x00, 0x7f },
+ { 0x01, 0x63 },
+ { 0x02, 0x63 },
+ { 0x03, 0x83 },
+ { 0x04, 0x66 },
+ { 0x05, 0x10 },
+ { 0x06, 0x72 },
+ { 0x07, 0x3e },
+ { 0x08, 0x00 },
+ { 0x09, 0x40 },
+ { 0x0c, 0x00 },
+ { 0x0d, 0x00 },
+ { 0x10, 0x59 },
+ { 0x11, 0x0d },
+ { 0x12, 0x57 },
+ { 0x13, 0x64 },
+ { 0x14, 0x00 },
+ { 0x15, 0x57 },
+ { 0x16, 0x73 },
+ { 0x17, 0xe3 },
+ { 0x18, 0xff },
+ { 0x30, 0x02 },
+ { 0x31, 0x02 },
+ { 0x32, 0x02 },
+ { 0x33, 0x02 },
+ { 0x40, 0x00 },
+ { 0x41, 0x00 },
+ { 0x40, 0x80 }
+};
+
+static struct chips_init_reg chips_init_fr[] = {
+ { 0x01, 0x02 },
+ { 0x03, 0x08 },
+ { 0x04, 0x81 },
+ { 0x05, 0x21 },
+ { 0x08, 0x0c },
+ { 0x0a, 0x74 },
+ { 0x0b, 0x11 },
+ { 0x10, 0x0c },
+ { 0x11, 0xe0 },
+ /* { 0x12, 0x40 }, -- 3400 needs 40, 2400 needs 48, no way to tell */
+ { 0x20, 0x63 },
+ { 0x21, 0x68 },
+ { 0x22, 0x19 },
+ { 0x23, 0x7f },
+ { 0x24, 0x68 },
+ { 0x26, 0x00 },
+ { 0x27, 0x0f },
+ { 0x30, 0x57 },
+ { 0x31, 0x58 },
+ { 0x32, 0x0d },
+ { 0x33, 0x72 },
+ { 0x34, 0x02 },
+ { 0x35, 0x22 },
+ { 0x36, 0x02 },
+ { 0x37, 0x00 }
+};
+
+static struct chips_init_reg chips_init_xr[] = {
+ { 0xce, 0x00 }, /* set default memory clock */
+ { 0xcc, 0x43 }, /* memory clock ratio */
+ { 0xcd, 0x18 },
+ { 0xce, 0xa1 },
+ { 0xc8, 0x84 },
+ { 0xc9, 0x0a },
+ { 0xca, 0x00 },
+ { 0xcb, 0x20 },
+ { 0xcf, 0x06 },
+ { 0xd0, 0x0e },
+ { 0x09, 0x01 },
+ { 0x0a, 0x02 },
+ { 0x0b, 0x01 },
+ { 0x20, 0x00 },
+ { 0x40, 0x03 },
+ { 0x41, 0x01 },
+ { 0x42, 0x00 },
+ { 0x80, 0x82 },
+ { 0x81, 0x12 },
+ { 0x82, 0x08 },
+ { 0xa0, 0x00 },
+ { 0xa8, 0x00 }
+};
+
+__initfunc(static void chips_hw_init(struct fb_info_chips *p))
+{
+ int i;
+
+ for (i = 0; i < N_ELTS(chips_init_xr); ++i)
+ write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
+ out_8(p->io_base + 0x3c2, 0x29); /* set misc output reg */
+ for (i = 0; i < N_ELTS(chips_init_sr); ++i)
+ write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
+ for (i = 0; i < N_ELTS(chips_init_gr); ++i)
+ write_gr(chips_init_gr[i].addr, chips_init_gr[i].data);
+ for (i = 0; i < N_ELTS(chips_init_ar); ++i)
+ write_ar(chips_init_ar[i].addr, chips_init_ar[i].data);
+ for (i = 0; i < N_ELTS(chips_init_cr); ++i)
+ write_cr(chips_init_cr[i].addr, chips_init_cr[i].data);
+ for (i = 0; i < N_ELTS(chips_init_fr); ++i)
+ write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
+}
+
__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;
@@ -405,7 +554,6 @@ __initfunc(static void init_chips(struct fb_info_chips *p))
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;
@@ -419,7 +567,6 @@ __initfunc(static void init_chips(struct fb_info_chips *p))
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;
@@ -443,6 +590,7 @@ __initfunc(static void init_chips(struct fb_info_chips *p))
p->info.switch_con = &chipsfb_switch;
p->info.updatevar = &chipsfb_updatevar;
p->info.blank = &chipsfb_blank;
+ p->info.flags = FBINFO_FLAG_DEFAULT;
for (i = 0; i < 16; ++i) {
int j = color_table[i];
@@ -458,6 +606,8 @@ __initfunc(static void init_chips(struct fb_info_chips *p))
printk("fb%d: Chips 65550 frame buffer\n", GET_FB_IDX(p->info.node));
+ chips_hw_init(p);
+
#ifdef CONFIG_FB_COMPAT_XPMAC
if (!console_fb_info) {
display_info.height = p->var.yres;
@@ -507,6 +657,7 @@ __initfunc(void chips_of_init(struct device_node *dp))
p = kmalloc(sizeof(*p), GFP_ATOMIC);
if (p == 0)
return;
+ memset(p, 0, sizeof(*p));
addr = dp->addrs[0].address;
p->chips_base_phys = addr;
p->frame_buffer = __ioremap(addr+0x800000, 0x100000, _PAGE_NO_CACHE);
diff --git a/drivers/video/clgenfb.c b/drivers/video/clgenfb.c
index fc3f15efe..68078c091 100644
--- a/drivers/video/clgenfb.c
+++ b/drivers/video/clgenfb.c
@@ -16,14 +16,13 @@
#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 <video/fbcon.h>
+#include <video/fbcon-mfb.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
#include "clgenfb.h"
@@ -33,17 +32,6 @@
#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
@@ -101,8 +89,22 @@ struct clgenfb_info
int btype;
int smallboard;
unsigned char SFR; /* Shadow of special function register */
+
+ unsigned long fbmem_phys;
+ unsigned long fbregs_phys;
struct clgenfb_par currentmode;
+ union {
+#ifdef FBCON_HAS_CFB16
+ u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+ u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u32 cfb32[16];
+#endif
+ } fbcon_cmap;
};
static struct display disp;
@@ -201,8 +203,8 @@ 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);
+static void clgen_set_dispsw(const void *par, struct display *disp,
+ struct fb_info_gen *info);
/* function table of the above functions */
static struct fbgen_hwswitch clgen_hwswitch =
@@ -217,7 +219,7 @@ static struct fbgen_hwswitch clgen_hwswitch =
clgen_setcolreg,
clgen_pan_display,
clgen_blank,
- clgen_get_dispsw
+ clgen_set_dispsw
};
/* Text console acceleration */
@@ -334,7 +336,7 @@ static int clgen_encode_fix(struct fb_fix_screeninfo *fix, const void *par,
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, clgenfb_name);
- fix->smem_start = (char*)_info->fbmem;
+ fix->smem_start = (char*)_info->fbmem_phys;
/* monochrome: only 1 memory plane */
/* 8 bit and above: Use whole memory area */
@@ -347,7 +349,7 @@ static int clgen_encode_fix(struct fb_fix_screeninfo *fix, const void *par,
fix->ypanstep = 1;
fix->ywrapstep = 0;
fix->line_length = _par->line_length;
- fix->mmio_start = (char *)_info->regs;
+ fix->mmio_start = (char *)_info->fbregs_phys;
fix->mmio_len = 0x10000;
fix->accel = FB_ACCEL_NONE;
@@ -411,7 +413,7 @@ static int clgen_decode_var(const struct fb_var_screeninfo *var, void *par,
/* use highest possible virtual resolution */
if (_par->var.xres_virtual == -1 &&
- _par->var.xres_virtual == -1)
+ _par->var.yres_virtual == -1)
{
printk("clgen: using maximum available virtual resolution\n");
for (i=0; modes[i].xres != -1; i++)
@@ -457,23 +459,54 @@ static int clgen_decode_var(const struct fb_var_screeninfo *var, void *par,
case 8:
_par->line_length = _par->var.xres_virtual;
_par->visual = FB_VISUAL_PSEUDOCOLOR;
+ _par->var.red.offset = 0;
+ _par->var.red.length = 6;
+ _par->var.green.offset = 0;
+ _par->var.green.length = 6;
+ _par->var.blue.offset = 0;
+ _par->var.blue.length = 6;
break;
case 16:
_par->line_length = _par->var.xres_virtual * 2;
_par->visual = FB_VISUAL_DIRECTCOLOR;
+ _par->var.red.offset = 10;
+ _par->var.red.length = 5;
+ _par->var.green.offset = 5;
+ _par->var.green.length = 5;
+ _par->var.blue.offset = 0;
+ _par->var.blue.length = 5;
break;
case 24:
_par->line_length = _par->var.xres_virtual * 3;
_par->visual = FB_VISUAL_DIRECTCOLOR;
+ _par->var.red.offset = 16;
+ _par->var.red.length = 8;
+ _par->var.green.offset = 8;
+ _par->var.green.length = 8;
+ _par->var.blue.offset = 0;
+ _par->var.blue.length = 8;
break;
case 32:
_par->line_length = _par->var.xres_virtual * 4;
_par->visual = FB_VISUAL_DIRECTCOLOR;
+ _par->var.red.offset = 16;
+ _par->var.red.length = 8;
+ _par->var.green.offset = 8;
+ _par->var.green.length = 8;
+ _par->var.blue.offset = 0;
+ _par->var.blue.length = 8;
break;
}
+ _par->var.red.msb_right = 0;
+ _par->var.green.msb_right = 0;
+ _par->var.blue.msb_right = 0;
+ _par->var.transp.offset = 0;
+ _par->var.transp.length = 0;
+ _par->var.transp.msb_right = 0;
+
_par->type = FB_TYPE_PACKED_PIXELS;
/* convert from ps to kHz */
@@ -691,7 +724,7 @@ static void clgen_set_par(const void *par, struct fb_info_gen *info)
#if 0
/* restore first 2 color registers for mono mode */
WClut( 0, 0x00, 0x00, 0x00); /* background: black */
- WClut( 1, 0xff, 0xff, 0xff); /* foreground: white */
+ WClut( 1, 0x3f, 0x3f, 0x3f); /* foreground: white */
#endif
WGfx(GR5, 0); /* mode register */
@@ -955,16 +988,16 @@ static int clgen_getcolreg(unsigned regno, unsigned *red, unsigned *green,
{
unsigned char bred, bgreen, bblue;
- if (regno > 255 || regno < 0)
+ if (regno > 255)
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;
+ *red = (bred<<10) | (bred<<4) | (bred>>2);
+ *green = (bgreen<<10) | (bgreen<<4) | (bgreen>>2);
+ *blue = (bblue<<10) | (bblue<<4) | (bblue>>2);
*transp = 0;
return (0);
}
@@ -973,13 +1006,13 @@ static int clgen_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
- if (regno > 255 || regno < 0)
+ if (regno > 255)
return (1);
fb_info = (struct clgenfb_info *)info;
/* "transparent" stuff is completely ignored. */
- WClut(regno, (red & 0xff), (green & 0xff), (blue & 0xff));
+ WClut(regno, red>>10, green>>10, blue>>10);
return (0);
}
@@ -1240,28 +1273,28 @@ static void init_vgachip(void)
/* 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);
+ WClut( 1, 0x3f, 0x3f, 0x3f); /* foreground: white */
+ WClut( 2, 0x00, 0x20, 0x00);
+ WClut( 3, 0x00, 0x20, 0x20);
+ WClut( 4, 0x20, 0x00, 0x00);
+ WClut( 5, 0x20, 0x00, 0x20);
+ WClut( 6, 0x20, 0x10, 0x00);
+ WClut( 7, 0x20, 0x20, 0x20);
+ WClut( 8, 0x10, 0x10, 0x10);
+ WClut( 9, 0x10, 0x10, 0x30);
+ WClut(10, 0x10, 0x30, 0x10);
+ WClut(11, 0x10, 0x30, 0x30);
+ WClut(12, 0x30, 0x10, 0x10);
+ WClut(13, 0x30, 0x10, 0x30);
+ WClut(14, 0x30, 0x30, 0x10);
+ WClut(15, 0x30, 0x30, 0x30);
/* the rest a grey ramp */
{
int i;
for (i = 16; i < 256; i++)
- WClut(i, i, i, i);
+ WClut(i, i>>2, i>>2, i>>2);
}
@@ -1338,10 +1371,11 @@ static void switch_monitor(int on)
}
}
-static struct display_switch *clgen_get_dispsw(const void *par,
- struct fb_info_gen *info)
+static void clgen_set_dispsw(const void *par, struct display *disp,
+ struct fb_info_gen *info)
{
struct clgenfb_par *_par = (struct clgenfb_par*) par;
+ struct clgenfb_info *info2 = (struct clgenfb_info *)info;
printk("clgen_get_dispsw(): ");
switch (_par->var.bits_per_pixel)
@@ -1349,44 +1383,53 @@ static struct display_switch *clgen_get_dispsw(const void *par,
#ifdef FBCON_HAS_MFB
case 1:
printk("monochrome\n");
- return &fbcon_mfb;
+ disp->dispsw = &fbcon_mfb;
+ break;
#endif
#ifdef FBCON_HAS_CFB8
case 8:
printk("8 bit color depth\n");
- return &fbcon_clgen_8;
+ disp->dispsw = &fbcon_clgen_8;
+ break;
#endif
#ifdef FBCON_HAS_CFB16
case 16:
printk("16 bit color depth\n");
- return &fbcon_cfb16;
+ disp->dispsw = &fbcon_cfb16;
+ disp->dispsw_data = info2->fbcon_cmap.cfb16;
+ break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
printk("24 bit color depth\n");
- return &fbcon_cfb24;
+ disp->dispsw = &fbcon_cfb24;
+ disp->dispsw_data = info2->fbcon_cmap.cfb24;
+ break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
printk("32 bit color depth\n");
- return &fbcon_cfb32;
+ disp->dispsw = &fbcon_cfb32;
+ disp->dispsw_data = info2->fbcon_cmap.cfb32;
+ break;
#endif
default:
printk("unsupported color depth\n");
- return NULL;
+ disp->dispsw = &fbcon_dummy;
+ break;
}
}
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;
+ sx *= fontwidth(p);
+ sy *= fontheight(p);
+ dx *= fontwidth(p);
+ dy *= fontheight(p);
+ width *= fontwidth(p);
+ height *= fontheight(p);
fb_info = (struct clgenfb_info*)p->fb_info;
@@ -1404,10 +1447,10 @@ static void fbcon_clgen8_clear(struct vc_data *conp, struct display *p,
fb_info = (struct clgenfb_info*)p->fb_info;
- sx *= p->fontwidth;
- sy *= p->fontheight;
- width *= p->fontwidth;
- height *= p->fontheight;
+ sx *= fontwidth(p);
+ sy *= fontheight(p);
+ width *= fontwidth(p);
+ height *= fontheight(p);
col = attr_bgcol_ec(p, conp);
col &= 0xff;
@@ -1494,8 +1537,10 @@ __initfunc(void clgenfb_init(void))
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->fbregs_phys = board_addr + 0x600000;
- fb_info->fbmem = kernel_map(board_addr + 16777216, 16777216,
+ fb_info->fbmem_phys = board_addr + 16777216;
+ fb_info->fbmem = kernel_map(fb_info->fbmem_phys, 16777216,
KERNELMAP_NOCACHE_SER, NULL);
DEBUG printk(KERN_INFO "clgen: (RAM start set to: $%lx)\n", fb_info->fbmem);
}
@@ -1504,6 +1549,7 @@ __initfunc(void clgenfb_init(void))
cd2 = zorro_get_board(key2);
printk(" REG at $%lx\n", (unsigned long)cd2->cd_BoardAddr);
+ fb_info->fbmem_phys = board_addr;
if (board_addr > 0x01000000)
fb_info->fbmem = kernel_map(board_addr, board_size,
KERNELMAP_NOCACHE_SER, NULL);
@@ -1512,6 +1558,7 @@ __initfunc(void clgenfb_init(void))
/* set address for REG area of board */
fb_info->regs = (unsigned char *)ZTWO_VADDR(cd2->cd_BoardAddr);
+ fb_info->fbregs_phys = (unsigned long) 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);
@@ -1530,6 +1577,7 @@ __initfunc(void clgenfb_init(void))
fb_info->gen.info.switch_con = &fbgen_switch;
fb_info->gen.info.updatevar = &fbgen_update_var;
fb_info->gen.info.blank = &fbgen_blank;
+ fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT;
/* mark this board as "autoconfigured" */
zorro_config_board(key, 0);
@@ -1835,7 +1883,7 @@ void WSFR2(unsigned char val)
fb_info->regs[0x9000] = val;
}
-/*** WClut - set CLUT entry (range: 0..255 is automat. shifted to 0..63) ***/
+/*** WClut - set CLUT entry (range: 0..63) ***/
void WClut(unsigned char regnum, unsigned char red, unsigned char green, unsigned char blue)
{
unsigned int data = 0x3c9;
@@ -1848,19 +1896,19 @@ void WClut(unsigned char regnum, unsigned char red, unsigned char green, unsigne
/* 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);
+ fb_info->regs[data] = red;
+ fb_info->regs[data] = green;
+ fb_info->regs[data] = blue;
}
else
{
- fb_info->regs[data] = (blue >> 2);
- fb_info->regs[data] = (green >> 2);
- fb_info->regs[data] = (red >> 2);
+ fb_info->regs[data] = blue;
+ fb_info->regs[data] = green;
+ fb_info->regs[data] = red;
}
}
-/*** RClut - read CLUT entry and convert to 0..255 range ***/
+/*** RClut - read CLUT entry (range 0..63) ***/
void RClut(unsigned char regnum, unsigned char *red, unsigned char *green, unsigned char *blue)
{
unsigned int data = 0x3c9;
@@ -1871,15 +1919,15 @@ void RClut(unsigned char regnum, unsigned char *red, unsigned char *green, unsig
{
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;
+ *red = fb_info->regs[data];
+ *green = fb_info->regs[data];
+ *blue = fb_info->regs[data];
}
else
{
- *blue = fb_info->regs[data] << 2;
- *green = fb_info->regs[data] << 2;
- *red = fb_info->regs[data] << 2;
+ *blue = fb_info->regs[data];
+ *green = fb_info->regs[data];
+ *red = fb_info->regs[data];
}
}
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 466bf52ee..d1a63b64f 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -49,16 +49,19 @@
#include <asm/adb.h>
#include <asm/cuda.h>
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-#include "fbcon-cfb32.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb32.h>
+#include <video/macmodes.h>
-#include "macmodes.h"
#include "controlfb.h"
static int currcon = 0;
static int switching = 0;
+static char fontname[40] __initdata = { 0 };
+static int default_vmode = VMODE_NVRAM;
+static int default_cmode = CMODE_NVRAM;
struct fb_par_control {
int vmode, cmode;
@@ -88,13 +91,24 @@ struct fb_info_control {
int sense, control_use_bank2;
unsigned long total_vram;
+ union {
+#ifdef FBCON_HAS_CFB16
+ u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u32 cfb32[16];
+#endif
+ } fbcon_cmap;
};
/*
* Exported functions
*/
void control_init(void);
+#ifdef CONFIG_FB_OF
void control_of_init(struct device_node *dp);
+#endif
+void controlfb_setup(char *options, int *ints);
static int control_open(struct fb_info *info, int user);
static int control_release(struct fb_info *info, int user);
@@ -198,7 +212,7 @@ static int control_set_var(struct fb_var_screeninfo *var, int con,
}
if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) {
- printk("Not activating, in control_set_var.\n");
+ /* printk("Not activating, in control_set_var.\n"); */
control_par_to_var(&par, var);
return 0;
}
@@ -211,7 +225,7 @@ static int control_set_var(struct fb_var_screeninfo *var, int con,
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);
+ /* 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);
@@ -244,8 +258,7 @@ 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);
+ return fb_get_cmap(cmap, 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 {
@@ -269,8 +282,7 @@ static int control_set_cmap(struct fb_cmap *cmap, int kspc, int con,
}
if (con == currcon)
- return fb_set_cmap(cmap, &disp->var, kspc, controlfb_setcolreg,
- info);
+ return fb_set_cmap(cmap, kspc, controlfb_setcolreg, info);
fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
return 0;
}
@@ -284,8 +296,7 @@ static int control_ioctl(struct inode *inode, struct file *file, u_int cmd,
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,
+ fb_get_cmap(&fb_display[currcon].cmap, 1, controlfb_getcolreg,
info);
currcon = con;
#if 0
@@ -346,9 +357,10 @@ static int controlfb_getcolreg(u_int regno, u_int *red, u_int *green,
if (regno > 255)
return 1;
- *red = p->palette[regno].red;
- *green = p->palette[regno].green;
- *blue = p->palette[regno].blue;
+ *red = (p->palette[regno].red<<8) | p->palette[regno].red;
+ *green = (p->palette[regno].green<<8) | p->palette[regno].green;
+ *blue = (p->palette[regno].blue<<8) | p->palette[regno].blue;
+ *transp = 0;
return 0;
}
@@ -356,9 +368,13 @@ 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;
+ int i;
- if (regno > 255 || regno < 0)
+ if (regno > 255)
return 1;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
p->palette[regno].red = red;
p->palette[regno].green = green;
p->palette[regno].blue = blue;
@@ -368,25 +384,29 @@ static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
out_8(&p->cmap_regs->lut, green); /* a time... */
out_8(&p->cmap_regs->lut, blue);
- if(regno < 16) {
-#if 0
+ if (regno < 16)
+ switch (p->var.bits_per_pixel) {
#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
+ case 16:
+#if 0
+ p->fbcon_cmap.cfb16[regno] = (red << 10) | (green << 5) | blue;
#else
-#ifdef FBCON_HAS_CFB16
- fbcon_cfb16_cmap[regno] = (regno << 10) | (regno << 5) | regno;
+ p->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | regno;
+#endif
+ break;
#endif
#ifdef FBCON_HAS_CFB32
- fbcon_cfb32_cmap[regno] = (regno << 24) | (regno << 16) | (regno << 8) | regno;
- /* I think. */
+ case 32:
+#if 0
+ p->fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | blue;
+#else
+ i = (regno << 8) | regno;
+ p->fbcon_cmap.cfb32[regno] = (i << 16) | i;
+ /* I think */
#endif
+ break;
#endif
- }
+ }
return 0;
}
@@ -395,12 +415,12 @@ 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);
+ fb_set_cmap(&fb_display[con].cmap, 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);
+ fb_set_cmap(fb_default_cmap(size), 1, controlfb_setcolreg,
+ info);
}
}
@@ -440,7 +460,7 @@ __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);
+ printk(KERN_INFO "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])
@@ -467,13 +487,14 @@ __initfunc(static void init_control(struct fb_info_control *p))
control_par_to_all(p, 1);
+ p->info.flags = FBINFO_FLAG_DEFAULT;
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));
+ printk(KERN_INFO "fb%d: control display adapter\n", GET_FB_IDX(p->info.node));
}
/* Now how about actually saying, Make it so! */
@@ -523,8 +544,9 @@ static void control_set_hardware(struct fb_info_control *p)
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);
+ controlfb_setcolreg(color_table[i], default_red[i]<<8,
+ default_grn[i]<<8, default_blu[i]<<8,
+ 0, (struct fb_info *)p);
}
/* Does the above need to be here each time? -- danj */
@@ -568,16 +590,24 @@ __initfunc(void control_of_init(struct device_node *dp))
struct fb_info_control *p;
unsigned long addr, size;
int i, bank1, bank2;
-
+
+#if 0
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);
+ * had two of them, they'd be two framebuffers, right?
+ * Yep. - paulus
+ */
+#endif
+
+ if(dp->n_addrs != 2) {
+ printk(KERN_ERR "expecting 2 address for control (got %d)", dp->n_addrs);
+ return;
+ }
p = kmalloc(sizeof(*p), GFP_ATOMIC);
if (p == 0)
return;
+ memset(p, 0, sizeof(*p));
/* Map in frame buffer and registers */
for (i = 0; i < dp->n_addrs; ++i) {
@@ -657,7 +687,7 @@ static int read_control_sense(struct fb_info_control *p)
#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,
+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;
@@ -758,7 +788,7 @@ static int control_var_to_par(struct fb_var_screeninfo *var,
}
#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,
+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;
@@ -901,7 +931,7 @@ static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeni
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;
+ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
p->fix.line_length = par->vxres << par->cmode;
/* ywrapstep, xpanstep, ypanstep */
}
@@ -935,8 +965,28 @@ 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);
+ 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;
+ disp->dispsw_data = p->fbcon_cmap.cfb16;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case CMODE_32:
+ disp->dispsw = &fbcon_cfb32;
+ disp->dispsw_data = p->fbcon_cmap.cfb32;
+ break;
+#endif
+ default:
+ disp->dispsw = &fbcon_dummy;
+ break;
+ }
}
static void control_init_info(struct fb_info *info, struct fb_info_control *p)
@@ -945,7 +995,7 @@ static void control_init_info(struct fb_info *info, struct fb_info_control *p)
info->node = -1; /* ??? danj */
info->fbops = &controlfb_ops;
info->disp = &p->disp;
- info->fontname[0] = 0;
+ strcpy(info->fontname, fontname);
info->changevar = NULL;
info->switch_con = &controlfb_switch;
info->updatevar = &controlfb_updatevar;
@@ -972,13 +1022,51 @@ static void control_par_to_all(struct fb_info_control *p, int init)
}
}
-#if 0
+/* Parse user speficied options (`video=controlfb:') */
__initfunc(void controlfb_setup(char *options, int *ints))
{
- /* Parse user speficied options (`video=controlfb:') */
- FUNCID;
+ char *this_opt;
+
+ 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 (!strncmp(this_opt, "vmode:", 6)) {
+ int vmode = simple_strtoul(this_opt+6, NULL, 0);
+ if (vmode > 0 && vmode <= VMODE_MAX)
+ default_vmode = vmode;
+ } else if (!strncmp(this_opt, "cmode:", 6)) {
+ int depth = simple_strtoul(this_opt+6, NULL, 0);
+ switch (depth) {
+ case 8:
+ default_cmode = CMODE_8;
+ break;
+ case 15:
+ case 16:
+ default_cmode = CMODE_16;
+ break;
+ case 24:
+ case 32:
+ default_cmode = CMODE_32;
+ break;
+ }
+ }
+ }
}
+#if 0
static int controlfb_pan_display(struct fb_var_screeninfo *var,
struct controlfb_par *par,
const struct fb_info *fb_info)
@@ -993,5 +1081,4 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var,
return 0;
}
-
#endif
diff --git a/drivers/video/controlfb.h b/drivers/video/controlfb.h
index 2e138b7c7..32943ed27 100644
--- a/drivers/video/controlfb.h
+++ b/drivers/video/controlfb.h
@@ -141,8 +141,8 @@ static struct control_regvals control_reg_init_17 = {
1024, 768
};
-/* Register values for 1024x768, 72Hz mode (15) */
-static struct control_regvals control_reg_init_15 = {
+/* Register values for 1024x768, 72Hz mode (16 (15?)) */
+static struct control_regvals control_reg_init_16 = {
{ 1024, 2048, 4096 },
{ 0x10, 0x28, 0x50 },
{ 1607, 1604, 68, 39, 10, 1610, 1612, 132,
@@ -253,8 +253,8 @@ static struct control_regvals *control_reg_init[VMODE_MAX] = {
&control_reg_init_12,
&control_reg_init_13,
&control_reg_init_14,
- &control_reg_init_15,
- NULL,
+ &control_reg_init_16,
+ &control_reg_init_16,
&control_reg_init_17,
&control_reg_init_18,
&control_reg_init_19,
diff --git a/drivers/video/creatorfb.c b/drivers/video/creatorfb.c
index 2175c9e5d..6c8f14b1d 100644
--- a/drivers/video/creatorfb.c
+++ b/drivers/video/creatorfb.c
@@ -1,10 +1,9 @@
-/* $Id: creatorfb.c,v 1.10 1998/07/25 22:54:37 davem Exp $
+/* $Id: creatorfb.c,v 1.15 1998/09/04 15:43:40 jj 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>
@@ -20,7 +19,7 @@
#include <linux/init.h>
#include <linux/selection.h>
-#include "sbusfb.h"
+#include <video/sbusfb.h>
#define FFB_SFB8R_VOFF 0x00000000
#define FFB_SFB8G_VOFF 0x00400000
@@ -69,56 +68,141 @@
#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
+/* Draw operations */
+#define FFB_DRAWOP_DOT 0x00
+#define FFB_DRAWOP_AADOT 0x01
+#define FFB_DRAWOP_BRLINECAP 0x02
+#define FFB_DRAWOP_BRLINEOPEN 0x03
+#define FFB_DRAWOP_DDLINE 0x04
+#define FFB_DRAWOP_AALINE 0x05
+#define FFB_DRAWOP_TRIANGLE 0x06
+#define FFB_DRAWOP_POLYGON 0x07
+#define FFB_DRAWOP_RECTANGLE 0x08
+#define FFB_DRAWOP_FASTFILL 0x09
+#define FFB_DRAWOP_BCOPY 0x0a
+#define FFB_DRAWOP_VSCROLL 0x0b
+
+/* Pixel processor control */
+/* Force WID */
+#define FFB_PPC_FW_DISABLE 0x800000
+#define FFB_PPC_FW_ENABLE 0xc00000
+/* Auxiliary clip */
+#define FFB_PPC_ACE_DISABLE 0x040000
+#define FFB_PPC_ACE_AUX_SUB 0x080000
+#define FFB_PPC_ACE_AUX_ADD 0x0c0000
+/* Depth cue */
+#define FFB_PPC_DCE_DISABLE 0x020000
+#define FFB_PPC_DCE_ENABLE 0x030000
+/* Alpha blend */
+#define FFB_PPC_ABE_DISABLE 0x008000
+#define FFB_PPC_ABE_ENABLE 0x00c000
+/* View clip */
+#define FFB_PPC_VCE_DISABLE 0x001000
+#define FFB_PPC_VCE_2D 0x002000
+#define FFB_PPC_VCE_3D 0x003000
+/* Area pattern */
+#define FFB_PPC_APE_DISABLE 0x000800
+#define FFB_PPC_APE_ENABLE 0x000c00
+/* Transparent background */
+#define FFB_PPC_TBE_OPAQUE 0x000200
+#define FFB_PPC_TBE_TRANSPARENT 0x000300
+/* Z source */
+#define FFB_PPC_ZS_VAR 0x000080
+#define FFB_PPC_ZS_CONST 0x0000c0
+/* Y source */
+#define FFB_PPC_YS_VAR 0x000020
+#define FFB_PPC_YS_CONST 0x000030
+/* X source */
+#define FFB_PPC_XS_WID 0x000004
+#define FFB_PPC_XS_VAR 0x000008
+#define FFB_PPC_XS_CONST 0x00000c
+/* Color (BGR) source */
+#define FFB_PPC_CS_VAR 0x000002
+#define FFB_PPC_CS_CONST 0x000003
#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];
+ /* Next vertex registers */
+ u32 xxx1[3];
+ volatile u32 alpha;
+ volatile u32 red;
+ volatile u32 green;
+ volatile u32 blue;
+ volatile u32 depth;
+ volatile u32 y;
+ volatile u32 x;
+ u32 xxx2[2];
+ volatile u32 ryf;
+ volatile u32 rxf;
+ u32 xxx3[2];
+
+ volatile u32 dmyf;
+ volatile u32 dmxf;
+ u32 xxx4[2];
+ volatile u32 ebyi;
+ volatile u32 ebxi;
+ u32 xxx5[2];
volatile u32 by;
volatile u32 bx;
- u32 xxx2;
- u32 xxx3;
+ u32 dy;
+ u32 dx;
volatile u32 bh;
volatile u32 bw;
- u8 xxx4[0x188];
+ u32 xxx6[2];
+
+ u32 xxx7[32];
+
+ /* Setup unit vertex state register */
+ volatile u32 suvtx;
+ u32 xxx8[63];
+
+ /* Control registers */
volatile u32 ppc;
- u32 xxx5;
+ volatile u32 wid;
volatile u32 fg;
volatile u32 bg;
- u8 xxx6[0x44];
+ volatile u32 consty;
+ volatile u32 constz;
+ volatile u32 xclip;
+ volatile u32 dcss;
+ volatile u32 vclipmin;
+ volatile u32 vclipmax;
+ volatile u32 vclipzmin;
+ volatile u32 vclipzmax;
+ volatile u32 dcsf;
+ volatile u32 dcsb;
+ volatile u32 dczf;
+ volatile u32 dczb;
+
+ u32 xxx9;
+ volatile u32 blendc;
+ volatile u32 blendc1;
+ volatile u32 blendc2;
+ volatile u32 fbramitc;
volatile u32 fbc;
volatile u32 rop;
- u8 xxx7[0x34];
+ volatile u32 cmp;
+ volatile u32 matchab;
+ volatile u32 matchc;
+ volatile u32 magnab;
+ volatile u32 magnc;
+ volatile u32 fbcfg0;
+ volatile u32 fbcfg1;
+ volatile u32 fbcfg2;
+ volatile u32 fbcfg3;
+
+ u32 ppcfg;
+ volatile u32 pick;
+ volatile u32 fillmode;
+ volatile u32 fbramwac;
volatile u32 pmask;
- u8 xxx8[12];
+ volatile u32 xpmask;
+ volatile u32 ypmask;
+ volatile u32 zpmask;
volatile u32 clip0min;
volatile u32 clip0max;
volatile u32 clip1min;
@@ -127,18 +211,64 @@ struct ffb_fbc {
volatile u32 clip2max;
volatile u32 clip3min;
volatile u32 clip3max;
- u8 xxx9[0x3c];
- volatile u32 unk1;
- volatile u32 unk2;
- u8 xxx10[0x10];
+
+ /* New 3dRAM III support regs */
+ volatile u32 rawblend2;
+ volatile u32 rawpreblend;
+ volatile u32 rawstencil;
+ volatile u32 rawstencilctl;
+ volatile u32 threedram1;
+ volatile u32 threedram2;
+ volatile u32 passin;
+ volatile u32 rawclrdepth;
+ volatile u32 rawpmask;
+ volatile u32 rawcsrc;
+ volatile u32 rawmatch;
+ volatile u32 rawmagn;
+ volatile u32 rawropblend;
+ volatile u32 rawcmp;
+ volatile u32 rawwac;
+ volatile u32 fbramid;
+
+ volatile u32 drawop;
+ u32 xxx10[2];
+ volatile u32 fontlpat;
+ u32 xxx11;
volatile u32 fontxy;
volatile u32 fontw;
volatile u32 fontinc;
volatile u32 font;
- u8 xxx11[0x4dc];
- volatile u32 unk3;
- u8 xxx12[0xfc];
+ u32 xxx12[3];
+ volatile u32 blend2;
+ volatile u32 preblend;
+ volatile u32 stencil;
+ volatile u32 stencilctl;
+
+ u32 xxx13[4];
+ volatile u32 dcss1;
+ volatile u32 dcss2;
+ volatile u32 dcss3;
+ volatile u32 widpmask;
+ volatile u32 dcs2;
+ volatile u32 dcs3;
+ volatile u32 dcs4;
+ u32 xxx14;
+ volatile u32 dcd2;
+ volatile u32 dcd3;
+ volatile u32 dcd4;
+ u32 xxx15;
+
+ volatile u32 pattern[32];
+
+ u32 xxx16[256];
+
+ volatile u32 devid;
+ u32 xxx17[63];
+
volatile u32 ucsr;
+ u32 xxx18[31];
+
+ volatile u32 mer;
};
struct ffb_dac {
@@ -170,8 +300,6 @@ static struct sbus_mmap_map ffb_mmap_map[] = {
{ 0, 0, 0 }
};
-static u32 ffb_cmap[16];
-
static void ffb_setup(struct display *p)
{
p->next_line = 8192;
@@ -185,22 +313,18 @@ static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
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;
+ fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
+ fbc->drawop = FFB_DRAWOP_RECTANGLE;
- if (p->fontheightlog) {
- y = sy << p->fontheightlog; h = height << p->fontheightlog;
+ if (fontheightlog(p)) {
+ y = sy << fontheightlog(p); h = height << fontheightlog(p);
} else {
- y = sy * p->fontheight; h = height * p->fontheight;
+ y = sy * fontheight(p); h = height * fontheight(p);
}
- if (p->fontwidthlog) {
- x = sx << p->fontwidthlog; w = width << p->fontwidthlog;
+ if (fontwidthlog(p)) {
+ x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
} else {
- x = sx * p->fontwidth; w = width * p->fontwidth;
+ x = sx * fontwidth(p); w = width * fontwidth(p);
}
fbc->by = y + fb->y_margin;
fbc->bx = x + fb->x_margin;
@@ -213,12 +337,8 @@ static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
{
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;
+ fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
+ fbc->drawop = FFB_DRAWOP_RECTANGLE;
while (count-- > 0) {
fbc->by = boxes[1];
fbc->bx = boxes[0];
@@ -235,48 +355,35 @@ static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int
int i, xy;
u8 *fd;
- if (p->fontheightlog) {
- xy = (yy << (16 + p->fontheightlog));
- i = ((c & p->charmask) << p->fontheightlog);
+ if (fontheightlog(p)) {
+ xy = (yy << (16 + fontheightlog(p)));
+ i = ((c & p->charmask) << fontheightlog(p));
} else {
- xy = ((yy * p->fontheight) << 16);
- i = (c & p->charmask) * p->fontheight;
+ xy = ((yy * fontheight(p)) << 16);
+ i = (c & p->charmask) * fontheight(p);
}
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
- fd = p->fontdata + i;
- xy += (xx * 8) + fb->s.ffb.xy_margin;
-#else
- if (p->fontwidth <= 8)
+ if (fontwidth(p) <= 8)
fd = p->fontdata + i;
else
fd = p->fontdata + (i << 1);
- if (p->fontwidthlog)
- xy += (xx << p->fontwidthlog) + fb->s.ffb.xy_margin;
+ if (fontwidthlog(p))
+ xy += (xx << fontwidthlog(p)) + 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;
+ xy += (xx * fontwidth(p)) + fb->s.ffb.xy_margin;
+ fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
+ fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
+ fbc->fontw = fontwidth(p);
fbc->fontinc = 0x10000;
fbc->fontxy = xy;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
- if (p->fontwidth <= 8) {
-#endif
- for (i = 0; i < p->fontheight; i++)
+ if (fontwidth(p) <= 8) {
+ for (i = 0; i < fontheight(p); i++)
fbc->font = *fd++ << 24;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
} else {
- for (i = 0; i < p->fontheight; i++) {
+ for (i = 0; i < fontheight(p); i++) {
fbc->font = *(u16 *)fd << 16;
fd += 2;
}
}
-#endif
}
static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
@@ -287,105 +394,87 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
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)];
+ fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,*s)];
+ fbc->bg = ((u32 *)p->dispsw_data)[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);
+ if (fontwidthlog(p))
+ xy += (xx << fontwidthlog(p));
else
- xy += xx * p->fontwidth;
-#endif
- if (p->fontheightlog)
- xy += (yy << (16 + p->fontheightlog));
+ xy += xx * fontwidth(p);
+ if (fontheightlog(p))
+ xy += (yy << (16 + fontheightlog(p)));
else
- xy += ((yy * p->fontheight) << 16);
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
- if (p->fontwidth <= 8) {
-#endif
+ xy += ((yy * fontheight(p)) << 16);
+ if (fontwidth(p) <= 8) {
while (count >= 4) {
count -= 4;
- fbc->fontw = 4 * p->fontwidth;
+ fbc->fontw = 4 * fontwidth(p);
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);
+ if (fontheightlog(p)) {
+ fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+ fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+ fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+ fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
} 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);
+ fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+ fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+ fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+ fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
}
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
- if (p->fontwidth == 8) {
-#endif
- for (i = 0; i < p->fontheight; i++)
+ if (fontwidth(p) == 8) {
+ for (i = 0; i < fontheight(p); 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++)
+ for (i = 0; i < fontheight(p); 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;
+ << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
+ xy += 4 * fontwidth(p);
}
}
} else {
while (count >= 2) {
count -= 2;
- fbc->fontw = 2 * p->fontwidth;
+ fbc->fontw = 2 * fontwidth(p);
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));
+ if (fontheightlog(p)) {
+ fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
+ fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
} else {
- fd1 = p->fontdata + (((*s++ & p->charmask) * p->fontheight) << 1);
- fd2 = p->fontdata + (((*s++ & p->charmask) * p->fontheight) << 1);
+ fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
+ fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
}
- for (i = 0; i < p->fontheight; i++) {
- fbc->font = ((((u32)*(u16 *)fd1) << p->fontwidth) | ((u32)*(u16 *)fd2)) << (16 - p->fontwidth);
+ for (i = 0; i < fontheight(p); i++) {
+ fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
fd1 += 2; fd2 += 2;
}
- xy += 2 * p->fontwidth;
+ xy += 2 * fontwidth(p);
}
-#endif
}
while (count) {
count--;
- fbc->fontw = p->fontwidth;
+ fbc->fontw = fontwidth(p);
fbc->fontinc = 0x10000;
fbc->fontxy = xy;
- if (p->fontheightlog)
- i = ((*s++ & p->charmask) << p->fontheightlog);
+ if (fontheightlog(p))
+ i = ((*s++ & p->charmask) << fontheightlog(p));
else
- i = ((*s++ & p->charmask) * p->fontheight);
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
- if (p->fontwidth <= 8) {
-#endif
+ i = ((*s++ & p->charmask) * fontheight(p));
+ if (fontwidth(p) <= 8) {
fd1 = p->fontdata + i;
- for (i = 0; i < p->fontheight; i++)
+ for (i = 0; i < fontheight(p); i++)
fbc->font = *fd1++ << 24;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
} else {
fd1 = p->fontdata + (i << 1);
- for (i = 0; i < p->fontheight; i++) {
+ for (i = 0; i < fontheight(p); i++) {
fbc->font = *(u16 *)fd1 << 16;
fd1 += 2;
}
}
-#endif
- xy += p->fontwidth;
+ xy += fontwidth(p);
}
}
@@ -394,7 +483,7 @@ 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)
+static void ffb_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
{
struct ffb_dac *dac = fb->s.ffb.dac;
int i, j = count;
@@ -405,10 +494,12 @@ static void ffb_loadcmap (struct fb_info_sbusfb *fb, int index, int count)
dac->value = ((fb->color_map CM(i,0))) |
((fb->color_map CM(i,1)) << 8) |
((fb->color_map CM(i,2)) << 16);
+ if (!p)
+ return;
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);
+ ((u32 *)p->dispsw_data)[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 = {
@@ -478,6 +569,16 @@ static void ffb_setcursor (struct fb_info_sbusfb *fb)
ffb_curs_enable (fb, fb->cursor.enable);
}
+static void ffb_switch_from_graph (struct fb_info_sbusfb *fb)
+{
+ register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+
+ fbc->ppc = FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST;
+ fbc->fbc = 0x2000707f;
+ fbc->rop = FFB_ROP_NEW;
+ fbc->pmask = 0xffffffff;
+}
+
static char idstring[60] __initdata = { 0 };
__initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
@@ -492,10 +593,15 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
if (prom_getproperty(fb->prom_node, "reg", (void *) regs, sizeof(regs)) <= 0)
return NULL;
+ disp->dispsw_data = (void *)kmalloc(16 * sizeof(u32), GFP_KERNEL);
+ if (!disp->dispsw_data)
+ return NULL;
+ memset(disp->dispsw_data, 0, 16 * sizeof(u32));
+
strcpy(fb->info.modename, "Creator");
strcpy(fix->id, "Creator");
- fix->visual = FB_VISUAL_DIRECTCOLOR;
+ fix->visual = FB_VISUAL_TRUECOLOR;
fix->line_length = 8192;
fix->accel = FB_ACCEL_SUN_CREATOR;
@@ -516,8 +622,11 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
fb->setcursor = ffb_setcursor;
fb->setcursormap = ffb_setcursormap;
fb->setcurshape = ffb_setcurshape;
+ fb->switch_from_graph = ffb_switch_from_graph;
fb->fill = ffb_fill;
+ ffb_switch_from_graph(fb);
+
fb->physbase = regs[0].phys_addr;
fb->mmap_map = ffb_mmap_map;
diff --git a/drivers/video/cvppcfb.c b/drivers/video/cvppcfb.c
new file mode 100644
index 000000000..3e786ab61
--- /dev/null
+++ b/drivers/video/cvppcfb.c
@@ -0,0 +1,606 @@
+/*
+ * CybervisionPPC (TVP4020) low level driver for the frame buffer device
+ * ^^^^^^^^^
+ * literally ;)
+ *
+ * Copyright (c) 1998 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) (v124)
+ * --------------------------------------------------------------------------
+ * based on linux/drivers/video/skeletonfb.c by Geert Uytterhoeven
+ * --------------------------------------------------------------------------
+ * TODO h/w parameters detect/modify, 8-bit CLUT, acceleration
+ * --------------------------------------------------------------------------
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file README.legal in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/amigahw.h>
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb32.h>
+#include <asm/setup.h>
+#include <asm/io.h>
+
+#define ISDIGIT(a) ((a)>='0' && (a)<='9')
+
+#undef CVPPCFB_MASTER_DEBUG
+#ifdef CVPPCFB_MASTER_DEBUG
+#define FBEGIN if (usr_startup.debug>1)\
+ printk(__FUNCTION__ " {\n")
+#define FEND if (usr_startup.debug>1)\
+ printk("} /* " __FUNCTION__ " */\n")
+#define DPRINTK(a,b...) if (usr_startup.debug)\
+ printk("%s: " a, __FUNCTION__ , ## b)
+#else
+#define FBEGIN
+#define FEND
+#define DPRINTK(a,b...)
+#endif
+
+static const char cvppcfb_name[16]="CybervisionPPC";
+
+struct cvppcfb_startup { /* startup options */
+ char font[40];
+ u32 xres;
+ u32 yres;
+ u32 bpp;
+ unsigned long debug;
+ unsigned long YANW; /* You Are Not Welcome */
+ struct fb_monspecs monitor;
+};
+static struct cvppcfb_startup usr_startup = {
+ "\0", 640, 480, 16, 0, 1, { 31, 32, 58, 62, 0 } };
+
+#define CVPPC_BASE 0xe0000000
+#define CVPPC_SIZE 0x00800000
+static char* video_base; /* virtual address of board video memory */
+static unsigned long video_phys;/* physical address of board video memory */
+static u32 video_size; /* size of board video memory */
+
+struct cvppcfb_par { /* board parameters (sort of) */
+ u32 xres;
+ u32 yres;
+ u32 vxres;
+ u32 vyres;
+ u32 vxoff;
+ u32 vyoff;
+ u32 bpp;
+ u32 clock;
+ u32 sflags;
+ u32 left;
+ u32 right;
+ u32 top;
+ u32 bottom;
+ u32 hsynclen;
+ u32 vsynclen;
+};
+
+struct cvppcfb_info {
+ struct fb_info_gen gen;
+ struct cvppcfb_par current_par;
+ int current_par_valid;
+ struct display disp;
+ struct {
+ u8 transp;
+ u8 red;
+ u8 green;
+ u8 blue;
+ } palette[256];
+ union {
+#ifdef FBCON_HAS_CFB16
+ u16 cmap16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u32 cmap32[16];
+#endif
+ } cmap;
+};
+static struct cvppcfb_info fb_info;
+
+/*
+ * declaration of hw switch functions
+ */
+static void cvppcfb_detect(void);
+static int cvppcfb_encode_fix(struct fb_fix_screeninfo* fix,
+ const void* par, struct fb_info_gen* info);
+static int cvppcfb_decode_var(const struct fb_var_screeninfo* var,
+ void* par, struct fb_info_gen* info);
+static int cvppcfb_encode_var(struct fb_var_screeninfo* var,
+ const void* par, struct fb_info_gen* info);
+static void cvppcfb_get_par(void* par, struct fb_info_gen* info);
+static void cvppcfb_set_par(const void* par, struct fb_info_gen* info);
+static int cvppcfb_getcolreg(unsigned regno,
+ unsigned* red, unsigned* green, unsigned* blue,
+ unsigned* transp, struct fb_info* info);
+static int cvppcfb_setcolreg(unsigned regno,
+ unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info* info);
+static void cvppcfb_dispsw(const void* par, struct display* disp,
+ struct fb_info_gen* info);
+
+static struct fbgen_hwswitch cvppcfb_hwswitch={
+ cvppcfb_detect, cvppcfb_encode_fix, cvppcfb_decode_var,
+ cvppcfb_encode_var, cvppcfb_get_par, cvppcfb_set_par,
+ cvppcfb_getcolreg, cvppcfb_setcolreg, NULL /* pan_display() */,
+ NULL /* blank() */, cvppcfb_dispsw
+};
+
+/*
+ * declaration of ops switch functions
+ */
+static int cvppcfb_open(struct fb_info* info, int user);
+static int cvppcfb_release(struct fb_info* info, int user);
+
+static struct fb_ops cvppcfb_ops={
+ cvppcfb_open, cvppcfb_release, fbgen_get_fix, fbgen_get_var,
+ fbgen_set_var, fbgen_get_cmap, fbgen_set_cmap, fbgen_pan_display,
+ fbgen_ioctl, NULL /* fb_mmap() */
+};
+
+/*
+ * the actual definition of the above mentioned functions follows
+ */
+
+/*
+ * private functions
+ */
+
+static void cvppcfb_set_modename(struct cvppcfb_info* info,
+ struct cvppcfb_startup* s) {
+
+ strcpy(info->gen.info.modename, cvppcfb_name);
+}
+
+static void cvppcfb_decode_opt(struct cvppcfb_startup* s, void* par,
+ struct cvppcfb_info* info) {
+ struct cvppcfb_par* p=(struct cvppcfb_par* )par;
+
+ memset(p, 0, sizeof(struct cvppcfb_par));
+ p->xres=p->vxres=(s->xres+7)&~7;
+ p->yres=p->vyres=s->yres;
+ p->bpp=(s->bpp+7)&~7;
+ if (p->bpp==24)
+ p->bpp=32;
+ if (p->bpp<32)
+ p->clock=6666;
+ else
+ p->clock=10000;
+}
+
+static void cvppcfb_encode_mcap(char* options, struct fb_monspecs* mcap) {
+ char* next;
+ int i=0;
+
+ while (i<4 && options) {
+ if ((next=strchr(options, ';')))
+ *(next++)='\0';
+ switch (i++) {
+ case 0: /* vmin */
+ mcap->vfmin=(__u16 )
+ simple_strtoul(options, NULL, 0);
+ break;
+ case 1: /* vmax */
+ mcap->vfmax=(__u16 )
+ simple_strtoul(options, NULL, 0);
+ break;
+ case 2: /* hmin */
+ mcap->hfmin=(__u32 )
+ simple_strtoul(options, NULL, 0);
+ break;
+ case 3: /* hmax */
+ mcap->hfmax=(__u32 )
+ simple_strtoul(options, NULL, 0);
+ break;
+ }
+ options=next;
+ }
+}
+
+static void cvppcfb_encode_mode(char* options, struct cvppcfb_startup* s) {
+ char* next;
+ int i=0;
+
+ while (i<3 && options) {
+ if ((next=strchr(options, ';')))
+ *(next++)='\0';
+ switch (i++) {
+ case 0:
+ s->xres=(u32 )
+ simple_strtoul(options, NULL, 0);
+ break;
+ case 1:
+ s->yres=(u32 )
+ simple_strtoul(options, NULL, 0);
+ break;
+ case 2:
+ s->bpp=(u32 )
+ simple_strtoul(options, NULL, 0);
+ break;
+ }
+ options=next;
+ }
+}
+
+/*
+ * protected functions
+ */
+
+static void cvppcfb_detect(void) {
+
+ FBEGIN;
+ FEND;
+}
+
+static int cvppcfb_encode_fix(struct fb_fix_screeninfo* fix,
+ const void* par, struct fb_info_gen* info) {
+
+ FBEGIN;
+ strcpy(fix->id, cvppcfb_name);
+ fix->smem_start=(char* )video_phys;
+ fix->smem_len=(__u32 )video_size;
+ fix->type=FB_TYPE_PACKED_PIXELS;
+ if (((struct cvppcfb_par* )par)->bpp==8)
+ fix->visual=FB_VISUAL_PSEUDOCOLOR;
+ else
+ fix->visual=FB_VISUAL_TRUECOLOR;
+ fix->xpanstep=fix->ypanstep=fix->ywrapstep=0;
+ fix->line_length=0; /* computed by fbcon */
+ fix->mmio_start=NULL;
+ fix->mmio_len=0;
+ fix->accel=FB_ACCEL_NONE;
+ FEND;
+ return 0;
+}
+
+static int cvppcfb_decode_var(const struct fb_var_screeninfo* var,
+ void* par, struct fb_info_gen* info) {
+ struct cvppcfb_par p;
+
+ FBEGIN;
+ memset(&p, 0, sizeof(struct cvppcfb_par));
+ p.bpp=(var->bits_per_pixel+7)&~7;
+ if (p.bpp==24)
+ p.bpp=32;
+ if (p.bpp>32) {
+ DPRINTK("depth too big (%lu)\n", p.bpp);
+ return -EINVAL;
+ }
+ p.xres=(var->xres+7)&~7;
+ p.yres=var->yres;
+ if (p.xres<320 || p.yres<200 || p.xres>2048 || p.yres>2048) {
+ DPRINTK("bad resolution (%lux%lu)\n", p.xres, p.yres);
+ return -EINVAL;
+ }
+ p.vxres=(var->xres_virtual+7)&~7;
+ p.vxoff=(var->xoffset+7)&~7;
+ p.vyres=var->yres_virtual;
+ p.vyoff=var->yoffset;
+ if (p.vxres<p.xres+p.vxoff)
+ p.vxres=p.xres+p.vxoff;
+ if (p.vyres<p.yres+p.vyoff)
+ p.vyres=p.yres+p.vyoff;
+ if (p.vxres*p.vyres*p.bpp/8>video_size) {
+ DPRINTK("no memory for screen (%lux%lux%lu)\n",
+ p.vxres, p.vyres, p.bpp);
+ return -EINVAL;
+ }
+ p.sflags=var->sync&(FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT);
+ p.clock=var->pixclock;
+ if (p.clock<6666) {
+ DPRINTK("pixclock too fast (%lu)\n", p.clock);
+ return -EINVAL;
+ }
+ p.left=var->left_margin;
+ p.top=var->upper_margin;
+ p.right=var->right_margin;
+ p.bottom=var->lower_margin;
+ p.hsynclen=var->hsync_len;
+ p.vsynclen=var->vsync_len;
+ *((struct cvppcfb_par* )par)=p;
+ FEND;
+ return 0;
+}
+
+static int cvppcfb_encode_var(struct fb_var_screeninfo* var,
+ const void* par, struct fb_info_gen* info) {
+ struct cvppcfb_par* p=(struct cvppcfb_par* )par;
+ struct fb_var_screeninfo v;
+
+ FBEGIN;
+ memset(&v, 0, sizeof(struct fb_var_screeninfo));
+ v.xres=p->xres;
+ v.yres=p->yres;
+ v.xres_virtual=p->vxres;
+ v.yres_virtual=p->vyres;
+ v.xoffset=p->vxoff;
+ v.yoffset=p->vyoff;
+ v.bits_per_pixel=p->bpp;
+ switch (p->bpp) {
+ case 16:
+ v.red.offset=11;
+ v.red.length=5;
+ v.green.offset=5;
+ v.green.length=6;
+ v.blue.length=5;
+ break;
+ case 32:
+ v.transp.offset=24;
+ v.red.offset=16;
+ v.green.offset=8;
+ v.transp.length=8;
+ /* fallback */
+ case 8:
+ v.red.length=v.green.length=v.blue.length=8;
+ break;
+ }
+ v.activate=FB_ACTIVATE_NOW;
+ v.height=v.width=-1;
+ v.pixclock=p->clock;
+ v.left_margin=p->left;
+ v.right_margin=p->right;
+ v.upper_margin=p->top;
+ v.lower_margin=p->bottom;
+ v.hsync_len=p->hsynclen;
+ v.vsync_len=p->vsynclen;
+ v.sync=p->sflags;
+ v.vmode=FB_VMODE_NONINTERLACED;
+ *var=v;
+ FEND;
+ return 0;
+}
+
+static void cvppcfb_get_par(void* par, struct fb_info_gen* info) {
+ struct cvppcfb_info* i=(struct cvppcfb_info* )info;
+
+ FBEGIN;
+ if (i->current_par_valid)
+ *((struct cvppcfb_par* )par)=i->current_par;
+ else
+ cvppcfb_decode_opt(&usr_startup, par, i);
+ FEND;
+}
+
+static void cvppcfb_set_par(const void* par, struct fb_info_gen* info) {
+ struct cvppcfb_info* i=(struct cvppcfb_info* )info;
+
+ FBEGIN;
+ i->current_par=*((struct cvppcfb_par* )par);
+ i->current_par_valid=1;
+ FEND;
+}
+
+static int cvppcfb_getcolreg(unsigned regno,
+ unsigned* red, unsigned* green, unsigned* blue,
+ unsigned* transp, struct fb_info* info) {
+ struct cvppcfb_info* i=(struct cvppcfb_info* )info;
+
+ if (regno<256) {
+ *red=i->palette[regno].red<<8|i->palette[regno].red;
+ *green=i->palette[regno].green<<8|i->palette[regno].green;
+ *blue=i->palette[regno].blue<<8|i->palette[regno].blue;
+ *transp=i->palette[regno].transp<<8|i->palette[regno].transp;
+ }
+ return regno>255;
+}
+
+static int cvppcfb_setcolreg(unsigned regno,
+ unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info* info) {
+ struct cvppcfb_info* i=(struct cvppcfb_info* )info;
+
+ if (regno<16) {
+ switch (i->current_par.bpp) {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ DPRINTK("8 bit depth not supported yet.\n");
+ return 1;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ i->cmap.cmap16[regno]=
+ ((u32 )red & 0xf800) |
+ (((u32 )green & 0xfc00)>>5) |
+ (((u32 )blue & 0xf800)>>11);
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ i->cmap.cmap32[regno]=
+ (((u32 )transp & 0xff00) << 16) |
+ (((u32 )red & 0xff00) << 8) |
+ (((u32 )green & 0xff00)) |
+ (((u32 )blue & 0xff00) >> 8);
+ break;
+#endif
+ }
+ }
+ if (regno<256) {
+ i->palette[regno].red=red >> 8;
+ i->palette[regno].green=green >> 8;
+ i->palette[regno].blue=blue >> 8;
+ i->palette[regno].transp=transp >> 8;
+ }
+ return regno>255;
+}
+
+static void cvppcfb_dispsw(const void* par, struct display* disp,
+ struct fb_info_gen* info) {
+ struct cvppcfb_info* i=(struct cvppcfb_info* )info;
+ unsigned long flags;
+
+ FBEGIN;
+ save_flags(flags);
+ cli();
+ switch (((struct cvppcfb_par* )par)->bpp) {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ disp->dispsw=&fbcon_cfb8;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ disp->dispsw=&fbcon_cfb16;
+ disp->dispsw_data=i->cmap.cmap16;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ disp->dispsw=&fbcon_cfb32;
+ disp->dispsw_data=i->cmap.cmap32;
+ break;
+#endif
+ default:
+ disp->dispsw=&fbcon_dummy;
+ break;
+ }
+ restore_flags(flags);
+ FEND;
+}
+
+static int cvppcfb_open(struct fb_info* info, int user) {
+
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int cvppcfb_release(struct fb_info* info, int user) {
+
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+/*
+ * public functions
+ */
+
+void cvppcfb_cleanup(struct fb_info* info) {
+
+ unregister_framebuffer(info);
+}
+
+__initfunc(void cvppcfb_init(void)) {
+
+ FBEGIN;
+#ifdef CVPPCFB_MASTER_DEBUG
+ printk("cvppcfb_init():\n");
+ printk(" resolution %ldx%ldx%ld\n", usr_startup.xres,
+ usr_startup.yres, usr_startup.bpp);
+ printk(" debug: %ld, YANW: %ld\n", usr_startup.debug,
+ usr_startup.YANW);
+ printk(" monitorcap: %ld,%ld,%ld,%ld\n",
+ usr_startup.monitor.vfmin, usr_startup.monitor.vfmax,
+ usr_startup.monitor.hfmin, usr_startup.monitor.hfmax);
+#endif
+ if (usr_startup.YANW) /* cannot probe yet */
+ return;
+ memset(&fb_info, 0, sizeof(struct cvppcfb_info));
+ video_size=CVPPC_SIZE;
+ video_phys=CVPPC_BASE;
+#ifdef CONFIG_APUS
+ video_base=(char* )
+ kernel_map(video_phys, video_size, KERNELMAP_NOCACHE_SER, NULL);
+#else
+ video_base=ioremap(video_phys, video_size);
+#endif
+ DPRINTK("video_phys=%08lx, video_base=%08lx\n", video_phys, video_base);
+ DPRINTK("phys_to_virt(video_phys)=%08lx\n", phys_to_virt(video_phys));
+ DPRINTK("virt_to_phys(video_base)=%08lx\n", virt_to_phys(video_base));
+ fb_info.disp.scrollmode=SCROLL_YREDRAW;
+ fb_info.gen.parsize=sizeof(struct cvppcfb_par);
+ fb_info.gen.fbhw=&cvppcfb_hwswitch;
+ cvppcfb_set_modename(&fb_info, &usr_startup);
+ fb_info.gen.info.flags=FBINFO_FLAG_DEFAULT;
+ fb_info.gen.info.fbops=&cvppcfb_ops;
+ fb_info.gen.info.monspecs=usr_startup.monitor;
+ fb_info.gen.info.disp=&fb_info.disp;
+ strcpy(fb_info.gen.info.fontname, usr_startup.font);
+ fb_info.gen.info.switch_con=&fbgen_switch;
+ fb_info.gen.info.updatevar=&fbgen_update_var;
+ fb_info.gen.info.blank=&fbgen_blank;
+ fbgen_get_var(&fb_info.disp.var, -1, &fb_info.gen.info);
+ if (fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen)<0) {
+ printk( "cvppcfb: bad startup configuration: "
+ "unable to register.\n");
+ return;
+ }
+ fbgen_set_disp(-1, &fb_info.gen);
+ fbgen_install_cmap(0, &fb_info.gen);
+ if (register_framebuffer(&fb_info.gen.info)<0) {
+ printk("cvppcfb: unable to register.\n");
+ return;
+ }
+ printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
+ GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename,
+ (unsigned long )(video_size>>10));
+ MOD_INC_USE_COUNT;
+ FEND;
+}
+
+__initfunc(void cvppcfb_setup(char* options, int* ints)) {
+ char* next;
+
+ usr_startup.YANW=0;
+ DPRINTK("options: '%s'\n", options);
+ while (options) {
+ if ((next=strchr(options, ',')))
+ *(next++)='\0';
+ if (!strncmp(options, "monitorcap:", 11))
+ cvppcfb_encode_mcap(options+11, &usr_startup.monitor);
+ else if (!strncmp(options, "debug:", 6)) {
+ if (ISDIGIT(options[6]))
+ usr_startup.debug=options[6]-'0';
+ else
+ usr_startup.debug=1;
+ }
+ else if (!strncmp(options, "mode:", 5))
+ cvppcfb_encode_mode(options+5, &usr_startup);
+ else if (!strncmp(options, "font:", 5))
+ strcpy(usr_startup.font, options+5);
+ else
+ DPRINTK("unrecognized option '%s'\n", options);
+ options=next;
+ }
+#ifdef CVPPCFB_MASTER_DEBUG
+ printk("cvppcfb_setup():\n");
+ printk(" resolution %ldx%ldx%ld\n", usr_startup.xres,
+ usr_startup.yres, usr_startup.bpp);
+ printk(" debug: %ld, YANW: %ld\n", usr_startup.debug,
+ usr_startup.YANW);
+ printk(" monitorcap: %ld,%ld,%ld,%ld\n",
+ usr_startup.monitor.vfmin, usr_startup.monitor.vfmax,
+ usr_startup.monitor.hfmin, usr_startup.monitor.hfmax);
+#endif
+}
+
+/*
+ * modularization
+ */
+
+#ifdef MODULE
+int init_module(void) {
+
+ cvppcfb_init();
+}
+
+void cleanup_module(void) {
+
+ cvppcfb_cleanup();
+}
+#endif /* MODULE */
+
diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c
index ebf72f0bd..80ec1481b 100644
--- a/drivers/video/cyberfb.c
+++ b/drivers/video/cyberfb.c
@@ -1,24 +1,80 @@
/*
- * linux/drivers/video/cyberfb.c -- CyberVision64 frame buffer device
- *
- * Copyright (C) 1996 Martin Apel
- * Geert Uytterhoeven
- *
- *
- * This file is based on the Amiga frame buffer device (amifb.c):
- *
- * Copyright (C) 1995 Geert Uytterhoeven
- *
- *
- * History:
- * - 22 Dec 95: Original version by Martin Apel
- * - 05 Jan 96: Geert: integration into the current source tree
- *
- *
- * 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.
- */
+* linux/drivers/video/cyberfb.c -- CyberVision64 frame buffer device
+* $Id: cyberfb.c,v 1.6 1998/09/11 04:54:58 abair Exp $
+*
+* Copyright (C) 1998 Alan Bair
+*
+* This file is based on two CyberVision64 frame buffer device drivers
+*
+* The second CyberVision64 frame buffer device (cvision.c cvision_core.c):
+*
+* Copyright (c) 1997 Antonio Santos
+*
+* Released as a patch to 2.1.35, but never included in the source tree.
+* This is based on work from the NetBSD CyberVision64 frame buffer driver
+* and support files (grf_cv.c, grf_cvreg.h, ite_cv.c):
+* Permission to use the source of this driver was obtained from the
+* author Michael Teske by Alan Bair.
+*
+* Copyright (c) 1995 Michael Teske
+*
+* The first CyberVision64 frame buffer device (cyberfb.c):
+*
+* Copyright (C) 1996 Martin Apel
+* Geert Uytterhoeven
+*
+* Which is based on the Amiga frame buffer device (amifb.c):
+*
+* Copyright (C) 1995 Geert Uytterhoeven
+*
+*
+* History:
+* - 22 Dec 95: Original version by Martin Apel
+* - 05 Jan 96: Geert: integration into the current source tree
+* - 01 Aug 98: Alan: Merge in code from cvision.c and cvision_core.c
+* $Log: cyberfb.c,v $
+* Revision 1.6 1998/09/11 04:54:58 abair
+* Update for 2.1.120 change in include file location.
+* Clean up for public release.
+*
+* Revision 1.5 1998/09/03 04:27:13 abair
+* Move cv64_load_video_mode to cyber_set_video so a new video mode is install
+* with each change of the 'var' data.
+*
+* Revision 1.4 1998/09/01 00:31:17 abair
+* Put in a set of default 8,16,24 bpp modes and map cyber8,16 to them.
+* Update operations with 'par' to handle a more complete set of parameter
+* values for encode/decode process.
+*
+* Revision 1.3 1998/08/31 21:31:33 abair
+* Swap 800x490 for 640x480 video mode and more cleanup.
+* Abandon idea to resurrect "custom" mode setting via kernel opts,
+* instead work on making use of fbset program to do this.
+*
+* Revision 1.2 1998/08/31 06:17:08 abair
+* Make updates for changes in cyberfb.c released in 2.1.119
+* and do some cleanup of the code.
+*
+* Revision 1.1 1998/08/29 18:38:31 abair
+* Initial revision
+*
+* Revision 1.3 1998/08/17 06:21:53 abair
+* Remove more redundant code after merging in cvision_core.c
+* Set blanking by colormap to pale red to detect this vs trying to
+* use video blanking. More formating to Linux code style.
+*
+* Revision 1.2 1998/08/15 17:51:37 abair
+* Added cvision_core.c code from 2.1.35 patches.
+* Changed to compile correctly and switch to using initialization
+* code. Added debugging and dropping of duplicate code.
+*
+*
+*
+* 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/kernel.h>
@@ -36,31 +92,31 @@
#include <asm/irq.h>
#include <asm/pgtable.h>
#include <asm/amigahw.h>
+#include <asm/io.h>
-#include "s3blit.h"
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-
+#include "cyberfb.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+/*#define CYBERFBDEBUG*/
#ifdef CYBERFBDEBUG
#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+static void cv64_dump(void);
#else
#define DPRINTK(fmt, args...)
#endif
#define arraysize(x) (sizeof(x)/sizeof(*(x)))
-
#define wb_64(reg,dat) (*((unsigned char volatile *)CyberRegs + reg) = dat)
-
-
struct cyberfb_par {
- int xres;
- int yres;
- int bpp;
- int accel;
+ struct fb_var_screeninfo var;
+ __u32 type;
+ __u32 type_aux;
+ __u32 visual;
+ __u32 line_length;
};
static struct cyberfb_par current_par;
@@ -73,148 +129,148 @@ static struct fb_info fb_info;
/*
- * Switch for Chipset Independency
- */
+* Switch for Chipset Independency
+*/
static struct fb_hwswitch {
- /* Initialisation */
+/* Initialisation */
- int (*init)(void);
+int (*init)(void);
- /* Display Control */
+/* Display Control */
- int (*encode_fix)(struct fb_fix_screeninfo *fix, struct cyberfb_par *par);
- int (*decode_var)(struct fb_var_screeninfo *var, struct cyberfb_par *par);
- int (*encode_var)(struct fb_var_screeninfo *var, struct cyberfb_par *par);
- int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue,
- u_int *transp, struct fb_info *info);
- int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info);
- void (*blank)(int blank);
+int (*encode_fix)(struct fb_fix_screeninfo *fix, struct cyberfb_par *par);
+int (*decode_var)(struct fb_var_screeninfo *var, struct cyberfb_par *par);
+int (*encode_var)(struct fb_var_screeninfo *var, struct cyberfb_par *par);
+int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue,
+ u_int *transp, struct fb_info *info);
+int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info);
+void (*blank)(int blank);
} *fbhw;
/*
- * Frame Buffer Name
- */
+* Frame Buffer Name
+*/
static char cyberfb_name[16] = "Cybervision";
/*
- * Cybervision Graphics Board
- */
-
-#define CYBER8_WIDTH 1152
-#define CYBER8_HEIGHT 886
-#define CYBER8_PIXCLOCK 12500 /* ++Geert: Just a guess */
+* Cybervision Graphics Board
+*/
-#if 0
-#define CYBER16_WIDTH 800
-#define CYBER16_HEIGHT 600
-#endif
-#define CYBER16_PIXCLOCK 25000 /* ++Geert: Just a guess */
-
-
-static unsigned int CyberKey = 0;
-static unsigned char Cyber_colour_table [256][4];
+static unsigned char Cyber_colour_table [256][3];
static unsigned long CyberMem;
static unsigned long CyberSize;
static volatile char *CyberRegs;
-
+/* From cvision.c for cvision_core.c */
+static unsigned long cv64_mem;
+static unsigned long cv64_fbmem;
+static volatile char *cv64_regs;
+static unsigned long cv64_size;
+#if 0
+static int cvision_custom_mode = 0;
+static int hbs, hbe, hss, hse, ht, vbs, vbe, vss, vse, vt;
+#endif
/*
- * Predefined Video Modes
- */
+* Predefined Video Modes
+*/
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_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_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_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_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_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_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_ACCELF_TEXT, CYBER16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
- FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
- }
- }
+ { "640x480-8", { /* Default 8 BPP mode (cyber8) */
+ 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_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
+ FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "640x480-16", { /* Default 16 BPP mode (cyber16) */
+ 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_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
+ FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "640x480-24", { /* Default 24 BPP mode */
+ 640, 480, 640, 480, 0, 0, 24, 0,
+ {16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
+ FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED
+ }},
+ { "800x490-8", { /* Cybervision 8 bpp */
+ /* NO Acceleration */
+ 800, 490, 800, 490, 0, 0, 8, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCEL_NONE, 33333, 80, 24, 23, 1, 56, 8,
+ FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED
+ }},
+/* I can't test these with my monitor, but I suspect they will
+ * be OK, since Antonio Santos indicated he had tested them in
+ * his system.
+ */
+ { "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_ACCELF_TEXT, 27778, 64, 24, 22, 1, 72, 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_ACCELF_TEXT, 16667, 224, 72, 60, 12, 168, 4,
+ 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_ACCELF_TEXT, 15873, 184, 40, 24, 1, 56, 16,
+ 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_ACCELF_TEXT, 16667, 256, 48, 50, 12, 72, 4,
+ FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_INTERLACED
+ }}
};
-
#define NUM_TOTAL_MODES arraysize(cyberfb_predefined)
-
static int Cyberfb_inverse = 0;
-#if 0
-static int Cyberfb_Cyber8 = 0; /* Use Cybervision board */
-static int Cyberfb_Cyber16 = 0; /* Use Cybervision board */
-#endif
/*
- * Some default modes
- */
+* Some default modes
+*/
#define CYBER8_DEFMODE (0)
-#define CYBER16_DEFMODE (6)
+#define CYBER16_DEFMODE (1)
static struct fb_var_screeninfo cyberfb_default;
-
/*
- * Interface used by the world
- */
+* Interface used by the world
+*/
void cyberfb_setup(char *options, int *ints);
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
-fb_info *info);
-static int cyberfb_set_var(struct fb_var_screeninfo *var, int con, struct
-fb_info *info);
+static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info);
+static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info);
static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
@@ -222,31 +278,28 @@ static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
static int cyberfb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int cyberfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
- u_long arg, int con, struct fb_info *info);
-
+ u_long arg, int con, struct fb_info *info);
/*
- * Interface to the low level console driver
- */
+* Interface to the low level console driver
+*/
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);
-
/*
- * Text console acceleration
- */
+* Text console acceleration
+*/
#ifdef FBCON_HAS_CFB8
static struct display_switch fbcon_cyber8;
#endif
-
/*
- * Accelerated Functions used by the low level console driver
- */
+* Accelerated Functions used by the low level console driver
+*/
static void Cyber_WaitQueue(u_short fifo);
static void Cyber_WaitBlit(void);
@@ -257,28 +310,26 @@ static void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
u_short mode, u_short color);
static void Cyber_MoveCursor(u_short x, u_short y);
-
/*
- * Hardware Specific Routines
- */
+* Hardware Specific Routines
+*/
static int Cyber_init(void);
static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
- struct cyberfb_par *par);
+ struct cyberfb_par *par);
static int Cyber_decode_var(struct fb_var_screeninfo *var,
- struct cyberfb_par *par);
+ struct cyberfb_par *par);
static int Cyber_encode_var(struct fb_var_screeninfo *var,
- struct cyberfb_par *par);
+ struct cyberfb_par *par);
static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
- u_int *transp, struct fb_info *info);
+ u_int *transp, struct fb_info *info);
static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info);
+ u_int transp, struct fb_info *info);
static void Cyber_blank(int blank);
-
/*
- * Internal routines
- */
+* Internal routines
+*/
static void cyberfb_get_par(struct cyberfb_par *par);
static void cyberfb_set_par(struct cyberfb_par *par);
@@ -287,41 +338,48 @@ static void do_install_cmap(int con, struct fb_info *info);
static void cyberfb_set_disp(int con, struct fb_info *info);
static int get_video_mode(const char *name);
+/* For cvision_core.c */
+static unsigned short cv64_compute_clock(unsigned long);
+static int cv_has_4mb (volatile caddr_t);
+static void cv64_board_init (void);
+static void cv64_load_video_mode (struct fb_var_screeninfo *);
+
/* -------------------- Hardware specific routines ------------------------- */
/*
- * Initialization
- *
- * Set the default video mode for this chipset. If a video mode was
- * specified on the command line, it will override the default mode.
- */
+* Initialization
+*
+* Set the default video mode for this chipset. If a video mode was
+* specified on the command line, it will override the default mode.
+*/
static int Cyber_init(void)
{
int i;
- char size;
volatile u_long *CursorBase;
+ DPRINTK("ENTER\n");
- for (i = 0; i < 256; i++)
- {
+/* Init local cmap as greyscale levels */
+ for (i = 0; i < 256; i++) {
Cyber_colour_table [i][0] = i;
Cyber_colour_table [i][1] = i;
Cyber_colour_table [i][2] = i;
- Cyber_colour_table [i][3] = 0;
}
- /*
- * Just clear the thing for the biggest mode.
- *
- * ++Andre, TODO: determine size first, then clear all memory
- * (the 3D penguin might need texture memory :-) )
- */
-
- memset ((char*)CyberMem, 0, 1600 * 1200);
+/* Initialize the board and determine fbmem size */
+ cv64_board_init ();
+#ifdef CYBERFBDEBUG
+ DPRINTK("Register state after initing board\n");
+ cv64_dump();
+#endif
+/* Clear framebuffer memory */
+ DPRINTK("Clear framebuffer memory\n");
+ memset ((char *) cv64_fbmem, 0, cv64_size);
- /* Disable hardware cursor */
+/* Disable hardware cursor */
+ DPRINTK("Disable HW cursor\n");
wb_64(S3_CRTC_ADR, S3_REG_LOCK2);
wb_64(S3_CRTC_DATA, 0xa0);
wb_64(S3_CRTC_ADR, S3_HGC_MODE);
@@ -331,15 +389,10 @@ static int Cyber_init(void)
wb_64(S3_CRTC_ADR, S3_HWGC_DY);
wb_64(S3_CRTC_DATA, 0x00);
- /* Get memory size (if not 2MB it is 4MB) */
- *(CyberRegs + S3_CRTC_ADR) = S3_LAW_CTL;
- size = *(CyberRegs + S3_CRTC_DATA);
- if ((size & 0x03) == 0x02)
- CyberSize = 0x00200000; /* 2 MB */
- else
- CyberSize = 0x00400000; /* 4 MB */
+ CyberSize = cv64_size;
- /* Initialize hardware cursor */
+/* Initialize hardware cursor */
+ DPRINTK("Init HW cursor\n");
CursorBase = (u_long *)((char *)(CyberMem) + CyberSize - 0x400);
for (i=0; i < 8; i++)
{
@@ -356,34 +409,38 @@ static int Cyber_init(void)
*(CursorBase+3+(i*4)) = 0xffff0000;
}
- Cyber_setcolreg (255, 56, 100, 160, 0, NULL /* unused */);
+ Cyber_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL /* unused */);
Cyber_setcolreg (254, 0, 0, 0, 0, NULL /* unused */);
+ DPRINTK("EXIT\n");
return 0;
}
/*
- * This function should fill in the `fix' structure based on the
- * values in the `par' structure.
- */
+* This function should fill in the `fix' structure based on the
+* values in the `par' structure.
+*/
static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
struct cyberfb_par *par)
{
+ DPRINTK("ENTER\n");
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, cyberfb_name);
- fix->smem_start = (char *)CyberMem;
+ fix->smem_start = (char*) virt_to_phys ((void *)CyberMem);
fix->smem_len = CyberSize;
- fix->mmio_start = (char *)CyberRegs;
+ fix->mmio_start = (char*) virt_to_phys ((void *)CyberRegs);
fix->mmio_len = 0x10000;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
- if (par->bpp == 8)
- fix->visual = FB_VISUAL_PSEUDOCOLOR;
- else
+ if (par->var.bits_per_pixel == 15 || par->var.bits_per_pixel == 16 ||
+ par->var.bits_per_pixel == 24 || par->var.bits_per_pixel == 32) {
fix->visual = FB_VISUAL_DIRECTCOLOR;
+ } else {
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ }
fix->xpanstep = 0;
fix->ypanstep = 0;
@@ -391,181 +448,194 @@ static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
fix->line_length = 0;
fix->accel = FB_ACCEL_S3_TRIO64;
+ DPRINTK("EXIT\n");
return(0);
}
/*
- * Get the video params out of `var'. If a value doesn't fit, round
- * it up, if it's too big, return -EINVAL.
- */
+* Fill the `par' structure based on the values in `var'.
+* TODO: Verify and adjust values, return -EINVAL if bad.
+*/
static int Cyber_decode_var(struct fb_var_screeninfo *var,
struct cyberfb_par *par)
{
-#if 1
- 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;
- par->yres = CYBER8_HEIGHT;
- par->bpp = 8;
+ DPRINTK("ENTER\n");
+ par->var.xres = var->xres;
+ par->var.yres = var->yres;
+ par->var.xres_virtual = var->xres_virtual;
+ par->var.yres_virtual = var->yres_virtual;
+ par->var.xoffset = var->xoffset;
+ par->var.yoffset = var->yoffset;
+ par->var.bits_per_pixel = var->bits_per_pixel;
+ par->var.grayscale = var->grayscale;
+ par->var.red = var->red;
+ par->var.green = var->green;
+ par->var.blue = var->blue;
+ par->var.transp = var->transp;
+ par->var.nonstd = var->nonstd;
+ par->var.activate = var->activate;
+ par->var.height = var->height;
+ par->var.width = var->width;
+ if (var->accel_flags & FB_ACCELF_TEXT) {
+ par->var.accel_flags = FB_ACCELF_TEXT;
} else {
- par->xres = CYBER16_WIDTH;
- par->yres = CYBER16_HEIGHT;
- par->bpp = 16;
+ par->var.accel_flags = 0;
}
-#endif
+ par->var.pixclock = var->pixclock;
+ par->var.left_margin = var->left_margin;
+ par->var.right_margin = var->right_margin;
+ par->var.upper_margin = var->upper_margin;
+ par->var.lower_margin = var->lower_margin;
+ par->var.hsync_len = var->hsync_len;
+ par->var.vsync_len = var->vsync_len;
+ par->var.sync = var->sync;
+ par->var.vmode = var->vmode;
+ DPRINTK("EXIT\n");
return(0);
}
-
/*
- * Fill the `var' structure based on the values in `par' and maybe
- * other values read out of the hardware.
- */
+* Fill the `var' structure based on the values in `par' and maybe
+* other values read out of the hardware.
+*/
static int Cyber_encode_var(struct fb_var_screeninfo *var,
struct cyberfb_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->bpp;
- var->grayscale = 0;
-
- if (par->bpp == 8) {
- var->red.offset = 0;
- var->red.length = 8;
- var->red.msb_right = 0;
- var->blue = var->green = var->red;
- } else {
- var->red.offset = 11;
- var->red.length = 5;
- var->red.msb_right = 0;
- var->green.offset = 5;
- var->green.length = 6;
- var->green.msb_right = 0;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->blue.msb_right = 0;
- }
- var->transp.offset = 0;
- var->transp.length = 0;
- var->transp.msb_right = 0;
-
- var->nonstd = 0;
- var->activate = 0;
-
- var->height = -1;
- var->width = -1;
-
- var->accel_flags = (par->accel && par->bpp == 8) ? FB_ACCELF_TEXT : 0;
-
- var->vmode = FB_VMODE_NONINTERLACED;
-
- /* Dummy values */
-
- if (par->bpp == 8)
- var->pixclock = CYBER8_PIXCLOCK;
- else
- var->pixclock = CYBER16_PIXCLOCK;
- var->sync = 0;
- var->left_margin = 64;
- var->right_margin = 96;
- var->upper_margin = 35;
- var->lower_margin = 12;
- var->hsync_len = 112;
- var->vsync_len = 2;
-
+ DPRINTK("ENTER\n");
+ var->xres = par->var.xres;
+ var->yres = par->var.yres;
+ var->xres_virtual = par->var.xres_virtual;
+ var->yres_virtual = par->var.yres_virtual;
+ var->xoffset = par->var.xoffset;
+ var->yoffset = par->var.yoffset;
+
+ var->bits_per_pixel = par->var.bits_per_pixel;
+ var->grayscale = par->var.grayscale;
+
+ var->red = par->var.red;
+ var->green = par->var.green;
+ var->blue = par->var.blue;
+ var->transp = par->var.transp;
+
+ var->nonstd = par->var.nonstd;
+ var->activate = par->var.activate;
+
+ var->height = par->var.height;
+ var->width = par->var.width;
+
+ var->accel_flags = par->var.accel_flags;
+
+ var->pixclock = par->var.pixclock;
+ var->left_margin = par->var.left_margin;
+ var->right_margin = par->var.right_margin;
+ var->upper_margin = par->var.upper_margin;
+ var->lower_margin = par->var.lower_margin;
+ var->hsync_len = par->var.hsync_len;
+ var->vsync_len = par->var.vsync_len;
+ var->sync = par->var.sync;
+ var->vmode = par->var.vmode;
+
+ DPRINTK("EXIT\n");
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.
- */
+* Set a single color register. Return != 0 for invalid regno.
+*/
static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
- if (regno > 255)
- {
+ /*DPRINTK("ENTER\n");*/
+ if (regno > 255) {
+ DPRINTK("EXIT - Register # > 255\n");
return (1);
}
wb_64(0x3c8, (unsigned char) regno);
- Cyber_colour_table [regno][0] = red & 0xff;
- Cyber_colour_table [regno][1] = green & 0xff;
- Cyber_colour_table [regno][2] = blue & 0xff;
- Cyber_colour_table [regno][3] = transp;
- wb_64(0x3c9, (red & 0xff) >> 2);
- wb_64(0x3c9, (green & 0xff) >> 2);
- wb_64(0x3c9, (blue & 0xff) >> 2);
+ red >>= 10;
+ green >>= 10;
+ blue >>= 10;
+ Cyber_colour_table [regno][0] = red;
+ Cyber_colour_table [regno][1] = green;
+ Cyber_colour_table [regno][2] = blue;
+
+ wb_64(0x3c9, red);
+ wb_64(0x3c9, green);
+ wb_64(0x3c9, blue);
+
+ /*DPRINTK("EXIT\n");*/
return (0);
}
/*
- * Read a single color register and split it into
- * colors/transparent. Return != 0 for invalid regno.
- */
+* Read a single color register and split it into
+* colors/transparent. Return != 0 for invalid regno.
+*/
static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info)
{
- if (regno >= 256)
+ int t;
+
+ /*DPRINTK("ENTER\n");*/
+ if (regno > 255) {
+ DPRINTK("EXIT - Register # > 255\n");
return (1);
- *red = Cyber_colour_table [regno][0];
- *green = Cyber_colour_table [regno][1];
- *blue = Cyber_colour_table [regno][2];
- *transp = Cyber_colour_table [regno][3];
+ }
+ /* ARB This shifting & oring seems VERY strange */
+ t = Cyber_colour_table [regno][0];
+ *red = (t<<10) | (t<<4) | (t>>2);
+ t = Cyber_colour_table [regno][1];
+ *green = (t<<10) | (t<<4) | (t>>2);
+ t = Cyber_colour_table [regno][2];
+ *blue = (t<<10) | (t<<4) | (t>>2);
+ *transp = 0;
+ /*DPRINTK("EXIT\n");*/
return (0);
}
/*
- * (Un)Blank the screen
- */
+* (Un)Blank the screen
+* blank: 1 = zero fb cmap
+* 0 = restore fb cmap from local cmap
+*/
void Cyber_blank(int blank)
{
int i;
- if (blank)
- {
- for (i = 0; i < 256; i++)
- {
+ DPRINTK("ENTER\n");
+#if 0
+/* Blank by turning gfx off */
+ gfx_on_off (1, cv64_regs);
+#else
+ if (blank) {
+ for (i = 0; i < 256; i++) {
wb_64(0x3c8, (unsigned char) i);
- wb_64(0x3c9, 0);
+ /* ARB Pale red to detect this blanking method */
+ wb_64(0x3c9, 48);
wb_64(0x3c9, 0);
wb_64(0x3c9, 0);
}
- }
- else
- {
- for (i = 0; i < 256; i++)
- {
+ } else {
+ for (i = 0; i < 256; i++) {
wb_64(0x3c8, (unsigned char) i);
- wb_64(0x3c9, Cyber_colour_table[i][0] >> 2);
- wb_64(0x3c9, Cyber_colour_table[i][1] >> 2);
- wb_64(0x3c9, Cyber_colour_table[i][2] >> 2);
+ wb_64(0x3c9, Cyber_colour_table[i][0]);
+ wb_64(0x3c9, Cyber_colour_table[i][1]);
+ wb_64(0x3c9, Cyber_colour_table[i][2]);
}
}
+#endif
+ DPRINTK("EXIT\n");
}
@@ -576,11 +646,12 @@ static void Cyber_WaitQueue (u_short fifo)
{
u_short status;
- do
- {
+ DPRINTK("ENTER\n");
+ do {
status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
}
while (status & fifo);
+ DPRINTK("EXIT\n");
}
/**************************************************************
@@ -590,11 +661,12 @@ static void Cyber_WaitBlit (void)
{
u_short status;
- do
- {
+ DPRINTK("ENTER\n");
+ do {
status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
}
while (status & S3_HDW_BUSY);
+ DPRINTK("EXIT\n");
}
/**************************************************************
@@ -606,20 +678,19 @@ static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx,
{
u_short blitcmd = S3_BITBLT;
+ DPRINTK("ENTER\n");
/* Set drawing direction */
/* -Y, X maj, -X (default) */
- if (curx > destx)
+ if (curx > destx) {
blitcmd |= 0x0020; /* Drawing direction +X */
- else
- {
+ } else {
curx += (width - 1);
destx += (width - 1);
}
- if (cury > desty)
+ if (cury > desty) {
blitcmd |= 0x0080; /* Drawing direction +Y */
- else
- {
+ } else {
cury += (height - 1);
desty += (height - 1);
}
@@ -639,6 +710,7 @@ static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx,
*((u_short volatile *)(CyberRegs + S3_MAJ_AXIS_PCNT)) = width - 1;
*((u_short volatile *)(CyberRegs + S3_CMD)) = blitcmd;
+ DPRINTK("EXIT\n");
}
/**************************************************************
@@ -649,6 +721,7 @@ static void Cyber_RectFill (u_short x, u_short y, u_short width,
{
u_short blitcmd = S3_FILLEDRECT;
+ DPRINTK("ENTER\n");
Cyber_WaitQueue (0x8000);
*((u_short volatile *)(CyberRegs + S3_PIXEL_CNTL)) = 0xa000;
@@ -664,6 +737,7 @@ static void Cyber_RectFill (u_short x, u_short y, u_short width,
*((u_short volatile *)(CyberRegs + S3_MAJ_AXIS_PCNT)) = width - 1;
*((u_short volatile *)(CyberRegs + S3_CMD)) = blitcmd;
+ DPRINTK("EXIT\n");
}
/**************************************************************
@@ -671,6 +745,7 @@ static void Cyber_RectFill (u_short x, u_short y, u_short width,
*/
static void Cyber_MoveCursor (u_short x, u_short y)
{
+ DPRINTK("ENTER\n");
*(CyberRegs + S3_CRTC_ADR) = 0x39;
*(CyberRegs + S3_CRTC_DATA) = 0xa0;
@@ -683,6 +758,7 @@ static void Cyber_MoveCursor (u_short x, u_short y)
*(CyberRegs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
*(CyberRegs + S3_CRTC_ADR) = S3_HWGC_ORGY_L;
*(CyberRegs + S3_CRTC_DATA) = (char)(y & 0x00ff);
+ DPRINTK("EXIT\n");
}
@@ -695,7 +771,7 @@ static struct fb_hwswitch Cyber_switch = {
};
-/* -------------------- Generic routines ------------------------------------ */
+/* -------------------- Generic routines ---------------------------------- */
/*
@@ -704,33 +780,34 @@ static struct fb_hwswitch Cyber_switch = {
static void cyberfb_get_par(struct cyberfb_par *par)
{
- if (current_par_valid)
- {
+ DPRINTK("ENTER\n");
+ if (current_par_valid) {
*par = current_par;
- }
- else
- {
+ } else {
fbhw->decode_var(&cyberfb_default, par);
}
+ DPRINTK("EXIT\n");
}
static void cyberfb_set_par(struct cyberfb_par *par)
{
+ DPRINTK("ENTER\n");
current_par = *par;
current_par_valid = 1;
+ DPRINTK("EXIT\n");
}
static void cyber_set_video(struct fb_var_screeninfo *var)
{
- /* Set clipping rectangle to current screen size */
-
- *((u_short volatile *)(CyberRegs + 0xbee8)) = 0x1000;
- *((u_short volatile *)(CyberRegs + 0xbee8)) = 0x2000;
- *((u_short volatile *)(CyberRegs + 0xbee8)) = 0x3000 | (var->yres - 1);
- *((u_short volatile *)(CyberRegs + 0xbee8)) = 0x4000 | (var->xres - 1);
+ /* Load the video mode defined by the 'var' data */
+ cv64_load_video_mode (var);
+#ifdef CYBERFBDEBUG
+ DPRINTK("Register state after loading video mode\n");
+ cv64_dump();
+#endif
}
@@ -739,8 +816,11 @@ static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
int err, activate;
struct cyberfb_par par;
- if ((err = fbhw->decode_var(var, &par)))
+ DPRINTK("ENTER\n");
+ if ((err = fbhw->decode_var(var, &par))) {
+ DPRINTK("EXIT - decode_var failed\n");
return(err);
+ }
activate = var->activate;
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
cyberfb_set_par(&par);
@@ -748,20 +828,27 @@ static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
var->activate = activate;
cyber_set_video(var);
+ DPRINTK("EXIT\n");
return 0;
}
static void do_install_cmap(int con, struct fb_info *info)
{
- if (con != currcon)
+ DPRINTK("ENTER\n");
+ if (con != currcon) {
+ DPRINTK("EXIT - Not current console\n");
return;
- if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
- fbhw->setcolreg, info);
- else
+ }
+ if (fb_display[con].cmap.len) {
+ DPRINTK("Use console cmap\n");
+ fb_set_cmap(&fb_display[con].cmap, 1, fbhw->setcolreg, info);
+ } else {
+ DPRINTK("Use default cmap\n");
fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
- &fb_display[con].var, 1, fbhw->setcolreg, info);
+ 1, fbhw->setcolreg, info);
+ }
+ DPRINTK("EXIT\n");
}
@@ -796,10 +883,13 @@ static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct cyberfb_par par;
int error = 0;
- if (con == -1)
+ DPRINTK("ENTER\n");
+ if (con == -1) {
cyberfb_get_par(&par);
- else
+ } else {
error = fbhw->decode_var(&fb_display[con].var, &par);
+ }
+ DPRINTK("EXIT\n");
return(error ? error : fbhw->encode_fix(fix, &par));
}
@@ -814,17 +904,16 @@ static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
struct cyberfb_par par;
int error = 0;
- if (con == -1)
- {
+ DPRINTK("ENTER\n");
+ if (con == -1) {
cyberfb_get_par(&par);
error = fbhw->encode_var(var, &par);
disp.var = *var; /* ++Andre: don't know if this is the right place */
- }
- else
- {
+ } else {
*var = fb_display[con].var;
}
+ DPRINTK("EXIT\n");
return(error);
}
@@ -834,6 +923,7 @@ static void cyberfb_set_disp(int con, struct fb_info *info)
struct fb_fix_screeninfo fix;
struct display *display;
+ DPRINTK("ENTER\n");
if (con >= 0)
display = &fb_display[con];
else
@@ -842,7 +932,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 = fix.smem_start;
+ display->screen_base = phys_to_virt ((unsigned long) fix.smem_start);
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
@@ -869,6 +959,7 @@ static void cyberfb_set_disp(int con, struct fb_info *info)
display->dispsw = NULL;
break;
}
+ DPRINTK("EXIT\n");
}
@@ -881,8 +972,11 @@ static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
{
int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
- if ((err = do_fb_set_var(var, con == currcon)))
+ DPRINTK("ENTER\n");
+ if ((err = do_fb_set_var(var, con == currcon))) {
+ DPRINTK("EXIT - do_fb_set_var failed\n");
return(err);
+ }
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
oldxres = fb_display[con].var.xres;
oldyres = fb_display[con].var.yres;
@@ -903,6 +997,7 @@ static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
}
}
var->activate = 0;
+ DPRINTK("EXIT\n");
return(0);
}
@@ -914,14 +1009,19 @@ static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
- if (con == currcon) /* current console? */
- return(fb_get_cmap(cmap, &fb_display[con].var,
- kspc, fbhw->getcolreg, info));
- else if (fb_display[con].cmap.len) /* non default colormap? */
+ DPRINTK("ENTER\n");
+ if (con == currcon) { /* current console? */
+ DPRINTK("EXIT - console is current console\n");
+ return(fb_get_cmap(cmap, kspc, fbhw->getcolreg, info));
+ } else if (fb_display[con].cmap.len) { /* non default colormap? */
+ DPRINTK("Use console cmap\n");
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
- else
+ } else {
+ DPRINTK("Use default cmap\n");
fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
cmap, kspc ? 0 : 2);
+ }
+ DPRINTK("EXIT\n");
return(0);
}
@@ -935,16 +1035,22 @@ static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
{
int err;
+ DPRINTK("ENTER\n");
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)))
+ 1<<fb_display[con].var.bits_per_pixel,
+ 0))) {
+ DPRINTK("EXIT - fb_alloc_cmap failed\n");
return(err);
+ }
}
- if (con == currcon) /* current console? */
- return(fb_set_cmap(cmap, &fb_display[con].var,
- kspc, fbhw->setcolreg, info));
- else
+ if (con == currcon) { /* current console? */
+ DPRINTK("EXIT - Current console\n");
+ return(fb_set_cmap(cmap, kspc, fbhw->setcolreg, info));
+ } else {
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+ }
+ DPRINTK("EXIT\n");
return(0);
}
@@ -983,33 +1089,36 @@ static struct fb_ops cyberfb_ops = {
__initfunc(void cyberfb_setup(char *options, int *ints))
{
char *this_opt;
+ DPRINTK("ENTER\n");
fb_info.fontname[0] = '\0';
- if (!options || !*options)
+ if (!options || !*options) {
+ DPRINTK("EXIT - no options\n");
return;
+ }
- for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ","))
+ for (this_opt = strtok(options, ","); this_opt;
+ this_opt = strtok(NULL, ",")) {
if (!strcmp(this_opt, "inverse")) {
Cyberfb_inverse = 1;
fb_invert_cmaps();
- } else if (!strncmp(this_opt, "font:", 5))
+ } else if (!strncmp(this_opt, "font:", 5)) {
strcpy(fb_info.fontname, this_opt+5);
- else if (!strcmp (this_opt, "cyber8")){
+ } else if (!strcmp (this_opt, "cyber8")) {
cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
- }
- else if (!strcmp (this_opt, "cyber16")){
+ } else if (!strcmp (this_opt, "cyber16")) {
cyberfb_default = cyberfb_predefined[CYBER16_DEFMODE].var;
- }
- else
- get_video_mode(this_opt);
+ } else get_video_mode(this_opt);
+ }
- DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",cyberfb_default.xres,
- cyberfb_default.yres,
- cyberfb_default.bits_per_pixel);
+ DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",
+ cyberfb_default.xres,
+ cyberfb_default.yres,
+ cyberfb_default.bits_per_pixel);
+ DPRINTK("EXIT\n");
}
-
/*
* Initialization
*/
@@ -1018,19 +1127,39 @@ __initfunc(void cyberfb_init(void))
{
struct cyberfb_par par;
unsigned long board_addr;
+ unsigned long board_size;
const struct ConfigDev *cd;
+ unsigned int CyberKey = 0;
+ DPRINTK("ENTER\n");
- if (!(CyberKey = zorro_find(ZORRO_PROD_PHASE5_CYBERVISION64, 0, 0)))
+ if (!(CyberKey = zorro_find(ZORRO_PROD_PHASE5_CYBERVISION64, 0, 0))) {
+ DPRINTK("EXIT - zorro_find failed\n");
return;
+ }
cd = zorro_get_board (CyberKey);
zorro_config_board (CyberKey, 0);
board_addr = (unsigned long)cd->cd_BoardAddr;
+ board_size = (unsigned long)cd->cd_BoardSize;
+ DPRINTK("board_addr=%08lx\n", board_addr);
+ DPRINTK("board_size=%08lx\n", board_size);
+
+ cv64_mem = kernel_map (board_addr, board_size, KERNELMAP_NOCACHE_SER,
+ NULL);
+ cv64_regs = (volatile char *)(cv64_mem + 0x02000000);
+ cv64_fbmem = cv64_mem + 0x01400000;
+ DPRINTK("cv64_mem=%08lx cv64_regs=%08lx cv64_fbmem=%08lx\n",
+ cv64_mem, (long unsigned int)cv64_regs, cv64_fbmem);
+
+ CyberMem = cv64_fbmem;
+ CyberRegs = cv64_regs;
+ DPRINTK("CyberMem=%08lx CyberRegs=%08lx\n", CyberMem,
+ (long unsigned int)CyberRegs);
- /* This includes the video memory as well as the S3 register set */
- CyberMem = kernel_map (board_addr + 0x01400000, 0x01000000,
- KERNELMAP_NOCACHE_SER, NULL);
- CyberRegs = (char*) (CyberMem + 0x00c00000);
+#ifdef CYBERFBDEBUG
+ DPRINTK("Register state just after mapping memory\n");
+ cv64_dump();
+#endif
fbhw = &Cyber_switch;
@@ -1052,28 +1181,34 @@ __initfunc(void cyberfb_init(void))
cyberfb_set_disp(-1, &fb_info);
do_install_cmap(0, &fb_info);
- if (register_framebuffer(&fb_info) < 0)
+ if (register_framebuffer(&fb_info) < 0) {
+ DPRINTK("EXIT - register_framebuffer failed\n");
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;
+ DPRINTK("EXIT\n");
}
static int Cyberfb_switch(int con, struct fb_info *info)
{
+ DPRINTK("ENTER\n");
/* Do we have to save the colormap? */
- if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
- fbhw->getcolreg, info);
+ if (fb_display[currcon].cmap.len) {
+ fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg,
+ info);
+ }
do_fb_set_var(&fb_display[con].var, 1);
currcon = con;
/* Install new colormap */
do_install_cmap(con, info);
+ DPRINTK("EXIT\n");
return(0);
}
@@ -1087,17 +1222,20 @@ static int Cyberfb_switch(int con, struct fb_info *info)
static int Cyberfb_updatevar(int con, struct fb_info *info)
{
+ DPRINTK("Enter - Exit\n");
return(0);
}
/*
- * Blank the display.
- */
+ * Blank the display.
+ */
static void Cyberfb_blank(int blank, struct fb_info *info)
{
+ DPRINTK("Enter\n");
fbhw->blank(blank);
+ DPRINTK("Exit\n");
}
@@ -1109,14 +1247,17 @@ __initfunc(static int get_video_mode(const char *name))
{
int i;
+ DPRINTK("ENTER\n");
for (i = 0; i < NUM_TOTAL_MODES; i++) {
if (!strcmp(name, cyberfb_predefined[i].name)) {
cyberfb_default = cyberfb_predefined[i].var;
+ DPRINTK("EXIT - Matched predefined mode\n");
return(i);
}
}
/* ++Andre: set cyberfb default mode */
cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
+ DPRINTK("EXIT - Use default cyber8 mode\n");
return(0);
}
@@ -1129,45 +1270,56 @@ __initfunc(static int get_video_mode(const char *name))
static void fbcon_cyber8_bmove(struct display *p, int sy, int sx, int dy,
int dx, int height, int width)
{
- sx *= 8; dx *= 8; width *= 8;
- Cyber_BitBLT((u_short)sx, (u_short)(sy*p->fontheight), (u_short)dx,
- (u_short)(dy*p->fontheight), (u_short)width,
- (u_short)(height*p->fontheight), (u_short)S3_NEW);
+ DPRINTK("ENTER\n");
+ sx *= 8; dx *= 8; width *= 8;
+ Cyber_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
+ (u_short)(dy*fontheight(p)), (u_short)width,
+ (u_short)(height*fontheight(p)), (u_short)S3_NEW);
+ DPRINTK("EXIT\n");
}
static void fbcon_cyber8_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
- unsigned char bg;
-
- sx *= 8; width *= 8;
- bg = attr_bgcol_ec(p,conp);
- Cyber_RectFill((u_short)sx,
- (u_short)(sy*p->fontheight),
- (u_short)width,
- (u_short)(height*p->fontheight),
- (u_short)S3_NEW,
- (u_short)bg);
+ unsigned char bg;
+
+ DPRINTK("ENTER\n");
+ sx *= 8; width *= 8;
+ bg = attr_bgcol_ec(p,conp);
+ Cyber_RectFill((u_short)sx,
+ (u_short)(sy*fontheight(p)),
+ (u_short)width,
+ (u_short)(height*fontheight(p)),
+ (u_short)S3_NEW,
+ (u_short)bg);
+ DPRINTK("EXIT\n");
}
static void fbcon_cyber8_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
- Cyber_WaitBlit();
- fbcon_cfb8_putc(conp, p, c, yy, xx);
+ DPRINTK("ENTER\n");
+ Cyber_WaitBlit();
+ fbcon_cfb8_putc(conp, p, c, yy, xx);
+ DPRINTK("EXIT\n");
}
static void fbcon_cyber8_putcs(struct vc_data *conp, struct display *p,
- const unsigned short *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);
+ DPRINTK("ENTER\n");
+ Cyber_WaitBlit();
+ fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
+ DPRINTK("EXIT\n");
}
static void fbcon_cyber8_revc(struct display *p, int xx, int yy)
{
- Cyber_WaitBlit();
- fbcon_cfb8_revc(p, xx, yy);
+ DPRINTK("ENTER\n");
+ Cyber_WaitBlit();
+ fbcon_cfb8_revc(p, xx, yy);
+ DPRINTK("EXIT\n");
}
static struct display_switch fbcon_cyber8 = {
@@ -1193,3 +1345,1125 @@ void cleanup_module(void)
/* TODO: clean up ... */
}
#endif /* MODULE */
+
+/*
+ *
+ * Low level initialization routines for the CyberVision64 graphics card
+ *
+ * Most of the following code is from cvision_core.c
+ *
+ */
+
+#define MAXPIXELCLOCK 135000000 /* safety */
+
+#ifdef CV_AGGRESSIVE_TIMING
+long cv64_memclk = 55000000;
+#else
+long cv64_memclk = 50000000;
+#endif
+
+/*********************/
+
+static unsigned char clocks[]={
+ 0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
+ 0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
+ 0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
+ 0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
+ 0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
+ 0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
+ 0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
+ 0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
+ 0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
+ 0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
+ 0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
+ 0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
+ 0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
+ 0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
+ 0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
+ 0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
+ 0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
+ 0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
+ 0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
+ 0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
+ 0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
+ 0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
+ 0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
+ 0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
+ 0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
+ 0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
+ 0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
+ 0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
+ 0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
+ 0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
+ 0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
+ 0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
+ 0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
+ 0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
+ 0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
+ 0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
+ 0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
+ 0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
+ 0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
+ 0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
+ 0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
+ 0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
+ 0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
+ 0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
+ 0x13, 0x1, 0x13, 0x1, 0x7d, 0x27, 0x4c, 0x9,
+ 0x37, 0x22, 0x5b, 0xb, 0x71, 0x26, 0x5c, 0xb,
+ 0x6b, 0xd, 0x47, 0x23, 0x14, 0x1, 0x4f, 0x9,
+ 0x23, 0x3, 0x75, 0x26, 0x7d, 0xf, 0x1c, 0x2,
+ 0x51, 0x9, 0x59, 0x24, 0x61, 0xb, 0x69, 0x25,
+ 0x79, 0x26, 0x34, 0x5, 0x1d, 0x2, 0x6b, 0x25,
+ 0x54, 0x9, 0x35, 0x5, 0x45, 0x7, 0x6d, 0x25,
+ 0x7d, 0x26, 0x16, 0x1, 0x7f, 0x26, 0x77, 0xd,
+ 0x4f, 0x23, 0x78, 0xd, 0x2f, 0x21, 0x27, 0x3,
+ 0x1f, 0x2, 0x59, 0x9, 0x6a, 0xb, 0x73, 0x25,
+ 0x6b, 0xb, 0x63, 0x24, 0x5b, 0x9, 0x20, 0x2,
+ 0x7e, 0xd, 0x4b, 0x7, 0x65, 0x24, 0x43, 0x22,
+ 0x18, 0x1, 0x6f, 0xb, 0x5e, 0x9, 0x70, 0xb,
+ 0x2a, 0x3, 0x33, 0x4, 0x45, 0x6, 0x60, 0x9,
+ 0x7b, 0xc, 0x19, 0x1, 0x19, 0x1, 0x7d, 0xc,
+ 0x74, 0xb, 0x50, 0x7, 0x75, 0xb, 0x63, 0x9,
+ 0x51, 0x7, 0x23, 0x2, 0x3f, 0x5, 0x1a, 0x1,
+ 0x65, 0x9, 0x2d, 0x3, 0x40, 0x5, 0x0, 0x0,
+};
+
+/* Console colors */
+unsigned char cvconscolors[16][3] = { /* background, foreground, hilite */
+ /* R G B */
+ {0x30, 0x30, 0x30},
+ {0x00, 0x00, 0x00},
+ {0x80, 0x00, 0x00},
+ {0x00, 0x80, 0x00},
+ {0x00, 0x00, 0x80},
+ {0x80, 0x80, 0x00},
+ {0x00, 0x80, 0x80},
+ {0x80, 0x00, 0x80},
+ {0xff, 0xff, 0xff},
+ {0x40, 0x40, 0x40},
+ {0xff, 0x00, 0x00},
+ {0x00, 0xff, 0x00},
+ {0x00, 0x00, 0xff},
+ {0xff, 0xff, 0x00},
+ {0x00, 0xff, 0xff},
+ {0x00, 0x00, 0xff}
+};
+
+/* -------------------- Hardware specific routines ------------------------- */
+#if 0
+/* ARB Generates 100 usec delay */
+inline void __delay (unsigned long usecs)
+{
+ int k;
+
+ for (k = 0; k < 1000; k++) {
+ asm volatile ("nop");
+ }
+}
+#endif
+
+/* Wait while Graphics Engine is busy */
+inline void GfxBusyWait (volatile caddr_t board)
+{
+ int test;
+ DPRINTK("ENTER\n");
+
+ do {
+ test = vgar16 (board, ECR_GP_STAT);
+ asm volatile ("nop");
+ } while (test & (1 << 9));
+ DPRINTK("EXIT\n");
+}
+
+/* Wait for any of the 8 Trio32 FIFOs to be free */
+inline void GfxFifoWait (volatile caddr_t board)
+{
+ int test;
+ DPRINTK("ENTER\n");
+
+ do {
+ test = vgar16 (board, ECR_GP_STAT);
+ } while (test & 0x0f);
+ DPRINTK("EXIT\n");
+}
+
+/* Read Attribute Controller Register=idx */
+inline unsigned char RAttr (volatile caddr_t board, short idx)
+{
+ vgaw (board, ACT_ADDRESS_W, idx);
+ udelay(100);
+ /* __delay (0); */
+ return (vgar (board, ACT_ADDRESS_R));
+}
+
+/* Read Sequencer Register=idx */
+inline unsigned char RSeq (volatile caddr_t board, short idx)
+{
+ vgaw (board, SEQ_ADDRESS, idx);
+ return (vgar (board, SEQ_ADDRESS_R));
+}
+
+/* Read CRT Controller Register=idx */
+inline unsigned char RCrt (volatile caddr_t board, short idx)
+{
+ vgaw (board, CRT_ADDRESS, idx);
+ return (vgar (board, CRT_ADDRESS_R));
+}
+
+/* Read Graphics Controller Register=idx */
+inline unsigned char RGfx (volatile caddr_t board, short idx)
+{
+ vgaw (board, GCT_ADDRESS, idx);
+ return (vgar (board, GCT_ADDRESS_R));
+}
+
+/*
+ * Special wakeup/passthrough registers on graphics boards
+ */
+
+inline void cv64_write_port (unsigned short bits,
+ volatile unsigned char *board)
+{
+ volatile unsigned char *addr;
+ static unsigned char cvportbits = 0; /* Mirror port bits here */
+ DPRINTK("ENTER\n");
+
+ addr = board + 0x40001;
+ if (bits & 0x8000) {
+ cvportbits |= bits & 0xff; /* Set bits */
+ DPRINTK("Set bits: %04x\n", bits);
+ } else {
+ bits = bits & 0xff;
+ bits = (~bits) & 0xff;
+ cvportbits &= bits; /* Clear bits */
+ DPRINTK("Clear bits: %04x\n", bits);
+ }
+
+ *addr = cvportbits;
+ DPRINTK("EXIT\n");
+}
+
+/*
+ * Monitor switch on CyberVision board
+ *
+ * toggle:
+ * 0 = CyberVision Signal
+ * 1 = Amiga Signal
+ * board = board addr
+ *
+ */
+inline void cvscreen (int toggle, volatile unsigned char *board)
+{
+ DPRINTK("ENTER\n");
+ if (toggle == 1) {
+ DPRINTK("Show Amiga video\n");
+ cv64_write_port (0x10, board);
+ } else {
+ DPRINTK("Show CyberVision video\n");
+ cv64_write_port (0x8010, board);
+ }
+ DPRINTK("EXIT\n");
+}
+
+/* Control screen display */
+/* toggle: 0 = on, 1 = off */
+/* board = registerbase */
+inline void gfx_on_off (int toggle, volatile unsigned char *board)
+{
+ int r;
+ DPRINTK("ENTER\n");
+
+ toggle &= 0x1;
+ toggle = toggle << 5;
+ DPRINTK("Turn display %s\n", (toggle ? "off" : "on"));
+
+ r = (int) RSeq ((volatile caddr_t) board, SEQ_ID_CLOCKING_MODE);
+ r &= 0xdf; /* Set bit 5 to 0 */
+
+ WSeq (board, SEQ_ID_CLOCKING_MODE, r | toggle);
+ DPRINTK("EXIT\n");
+}
+
+/*
+ * Computes M, N, and R values from
+ * given input frequency. It uses a table of
+ * precomputed values, to keep CPU time low.
+ *
+ * The return value consist of:
+ * lower byte: Bits 4-0: N Divider Value
+ * Bits 5-6: R Value for e.g. SR10 or SR12
+ * higher byte: Bits 0-6: M divider value for e.g. SR11 or SR13
+ */
+static unsigned short cv64_compute_clock(unsigned long freq)
+{
+ static unsigned char *mnr, *save; /* M, N + R vals */
+ unsigned long work_freq, r;
+ unsigned short erg;
+ long diff, d2;
+
+ DPRINTK("ENTER\n");
+ if (freq < 12500000 || freq > MAXPIXELCLOCK) {
+ printk("CV64 driver: Illegal clock frequency %ld, using 25MHz\n",
+ freq);
+ freq = 25000000;
+ }
+ DPRINTK("Freq = %ld\n", freq);
+ mnr = clocks; /* there the vals are stored */
+ d2 = 0x7fffffff;
+
+ while (*mnr) { /* mnr vals are 0-terminated */
+ work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
+
+ r = (mnr[1] >> 5) & 0x03;
+ if (r != 0) {
+ work_freq = work_freq >> r; /* r is the freq divider */
+ }
+
+ work_freq *= 0x3E8; /* 2nd part of OSC */
+
+ diff = abs(freq - work_freq);
+
+ if (d2 >= diff) {
+ d2 = diff;
+ /* In save are the vals for minimal diff */
+ save = mnr;
+ }
+ mnr += 2;
+ }
+ erg = *((unsigned short *)save);
+
+ DPRINTK("EXIT\n");
+ return (erg);
+}
+
+static int cv_has_4mb (volatile caddr_t fb)
+{
+ volatile unsigned long *tr, *tw;
+ DPRINTK("ENTER\n");
+
+ /* write patterns in memory and test if they can be read */
+ tw = (volatile unsigned long *) fb;
+ tr = (volatile unsigned long *) (fb + 0x02000000);
+
+ *tw = 0x87654321;
+
+ if (*tr != 0x87654321) {
+ DPRINTK("EXIT - <4MB\n");
+ return (0);
+ }
+
+ /* upper memory region */
+ tw = (volatile unsigned long *) (fb + 0x00200000);
+ tr = (volatile unsigned long *) (fb + 0x02200000);
+
+ *tw = 0x87654321;
+
+ if (*tr != 0x87654321) {
+ DPRINTK("EXIT - <4MB\n");
+ return (0);
+ }
+
+ *tw = 0xAAAAAAAA;
+
+ if (*tr != 0xAAAAAAAA) {
+ DPRINTK("EXIT - <4MB\n");
+ return (0);
+ }
+
+ *tw = 0x55555555;
+
+ if (*tr != 0x55555555) {
+ DPRINTK("EXIT - <4MB\n");
+ return (0);
+ }
+
+ DPRINTK("EXIT\n");
+ return (1);
+}
+
+static void cv64_board_init (void)
+{
+ int i;
+ unsigned char test;
+ unsigned int clockpar;
+
+ DPRINTK("ENTER\n");
+
+ /*
+ * Special CyberVision 64 board operations
+ */
+ /* Reset board */
+ for (i = 0; i < 6; i++) {
+ cv64_write_port (0xff, (volatile unsigned char *) cv64_mem);
+ }
+ /* Return to operational mode */
+ cv64_write_port (0x8004, (volatile unsigned char *) cv64_mem);
+
+ /*
+ * Generic (?) S3 chip wakeup
+ */
+ /* Disable I/O & memory decoders, video in setup mode */
+ vgaw (cv64_regs, SREG_VIDEO_SUBS_ENABLE, 0x10);
+ /* Video responds to cmds, addrs & data */
+ vgaw (cv64_regs, SREG_OPTION_SELECT, 0x1);
+ /* Enable I/O & memory decoders, video in operational mode */
+ vgaw (cv64_regs, SREG_VIDEO_SUBS_ENABLE, 0x8);
+ /* VGA color emulation, enable cpu access to display mem */
+ vgaw (cv64_regs, GREG_MISC_OUTPUT_W, 0x03);
+ /* Unlock S3 VGA regs */
+ WCrt (cv64_regs, CRT_ID_REGISTER_LOCK_1, 0x48);
+ /* Unlock system control & extension registers */
+ WCrt (cv64_regs, CRT_ID_REGISTER_LOCK_2, 0xA5);
+/* GRF - Enable interrupts */
+ /* Enable enhanced regs access, Ready cntl 0 wait states */
+ test = RCrt (cv64_regs, CRT_ID_SYSTEM_CONFIG);
+ test = test | 0x01; /* enable enhaced register access */
+ test = test & 0xEF; /* clear bit 4, 0 wait state */
+ WCrt (cv64_regs, CRT_ID_SYSTEM_CONFIG, test);
+ /*
+ * bit 0=1: Enable enhaced mode functions
+ * bit 2=0: Enhanced mode 8+ bits/pixel
+ * bit 4=1: Enable linear addressing
+ * bit 5=1: Enable MMIO
+ */
+ vgaw (cv64_regs, ECR_ADV_FUNC_CNTL, 0x31);
+ /*
+ * bit 0=1: Color emulation
+ * bit 1=1: Enable CPU access to display memory
+ * bit 5=1: Select high 64K memory page
+ */
+/* GRF - 0xE3 */
+ vgaw (cv64_regs, GREG_MISC_OUTPUT_W, 0x23);
+
+ /* Cpu base addr */
+ WCrt (cv64_regs, CRT_ID_EXT_SYS_CNTL_4, 0x0);
+
+ /* Reset. This does nothing on Trio, but standard VGA practice */
+ /* WSeq (cv64_regs, SEQ_ID_RESET, 0x03); */
+ /* Character clocks 8 dots wide */
+ WSeq (cv64_regs, SEQ_ID_CLOCKING_MODE, 0x01);
+ /* Enable cpu write to all color planes */
+ WSeq (cv64_regs, SEQ_ID_MAP_MASK, 0x0F);
+ /* Font table in 1st 8k of plane 2, font A=B disables swtich */
+ WSeq (cv64_regs, SEQ_ID_CHAR_MAP_SELECT, 0x0);
+ /* Allow mem access to 256kb */
+ WSeq (cv64_regs, SEQ_ID_MEMORY_MODE, 0x2);
+ /* Unlock S3 extensions to VGA Sequencer regs */
+ WSeq (cv64_regs, SEQ_ID_UNLOCK_EXT, 0x6);
+
+ /* Enable 4MB fast page mode */
+ test = RSeq (cv64_regs, SEQ_ID_BUS_REQ_CNTL);
+ test = test | 1 << 6;
+ WSeq (cv64_regs, SEQ_ID_BUS_REQ_CNTL, test);
+
+ /* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */
+ WSeq (cv64_regs, SEQ_ID_RAMDAC_CNTL, 0xC0);
+
+ /* Clear immediate clock load bit */
+ test = RSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2);
+ test = test & 0xDF;
+ /* If > 55MHz, enable 2 cycle memory write */
+ if (cv64_memclk >= 55000000) {
+ test |= 0x80;
+ }
+ WSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2, test);
+
+ /* Set MCLK value */
+ clockpar = cv64_compute_clock (cv64_memclk);
+ test = (clockpar & 0xFF00) >> 8;
+ WSeq (cv64_regs, SEQ_ID_MCLK_HI, test);
+ test = clockpar & 0xFF;
+ WSeq (cv64_regs, SEQ_ID_MCLK_LO, test);
+
+ /* Chip rev specific: Not in my Trio manual!!! */
+ if (RCrt (cv64_regs, CRT_ID_REVISION) == 0x10)
+ WSeq (cv64_regs, SEQ_ID_MORE_MAGIC, test);
+
+ /* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */
+
+ /* Set DCLK value */
+ WSeq (cv64_regs, SEQ_ID_DCLK_HI, 0x13);
+ WSeq (cv64_regs, SEQ_ID_DCLK_LO, 0x41);
+
+ /* Load DCLK (and MCLK?) immediately */
+ test = RSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2);
+ test = test | 0x22;
+ WSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2, test);
+
+ /* Enable loading of DCLK */
+ test = vgar (cv64_regs, GREG_MISC_OUTPUT_R);
+ test = test | 0x0C;
+ vgaw (cv64_regs, GREG_MISC_OUTPUT_W, test);
+
+ /* Turn off immediate xCLK load */
+ WSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2, 0x2);
+
+ /* Horizontal character clock counts */
+ /* 8 LSB of 9 bits = total line - 5 */
+ WCrt (cv64_regs, CRT_ID_HOR_TOTAL, 0x5F);
+ /* Active display line */
+ WCrt (cv64_regs, CRT_ID_HOR_DISP_ENA_END, 0x4F);
+ /* Blank assertion start */
+ WCrt (cv64_regs, CRT_ID_START_HOR_BLANK, 0x50);
+ /* Blank assertion end */
+ WCrt (cv64_regs, CRT_ID_END_HOR_BLANK, 0x82);
+ /* HSYNC assertion start */
+ WCrt (cv64_regs, CRT_ID_START_HOR_RETR, 0x54);
+ /* HSYNC assertion end */
+ WCrt (cv64_regs, CRT_ID_END_HOR_RETR, 0x80);
+ WCrt (cv64_regs, CRT_ID_VER_TOTAL, 0xBF);
+ WCrt (cv64_regs, CRT_ID_OVERFLOW, 0x1F);
+ WCrt (cv64_regs, CRT_ID_PRESET_ROW_SCAN, 0x0);
+ WCrt (cv64_regs, CRT_ID_MAX_SCAN_LINE, 0x40);
+ WCrt (cv64_regs, CRT_ID_CURSOR_START, 0x00);
+ WCrt (cv64_regs, CRT_ID_CURSOR_END, 0x00);
+ WCrt (cv64_regs, CRT_ID_START_ADDR_HIGH, 0x00);
+ WCrt (cv64_regs, CRT_ID_START_ADDR_LOW, 0x00);
+ WCrt (cv64_regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
+ WCrt (cv64_regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
+ WCrt (cv64_regs, CRT_ID_START_VER_RETR, 0x9C);
+ WCrt (cv64_regs, CRT_ID_END_VER_RETR, 0x0E);
+ WCrt (cv64_regs, CRT_ID_VER_DISP_ENA_END, 0x8F);
+ WCrt (cv64_regs, CRT_ID_SCREEN_OFFSET, 0x50);
+ WCrt (cv64_regs, CRT_ID_UNDERLINE_LOC, 0x00);
+ WCrt (cv64_regs, CRT_ID_START_VER_BLANK, 0x96);
+ WCrt (cv64_regs, CRT_ID_END_VER_BLANK, 0xB9);
+ WCrt (cv64_regs, CRT_ID_MODE_CONTROL, 0xE3);
+ WCrt (cv64_regs, CRT_ID_LINE_COMPARE, 0xFF);
+ WCrt (cv64_regs, CRT_ID_BACKWAD_COMP_3, 0x10); /* FIFO enabled */
+ WCrt (cv64_regs, CRT_ID_MISC_1, 0x35);
+ WCrt (cv64_regs, CRT_ID_DISPLAY_FIFO, 0x5A);
+ WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_2, 0x70);
+ WCrt (cv64_regs, CRT_ID_LAW_POS_LO, 0x40);
+ WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_3, 0xFF);
+
+ WGfx (cv64_regs, GCT_ID_SET_RESET, 0x0);
+ WGfx (cv64_regs, GCT_ID_ENABLE_SET_RESET, 0x0);
+ WGfx (cv64_regs, GCT_ID_COLOR_COMPARE, 0x0);
+ WGfx (cv64_regs, GCT_ID_DATA_ROTATE, 0x0);
+ WGfx (cv64_regs, GCT_ID_READ_MAP_SELECT, 0x0);
+ WGfx (cv64_regs, GCT_ID_GRAPHICS_MODE, 0x40);
+ WGfx (cv64_regs, GCT_ID_MISC, 0x01);
+ WGfx (cv64_regs, GCT_ID_COLOR_XCARE, 0x0F);
+ WGfx (cv64_regs, GCT_ID_BITMASK, 0xFF);
+
+ /* Colors for text mode */
+ for (i = 0; i < 0xf; i++)
+ WAttr (cv64_regs, i, i);
+
+ WAttr (cv64_regs, ACT_ID_ATTR_MODE_CNTL, 0x41);
+ WAttr (cv64_regs, ACT_ID_OVERSCAN_COLOR, 0x01);
+ WAttr (cv64_regs, ACT_ID_COLOR_PLANE_ENA, 0x0F);
+ WAttr (cv64_regs, ACT_ID_HOR_PEL_PANNING, 0x0);
+ WAttr (cv64_regs, ACT_ID_COLOR_SELECT, 0x0);
+
+ vgaw (cv64_regs, VDAC_MASK, 0xFF);
+
+ *((unsigned long *) (cv64_regs + ECR_FRGD_COLOR)) = 0xFF;
+ *((unsigned long *) (cv64_regs + ECR_BKGD_COLOR)) = 0;
+
+ /* Colors initially set to grayscale */
+
+ vgaw (cv64_regs, VDAC_ADDRESS_W, 0);
+ for (i = 255; i >= 0; i--) {
+ vgaw (cv64_regs, VDAC_DATA, i);
+ vgaw (cv64_regs, VDAC_DATA, i);
+ vgaw (cv64_regs, VDAC_DATA, i);
+ }
+
+ /* GFx hardware cursor off */
+ WCrt (cv64_regs, CRT_ID_HWGC_MODE, 0x00);
+
+ /* Set first to 4MB, so test will work */
+ WCrt (cv64_regs, CRT_ID_LAW_CNTL, 0x13);
+ /* Find "correct" size of fbmem of Z3 board */
+ if (cv_has_4mb ((volatile caddr_t) cv64_fbmem)) {
+ cv64_size = 1024 * 1024 * 4;
+ WCrt (cv64_regs, CRT_ID_LAW_CNTL, 0x13);
+ DPRINTK("4MB board\n");
+ } else {
+ cv64_size = 1024 * 1024 * 2;
+ WCrt (cv64_regs, CRT_ID_LAW_CNTL, 0x12);
+ DPRINTK("2MB board\n");
+ }
+
+ /* Initialize graphics engine */
+ Cyber_WaitBlit();
+ /* GfxBusyWait (cv64_regs); */
+ vgaw16 (cv64_regs, ECR_FRGD_MIX, 0x27);
+ vgaw16 (cv64_regs, ECR_BKGD_MIX, 0x07);
+ vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x1000);
+ udelay(200);
+ /* __delay (200000); */
+ vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x2000);
+ Cyber_WaitBlit();
+ /* GfxBusyWait (cv64_regs); */
+ vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x3FFF);
+ Cyber_WaitBlit();
+ /* GfxBusyWait (cv64_regs); */
+ udelay(200);
+ /* __delay (200000); */
+ vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x4FFF);
+ Cyber_WaitBlit();
+ /* GfxBusyWait (cv64_regs); */
+ vgaw16 (cv64_regs, ECR_BITPLANE_WRITE_MASK, ~0);
+ Cyber_WaitBlit();
+ /* GfxBusyWait (cv64_regs); */
+ vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0xE000);
+ vgaw16 (cv64_regs, ECR_CURRENT_Y_POS2, 0x00);
+ vgaw16 (cv64_regs, ECR_CURRENT_X_POS2, 0x00);
+ vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0xA000);
+ vgaw16 (cv64_regs, ECR_DEST_Y__AX_STEP, 0x00);
+ vgaw16 (cv64_regs, ECR_DEST_Y2__AX_STEP2, 0x00);
+ vgaw16 (cv64_regs, ECR_DEST_X__DIA_STEP, 0x00);
+ vgaw16 (cv64_regs, ECR_DEST_X2__DIA_STEP2, 0x00);
+ vgaw16 (cv64_regs, ECR_SHORT_STROKE, 0x00);
+ vgaw16 (cv64_regs, ECR_DRAW_CMD, 0x01);
+
+ Cyber_WaitBlit();
+ /* GfxBusyWait (cv64_regs); */
+
+ vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x4FFF);
+ vgaw16 (cv64_regs, ECR_BKGD_COLOR, 0x01);
+ vgaw16 (cv64_regs, ECR_FRGD_COLOR, 0x00);
+
+
+ /* Enable video display (set bit 5) */
+/* ARB - Would also seem to write to AR13.
+ * May want to use parts of WAttr to set JUST bit 5
+ */
+ WAttr (cv64_regs, 0x33, 0);
+
+/* GRF - function code ended here */
+
+ /* Turn gfx on again */
+ gfx_on_off (0, cv64_regs);
+
+ /* Pass-through */
+ cvscreen (0, (volatile unsigned char *) cv64_mem);
+
+ DPRINTK("EXIT\n");
+}
+
+static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
+{
+ int fx, fy;
+ unsigned short mnr;
+ unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT;
+ char LACE, DBLSCAN, TEXT, CONSOLE;
+ int cr50, sr15, sr18, clock_mode, test;
+ int m, n;
+ int tfillm, temptym;
+ int hmul;
+
+ /* ---------------- */
+ int xres, hfront, hsync, hback;
+ int yres, vfront, vsync, vback;
+ int bpp;
+ float freq_f;
+ long freq;
+ /* ---------------- */
+
+ DPRINTK("ENTER\n");
+ TEXT = 0; /* if depth == 4 */
+ CONSOLE = 0; /* mode num == 255 (console) */
+ fx = fy = 8; /* force 8x8 font */
+
+/* GRF - Disable interrupts */
+
+ gfx_on_off (1, cv64_regs);
+
+ switch (video_mode->bits_per_pixel) {
+ case 15:
+ case 16:
+ hmul = 2;
+ break;
+
+ default:
+ hmul = 1;
+ break;
+ }
+
+ bpp = video_mode->bits_per_pixel;
+ xres = video_mode->xres;
+ hfront = video_mode->right_margin;
+ hsync = video_mode->hsync_len;
+ hback = video_mode->left_margin;
+
+ LACE = 0;
+ DBLSCAN = 0;
+
+ if (video_mode->vmode & FB_VMODE_DOUBLE) {
+ yres = video_mode->yres * 2;
+ vfront = video_mode->lower_margin * 2;
+ vsync = video_mode->vsync_len * 2;
+ vback = video_mode->upper_margin * 2;
+ DBLSCAN = 1;
+ } else if (video_mode->vmode & FB_VMODE_INTERLACED) {
+ yres = (video_mode->yres + 1) / 2;
+ vfront = (video_mode->lower_margin + 1) / 2;
+ vsync = (video_mode->vsync_len + 1) / 2;
+ vback = (video_mode->upper_margin + 1) / 2;
+ LACE = 1;
+ } else {
+ yres = video_mode->yres;
+ vfront = video_mode->lower_margin;
+ vsync = video_mode->vsync_len;
+ vback = video_mode->upper_margin;
+ }
+
+ /* ARB Dropping custom setup method from cvision.c */
+#if 0
+ if (cvision_custom_mode) {
+ HBS = hbs / 8 * hmul;
+ HBE = hbe / 8 * hmul;
+ HSS = hss / 8 * hmul;
+ HSE = hse / 8 * hmul;
+ HT = ht / 8 * hmul - 5;
+
+ VBS = vbs - 1;
+ VSS = vss;
+ VSE = vse;
+ VBE = vbe;
+ VT = vt - 2;
+ } else {
+#else
+ {
+#endif
+ HBS = hmul * (xres / 8);
+ HBE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8) - 2);
+ HSS = hmul * ((xres/8) + (hfront/8) + 2);
+ HSE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + 1);
+ HT = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8));
+
+ VBS = yres;
+ VBE = yres + vfront + vsync + vback - 2;
+ VSS = yres + vfront - 1;
+ VSE = yres + vfront + vsync - 1;
+ VT = yres + vfront + vsync + vback - 2;
+ }
+
+ vgaw (cv64_regs, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31));
+
+ if (TEXT)
+ HDE = ((video_mode->xres + fx - 1) / fx) - 1;
+ else
+ HDE = (video_mode->xres + 3) * hmul / 8 - 1;
+
+ VDE = video_mode->yres - 1;
+
+ WCrt (cv64_regs, CRT_ID_HWGC_MODE, 0x00);
+ WCrt (cv64_regs, CRT_ID_EXT_DAC_CNTL, 0x00);
+
+ WSeq (cv64_regs, SEQ_ID_MEMORY_MODE,
+ (TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x0e);
+ WGfx (cv64_regs, GCT_ID_READ_MAP_SELECT, 0x00);
+ WSeq (cv64_regs, SEQ_ID_MAP_MASK,
+ (video_mode->bits_per_pixel == 1) ? 0x01 : 0xFF);
+ WSeq (cv64_regs, SEQ_ID_CHAR_MAP_SELECT, 0x00);
+
+ /* cv64_compute_clock accepts arguments in Hz */
+ /* pixclock is in ps ... convert to Hz */
+
+ freq_f = (1.0 / (float) video_mode->pixclock) * 1000000000;
+ freq = ((long) freq_f) * 1000;
+
+ mnr = cv64_compute_clock (freq);
+ WSeq (cv64_regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
+ WSeq (cv64_regs, SEQ_ID_DCLK_LO, (mnr & 0xFF));
+
+ /* Load display parameters into board */
+ WCrt (cv64_regs, CRT_ID_EXT_HOR_OVF,
+ ((HT & 0x100) ? 0x01 : 0x00) |
+ ((HDE & 0x100) ? 0x02 : 0x00) |
+ ((HBS & 0x100) ? 0x04 : 0x00) |
+ /* ((HBE & 0x40) ? 0x08 : 0x00) | */
+ ((HSS & 0x100) ? 0x10 : 0x00) |
+ /* ((HSE & 0x20) ? 0x20 : 0x00) | */
+ (((HT-5) & 0x100) ? 0x40 : 0x00)
+ );
+
+ WCrt (cv64_regs, CRT_ID_EXT_VER_OVF,
+ 0x40 |
+ ((VT & 0x400) ? 0x01 : 0x00) |
+ ((VDE & 0x400) ? 0x02 : 0x00) |
+ ((VBS & 0x400) ? 0x04 : 0x00) |
+ ((VSS & 0x400) ? 0x10 : 0x00)
+ );
+
+ WCrt (cv64_regs, CRT_ID_HOR_TOTAL, HT);
+ WCrt (cv64_regs, CRT_ID_DISPLAY_FIFO, HT - 5);
+ WCrt (cv64_regs, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
+ WCrt (cv64_regs, CRT_ID_START_HOR_BLANK, HBS);
+ WCrt (cv64_regs, CRT_ID_END_HOR_BLANK, ((HBE & 0x1F) | 0x80));
+ WCrt (cv64_regs, CRT_ID_START_HOR_RETR, HSS);
+ WCrt (cv64_regs, CRT_ID_END_HOR_RETR,
+ (HSE & 0x1F) |
+ ((HBE & 0x20) ? 0x80 : 0x00)
+ );
+ WCrt (cv64_regs, CRT_ID_VER_TOTAL, VT);
+ WCrt (cv64_regs, CRT_ID_OVERFLOW,
+ 0x10 |
+ ((VT & 0x100) ? 0x01 : 0x00) |
+ ((VDE & 0x100) ? 0x02 : 0x00) |
+ ((VSS & 0x100) ? 0x04 : 0x00) |
+ ((VBS & 0x100) ? 0x08 : 0x00) |
+ ((VT & 0x200) ? 0x20 : 0x00) |
+ ((VDE & 0x200) ? 0x40 : 0x00) |
+ ((VSS & 0x200) ? 0x80 : 0x00)
+ );
+ WCrt (cv64_regs, CRT_ID_MAX_SCAN_LINE,
+ 0x40 |
+ (DBLSCAN ? 0x80 : 0x00) |
+ ((VBS & 0x200) ? 0x20 : 0x00) |
+ (TEXT ? ((fy - 1) & 0x1F) : 0x00)
+ );
+
+ WCrt (cv64_regs, CRT_ID_MODE_CONTROL, 0xE3);
+
+ /* Text cursor */
+
+ if (TEXT) {
+#if 1
+ WCrt (cv64_regs, CRT_ID_CURSOR_START, (fy & 0x1f) - 2);
+ WCrt (cv64_regs, CRT_ID_CURSOR_END, (fy & 0x1F) - 1);
+#else
+ WCrt (cv64_regs, CRT_ID_CURSOR_START, 0x00);
+ WCrt (cv64_regs, CRT_ID_CURSOR_END, fy & 0x1F);
+#endif
+ WCrt (cv64_regs, CRT_ID_UNDERLINE_LOC, (fy - 1) & 0x1F);
+ WCrt (cv64_regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
+ WCrt (cv64_regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
+ }
+
+ WCrt (cv64_regs, CRT_ID_START_ADDR_HIGH, 0x00);
+ WCrt (cv64_regs, CRT_ID_START_ADDR_LOW, 0x00);
+ WCrt (cv64_regs, CRT_ID_START_VER_RETR, VSS);
+ WCrt (cv64_regs, CRT_ID_END_VER_RETR, (VSE & 0x0F));
+ WCrt (cv64_regs, CRT_ID_VER_DISP_ENA_END, VDE);
+ WCrt (cv64_regs, CRT_ID_START_VER_BLANK, VBS);
+ WCrt (cv64_regs, CRT_ID_END_VER_BLANK, VBE);
+ WCrt (cv64_regs, CRT_ID_LINE_COMPARE, 0xFF);
+ WCrt (cv64_regs, CRT_ID_LACE_RETR_START, HT / 2);
+ WCrt (cv64_regs, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
+ WGfx (cv64_regs, GCT_ID_GRAPHICS_MODE,
+ ((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x00 : 0x40));
+ WGfx (cv64_regs, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
+ WSeq (cv64_regs, SEQ_ID_MEMORY_MODE,
+ ((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x02));
+
+ vgaw (cv64_regs, VDAC_MASK, 0xFF);
+
+ /* Blank border */
+ test = RCrt (cv64_regs, CRT_ID_BACKWAD_COMP_2);
+ WCrt (cv64_regs, CRT_ID_BACKWAD_COMP_2, (test | 0x20));
+
+ sr15 = RSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2);
+ sr15 &= 0xEF;
+ sr18 = RSeq (cv64_regs, SEQ_ID_RAMDAC_CNTL);
+ sr18 &= 0x7F;
+ clock_mode = 0x00;
+ cr50 = 0x00;
+
+ test = RCrt (cv64_regs, CRT_ID_EXT_MISC_CNTL_2);
+ test &= 0xD;
+
+ /* Clear roxxler byte-swapping... */
+ cv64_write_port (0x0040, (volatile unsigned char *) cv64_mem);
+ cv64_write_port (0x0020, (volatile unsigned char *) cv64_mem);
+
+ switch (video_mode->bits_per_pixel) {
+ case 1:
+ case 4: /* text */
+ HDE = video_mode->xres / 16;
+ break;
+
+ case 8:
+ if (freq > 80000000) {
+ clock_mode = 0x10 | 0x02;
+ sr15 |= 0x10;
+ sr18 |= 0x80;
+ }
+ HDE = video_mode->xres / 8;
+ cr50 |= 0x00;
+ break;
+
+ case 15:
+ cv64_write_port (0x8020, (volatile unsigned char *) cv64_mem);
+ clock_mode = 0x30;
+ HDE = video_mode->xres / 4;
+ cr50 |= 0x10;
+ break;
+
+ case 16:
+ cv64_write_port (0x8020, (volatile unsigned char *) cv64_mem);
+ clock_mode = 0x50;
+ HDE = video_mode->xres / 4;
+ cr50 |= 0x10;
+ break;
+
+ case 24:
+ case 32:
+ cv64_write_port (0x8040, (volatile unsigned char *) cv64_mem);
+ clock_mode = 0xD0;
+ HDE = video_mode->xres / 2;
+ cr50 |= 0x30;
+ break;
+ }
+
+ WCrt (cv64_regs, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
+ WSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2, sr15);
+ WSeq (cv64_regs, SEQ_ID_RAMDAC_CNTL, sr18);
+ WCrt (cv64_regs, CRT_ID_SCREEN_OFFSET, HDE);
+
+ WCrt (cv64_regs, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
+
+ test = RCrt (cv64_regs, CRT_ID_EXT_SYS_CNTL_2);
+ test &= ~0x30;
+ test |= (HDE >> 4) & 0x30;
+ WCrt (cv64_regs, CRT_ID_EXT_SYS_CNTL_2, test);
+
+ /* Set up graphics engine */
+ switch (video_mode->xres) {
+ case 1024:
+ cr50 |= 0x00;
+ break;
+
+ case 640:
+ cr50 |= 0x40;
+ break;
+
+ case 800:
+ cr50 |= 0x80;
+ break;
+
+ case 1280:
+ cr50 |= 0xC0;
+ break;
+
+ case 1152:
+ cr50 |= 0x01;
+ break;
+
+ case 1600:
+ cr50 |= 0x81;
+ break;
+
+ default: /* XXX */
+ break;
+ }
+
+ WCrt (cv64_regs, CRT_ID_EXT_SYS_CNTL_1, cr50);
+
+ udelay(100);
+ /* __delay (100000); */
+ WAttr (cv64_regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
+ udelay(100);
+ /* __delay (100000); */
+ WAttr (cv64_regs, ACT_ID_COLOR_PLANE_ENA,
+ (video_mode->bits_per_pixel == 1) ? 0x01 : 0x0F);
+ udelay(100);
+ /* __delay (100000); */
+
+ tfillm = (96 * (cv64_memclk / 1000)) / 240000;
+
+ switch (video_mode->bits_per_pixel) {
+ case 32:
+ case 24:
+ temptym = (24 * (cv64_memclk / 1000)) / (freq / 1000);
+ break;
+ case 15:
+ case 16:
+ temptym = (48 * (cv64_memclk / 1000)) / (freq / 1000);
+ break;
+ case 4:
+ temptym = (192 * (cv64_memclk / 1000)) / (freq / 1000);
+ break;
+ default:
+ temptym = (96 * (cv64_memclk / 1000)) / (freq / 1000);
+ break;
+ }
+
+ m = (temptym - tfillm - 9) / 2;
+ if (m < 0)
+ m = 0;
+ m = (m & 0x1F) << 3;
+ if (m < 0x18)
+ m = 0x18;
+ n = 0xFF;
+
+ WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_2, m);
+ WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_3, n);
+ udelay(10);
+ /* __delay (10000); */
+
+ /* Text initialization */
+
+ if (TEXT) {
+ /* Do text initialization here ! */
+ }
+
+ if (CONSOLE) {
+ int i;
+ vgaw (cv64_regs, VDAC_ADDRESS_W, 0);
+ for (i = 0; i < 4; i++) {
+ vgaw (cv64_regs, VDAC_DATA, cvconscolors [i][0]);
+ vgaw (cv64_regs, VDAC_DATA, cvconscolors [i][1]);
+ vgaw (cv64_regs, VDAC_DATA, cvconscolors [i][2]);
+ }
+ }
+
+ WAttr (cv64_regs, 0x33, 0);
+
+ /* Turn gfx on again */
+ gfx_on_off (0, (volatile unsigned char *) cv64_regs);
+
+ /* Pass-through */
+ cvscreen (0, (volatile unsigned char *) cv64_mem);
+
+DPRINTK("EXIT\n");
+}
+
+void cvision_bitblt (u_short sx, u_short sy, u_short dx, u_short dy,
+ u_short w, u_short h)
+{
+ unsigned short drawdir = 0;
+
+ DPRINTK("ENTER\n");
+ if (sx > dx) {
+ drawdir |= 1 << 5;
+ } else {
+ sx += w - 1;
+ dx += w - 1;
+ }
+
+ if (sy > dy) {
+ drawdir |= 1 << 7;
+ } else {
+ sy += h - 1;
+ dy += h - 1;
+ }
+
+ Cyber_WaitBlit();
+ /* GfxBusyWait (cv64_regs); */
+ vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0xA000);
+ vgaw16 (cv64_regs, ECR_BKGD_MIX, 0x7);
+ vgaw16 (cv64_regs, ECR_FRGD_MIX, 0x67);
+ vgaw16 (cv64_regs, ECR_BKGD_COLOR, 0x0);
+ vgaw16 (cv64_regs, ECR_FRGD_COLOR, 0x1);
+ vgaw16 (cv64_regs, ECR_BITPLANE_READ_MASK, 0x1);
+ vgaw16 (cv64_regs, ECR_BITPLANE_WRITE_MASK, 0xFFF);
+ vgaw16 (cv64_regs, ECR_CURRENT_Y_POS, sy);
+ vgaw16 (cv64_regs, ECR_CURRENT_X_POS, sx);
+ vgaw16 (cv64_regs, ECR_DEST_Y__AX_STEP, dy);
+ vgaw16 (cv64_regs, ECR_DEST_X__DIA_STEP, dx);
+ vgaw16 (cv64_regs, ECR_READ_REG_DATA, h - 1);
+ vgaw16 (cv64_regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
+ vgaw16 (cv64_regs, ECR_DRAW_CMD, 0xC051 | drawdir);
+ DPRINTK("EXIT\n");
+}
+
+void cvision_clear (u_short dx, u_short dy, u_short w, u_short h, u_short bg)
+{
+ DPRINTK("ENTER\n");
+ Cyber_WaitBlit();
+ /* GfxBusyWait (cv64_regs); */
+ vgaw16 (cv64_regs, ECR_FRGD_MIX, 0x0027);
+ vgaw16 (cv64_regs, ECR_FRGD_COLOR, bg);
+ vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0xA000);
+ vgaw16 (cv64_regs, ECR_CURRENT_Y_POS, dy);
+ vgaw16 (cv64_regs, ECR_CURRENT_X_POS, dx);
+ vgaw16 (cv64_regs, ECR_READ_REG_DATA, h - 1);
+ vgaw16 (cv64_regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
+ vgaw16 (cv64_regs, ECR_DRAW_CMD, 0x40B1);
+ DPRINTK("EXIT\n");
+}
+
+#ifdef CYBERFBDEBUG
+/*
+ * Dump internal settings of CyberVision board
+ */
+static void cv64_dump (void)
+{
+ DPRINTK("ENTER\n");
+ /* Dump the VGA setup values */
+ *(CyberRegs + S3_CRTC_ADR) = 0x00;
+ DPRINTK("CR00 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x01;
+ DPRINTK("CR01 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x02;
+ DPRINTK("CR02 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x03;
+ DPRINTK("CR03 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x04;
+ DPRINTK("CR04 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x05;
+ DPRINTK("CR05 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x06;
+ DPRINTK("CR06 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x07;
+ DPRINTK("CR07 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x08;
+ DPRINTK("CR08 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x09;
+ DPRINTK("CR09 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x10;
+ DPRINTK("CR10 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x11;
+ DPRINTK("CR11 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x12;
+ DPRINTK("CR12 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x13;
+ DPRINTK("CR13 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x15;
+ DPRINTK("CR15 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x16;
+ DPRINTK("CR16 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x36;
+ DPRINTK("CR36 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x37;
+ DPRINTK("CR37 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x42;
+ DPRINTK("CR42 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x43;
+ DPRINTK("CR43 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x50;
+ DPRINTK("CR50 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x51;
+ DPRINTK("CR51 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x53;
+ DPRINTK("CR53 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x58;
+ DPRINTK("CR58 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x59;
+ DPRINTK("CR59 = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x5A;
+ DPRINTK("CR5A = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x5D;
+ DPRINTK("CR5D = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ *(CyberRegs + S3_CRTC_ADR) = 0x5E;
+ DPRINTK("CR5E = %x\n", *(CyberRegs + S3_CRTC_DATA));
+ DPRINTK("MISC = %x\n", *(CyberRegs + GREG_MISC_OUTPUT_R));
+ *(CyberRegs + SEQ_ADDRESS) = 0x01;
+ DPRINTK("SR01 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
+ *(CyberRegs + SEQ_ADDRESS) = 0x02;
+ DPRINTK("SR02 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
+ *(CyberRegs + SEQ_ADDRESS) = 0x03;
+ DPRINTK("SR03 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
+ *(CyberRegs + SEQ_ADDRESS) = 0x09;
+ DPRINTK("SR09 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
+ *(CyberRegs + SEQ_ADDRESS) = 0x10;
+ DPRINTK("SR10 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
+ *(CyberRegs + SEQ_ADDRESS) = 0x11;
+ DPRINTK("SR11 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
+ *(CyberRegs + SEQ_ADDRESS) = 0x12;
+ DPRINTK("SR12 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
+ *(CyberRegs + SEQ_ADDRESS) = 0x13;
+ DPRINTK("SR13 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
+ *(CyberRegs + SEQ_ADDRESS) = 0x15;
+ DPRINTK("SR15 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
+
+ return;
+}
+#endif
diff --git a/drivers/video/cyberfb.h b/drivers/video/cyberfb.h
new file mode 100644
index 000000000..232bc6857
--- /dev/null
+++ b/drivers/video/cyberfb.h
@@ -0,0 +1,444 @@
+/*
+ * linux/arch/m68k/console/cvision.h -- CyberVision64 definitions for the
+ * text console driver.
+ *
+ * Copyright (c) 1998 Alan Bair
+ *
+ * This file is based on the initial port to Linux of grf_cvreg.h:
+ *
+ * Copyright (c) 1997 Antonio Santos
+ *
+ * The original work is from the NetBSD CyberVision 64 framebuffer driver
+ * and support files (grf_cv.c, grf_cvreg.h, ite_cv.c):
+ * Permission to use the source of this driver was obtained from the
+ * author Michael Teske by Alan Bair.
+ *
+ * Copyright (c) 1995 Michael Teske
+ *
+ * History:
+ *
+ *
+ *
+ * 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.
+ */
+
+/* s3 commands */
+#define S3_BITBLT 0xc011
+#define S3_TWOPOINTLINE 0x2811
+#define S3_FILLEDRECT 0x40b1
+
+#define S3_FIFO_EMPTY 0x0400
+#define S3_HDW_BUSY 0x0200
+
+/* Enhanced register mapping (MMIO mode) */
+
+#define S3_READ_SEL 0xbee8 /* offset f */
+#define S3_MULT_MISC 0xbee8 /* offset e */
+#define S3_ERR_TERM 0x92e8
+#define S3_FRGD_COLOR 0xa6e8
+#define S3_BKGD_COLOR 0xa2e8
+#define S3_PIXEL_CNTL 0xbee8 /* offset a */
+#define S3_FRGD_MIX 0xbae8
+#define S3_BKGD_MIX 0xb6e8
+#define S3_CUR_Y 0x82e8
+#define S3_CUR_X 0x86e8
+#define S3_DESTY_AXSTP 0x8ae8
+#define S3_DESTX_DIASTP 0x8ee8
+#define S3_MIN_AXIS_PCNT 0xbee8 /* offset 0 */
+#define S3_MAJ_AXIS_PCNT 0x96e8
+#define S3_CMD 0x9ae8
+#define S3_GP_STAT 0x9ae8
+#define S3_ADVFUNC_CNTL 0x4ae8
+#define S3_WRT_MASK 0xaae8
+#define S3_RD_MASK 0xaee8
+
+/* Enhanced register mapping (Packed MMIO mode, write only) */
+#define S3_ALT_CURXY 0x8100
+#define S3_ALT_CURXY2 0x8104
+#define S3_ALT_STEP 0x8108
+#define S3_ALT_STEP2 0x810c
+#define S3_ALT_ERR 0x8110
+#define S3_ALT_CMD 0x8118
+#define S3_ALT_MIX 0x8134
+#define S3_ALT_PCNT 0x8148
+#define S3_ALT_PAT 0x8168
+
+/* Drawing modes */
+#define S3_NOTCUR 0x0000
+#define S3_LOGICALZERO 0x0001
+#define S3_LOGICALONE 0x0002
+#define S3_LEAVEASIS 0x0003
+#define S3_NOTNEW 0x0004
+#define S3_CURXORNEW 0x0005
+#define S3_NOT_CURXORNEW 0x0006
+#define S3_NEW 0x0007
+#define S3_NOTCURORNOTNEW 0x0008
+#define S3_CURORNOTNEW 0x0009
+#define S3_NOTCURORNEW 0x000a
+#define S3_CURORNEW 0x000b
+#define S3_CURANDNEW 0x000c
+#define S3_NOTCURANDNEW 0x000d
+#define S3_CURANDNOTNEW 0x000e
+#define S3_NOTCURANDNOTNEW 0x000f
+
+#define S3_CRTC_ADR 0x03d4
+#define S3_CRTC_DATA 0x03d5
+
+#define S3_REG_LOCK2 0x39
+#define S3_HGC_MODE 0x45
+
+#define S3_HWGC_ORGX_H 0x46
+#define S3_HWGC_ORGX_L 0x47
+#define S3_HWGC_ORGY_H 0x48
+#define S3_HWGC_ORGY_L 0x49
+#define S3_HWGC_DX 0x4e
+#define S3_HWGC_DY 0x4f
+
+#define S3_LAW_CTL 0x58
+
+/**************************************************/
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif /* !min */
+
+#ifndef max
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#endif /* !max */
+
+/* support for a BitBlt operation. The op-codes are identical
+ to X11 GCs */
+#define GRFBBOPclear 0x0 /* 0 */
+#define GRFBBOPand 0x1 /* src AND dst */
+#define GRFBBOPandReverse 0x2 /* src AND NOT dst */
+#define GRFBBOPcopy 0x3 /* src */
+#define GRFBBOPandInverted 0x4 /* NOT src AND dst */
+#define GRFBBOPnoop 0x5 /* dst */
+#define GRFBBOPxor 0x6 /* src XOR dst */
+#define GRFBBOPor 0x7 /* src OR dst */
+#define GRFBBOPnor 0x8 /* NOT src AND NOT dst */
+#define GRFBBOPequiv 0x9 /* NOT src XOR dst */
+#define GRFBBOPinvert 0xa /* NOT dst */
+#define GRFBBOPorReverse 0xb /* src OR NOT dst */
+#define GRFBBOPcopyInverted 0xc /* NOT src */
+#define GRFBBOPorInverted 0xd /* NOT src OR dst */
+#define GRFBBOPnand 0xe /* NOT src OR NOT dst */
+#define GRFBBOPset 0xf /* 1 */
+
+
+/* Read VGA register */
+#define vgar(ba, reg) (*(((volatile caddr_t)ba)+reg))
+
+/* Write VGA register */
+#define vgaw(ba, reg, val) \
+*(((volatile caddr_t)ba)+reg) = ((val) & 0xff)
+
+/* Read 16 Bit VGA register */
+#define vgar16(ba, reg) ( *((unsigned short *) (((volatile caddr_t)ba)+reg)) )
+
+/* Write 16 Bit VGA register */
+#define vgaw16(ba, reg, val) \
+*((unsigned short *) (((volatile caddr_t)ba)+reg)) = val
+
+/* Read 32 Bit VGA register */
+#define vgar32(ba, reg) ( *((unsigned long *) (((volatile caddr_t)ba)+reg)) )
+
+/* Write 32 Bit VGA register */
+#define vgaw32(ba, reg, val) \
+ *((unsigned long *) (((volatile caddr_t)ba)+reg)) = val
+
+/*
+ * Defines for the used register addresses (mw)
+ *
+ * NOTE: There are some registers that have different addresses when
+ * in mono or color mode. We only support color mode, and thus
+ * some addresses won't work in mono-mode!
+ *
+ * General and VGA-registers taken from retina driver. Fixed a few
+ * bugs in it. (SR and GR read address is Port + 1, NOT Port)
+ *
+ */
+
+/* General Registers: */
+#define GREG_MISC_OUTPUT_R 0x03CC
+#define GREG_MISC_OUTPUT_W 0x03C2
+#define GREG_FEATURE_CONTROL_R 0x03CA
+#define GREG_FEATURE_CONTROL_W 0x03DA
+#define GREG_INPUT_STATUS0_R 0x03C2
+#define GREG_INPUT_STATUS1_R 0x03DA
+
+/* Setup Registers: */
+#define SREG_OPTION_SELECT 0x0102
+#define SREG_VIDEO_SUBS_ENABLE 0x46E8
+
+/* Attribute Controller: */
+#define ACT_ADDRESS 0x03C0
+#define ACT_ADDRESS_R 0x03C1
+#define ACT_ADDRESS_W 0x03C0
+#define ACT_ADDRESS_RESET 0x03DA
+#define ACT_ID_PALETTE0 0x00
+#define ACT_ID_PALETTE1 0x01
+#define ACT_ID_PALETTE2 0x02
+#define ACT_ID_PALETTE3 0x03
+#define ACT_ID_PALETTE4 0x04
+#define ACT_ID_PALETTE5 0x05
+#define ACT_ID_PALETTE6 0x06
+#define ACT_ID_PALETTE7 0x07
+#define ACT_ID_PALETTE8 0x08
+#define ACT_ID_PALETTE9 0x09
+#define ACT_ID_PALETTE10 0x0A
+#define ACT_ID_PALETTE11 0x0B
+#define ACT_ID_PALETTE12 0x0C
+#define ACT_ID_PALETTE13 0x0D
+#define ACT_ID_PALETTE14 0x0E
+#define ACT_ID_PALETTE15 0x0F
+#define ACT_ID_ATTR_MODE_CNTL 0x10
+#define ACT_ID_OVERSCAN_COLOR 0x11
+#define ACT_ID_COLOR_PLANE_ENA 0x12
+#define ACT_ID_HOR_PEL_PANNING 0x13
+#define ACT_ID_COLOR_SELECT 0x14
+
+/* Graphics Controller: */
+#define GCT_ADDRESS 0x03CE
+#define GCT_ADDRESS_R 0x03CF
+#define GCT_ADDRESS_W 0x03CF
+#define GCT_ID_SET_RESET 0x00
+#define GCT_ID_ENABLE_SET_RESET 0x01
+#define GCT_ID_COLOR_COMPARE 0x02
+#define GCT_ID_DATA_ROTATE 0x03
+#define GCT_ID_READ_MAP_SELECT 0x04
+#define GCT_ID_GRAPHICS_MODE 0x05
+#define GCT_ID_MISC 0x06
+#define GCT_ID_COLOR_XCARE 0x07
+#define GCT_ID_BITMASK 0x08
+
+/* Sequencer: */
+#define SEQ_ADDRESS 0x03C4
+#define SEQ_ADDRESS_R 0x03C5
+#define SEQ_ADDRESS_W 0x03C5
+#define SEQ_ID_RESET 0x00
+#define SEQ_ID_CLOCKING_MODE 0x01
+#define SEQ_ID_MAP_MASK 0x02
+#define SEQ_ID_CHAR_MAP_SELECT 0x03
+#define SEQ_ID_MEMORY_MODE 0x04
+#define SEQ_ID_UNKNOWN1 0x05
+#define SEQ_ID_UNKNOWN2 0x06
+#define SEQ_ID_UNKNOWN3 0x07
+/* S3 extensions */
+#define SEQ_ID_UNLOCK_EXT 0x08
+#define SEQ_ID_EXT_SEQ_REG9 0x09
+#define SEQ_ID_BUS_REQ_CNTL 0x0A
+#define SEQ_ID_EXT_MISC_SEQ 0x0B
+#define SEQ_ID_UNKNOWN4 0x0C
+#define SEQ_ID_EXT_SEQ 0x0D
+#define SEQ_ID_UNKNOWN5 0x0E
+#define SEQ_ID_UNKNOWN6 0x0F
+#define SEQ_ID_MCLK_LO 0x10
+#define SEQ_ID_MCLK_HI 0x11
+#define SEQ_ID_DCLK_LO 0x12
+#define SEQ_ID_DCLK_HI 0x13
+#define SEQ_ID_CLKSYN_CNTL_1 0x14
+#define SEQ_ID_CLKSYN_CNTL_2 0x15
+#define SEQ_ID_CLKSYN_TEST_HI 0x16 /* reserved for S3 testing of the */
+#define SEQ_ID_CLKSYN_TEST_LO 0x17 /* internal clock synthesizer */
+#define SEQ_ID_RAMDAC_CNTL 0x18
+#define SEQ_ID_MORE_MAGIC 0x1A
+
+/* CRT Controller: */
+#define CRT_ADDRESS 0x03D4
+#define CRT_ADDRESS_R 0x03D5
+#define CRT_ADDRESS_W 0x03D5
+#define CRT_ID_HOR_TOTAL 0x00
+#define CRT_ID_HOR_DISP_ENA_END 0x01
+#define CRT_ID_START_HOR_BLANK 0x02
+#define CRT_ID_END_HOR_BLANK 0x03
+#define CRT_ID_START_HOR_RETR 0x04
+#define CRT_ID_END_HOR_RETR 0x05
+#define CRT_ID_VER_TOTAL 0x06
+#define CRT_ID_OVERFLOW 0x07
+#define CRT_ID_PRESET_ROW_SCAN 0x08
+#define CRT_ID_MAX_SCAN_LINE 0x09
+#define CRT_ID_CURSOR_START 0x0A
+#define CRT_ID_CURSOR_END 0x0B
+#define CRT_ID_START_ADDR_HIGH 0x0C
+#define CRT_ID_START_ADDR_LOW 0x0D
+#define CRT_ID_CURSOR_LOC_HIGH 0x0E
+#define CRT_ID_CURSOR_LOC_LOW 0x0F
+#define CRT_ID_START_VER_RETR 0x10
+#define CRT_ID_END_VER_RETR 0x11
+#define CRT_ID_VER_DISP_ENA_END 0x12
+#define CRT_ID_SCREEN_OFFSET 0x13
+#define CRT_ID_UNDERLINE_LOC 0x14
+#define CRT_ID_START_VER_BLANK 0x15
+#define CRT_ID_END_VER_BLANK 0x16
+#define CRT_ID_MODE_CONTROL 0x17
+#define CRT_ID_LINE_COMPARE 0x18
+#define CRT_ID_GD_LATCH_RBACK 0x22
+#define CRT_ID_ACT_TOGGLE_RBACK 0x24
+#define CRT_ID_ACT_INDEX_RBACK 0x26
+/* S3 extensions: S3 VGA Registers */
+#define CRT_ID_DEVICE_HIGH 0x2D
+#define CRT_ID_DEVICE_LOW 0x2E
+#define CRT_ID_REVISION 0x2F
+#define CRT_ID_CHIP_ID_REV 0x30
+#define CRT_ID_MEMORY_CONF 0x31
+#define CRT_ID_BACKWAD_COMP_1 0x32
+#define CRT_ID_BACKWAD_COMP_2 0x33
+#define CRT_ID_BACKWAD_COMP_3 0x34
+#define CRT_ID_REGISTER_LOCK 0x35
+#define CRT_ID_CONFIG_1 0x36
+#define CRT_ID_CONFIG_2 0x37
+#define CRT_ID_REGISTER_LOCK_1 0x38
+#define CRT_ID_REGISTER_LOCK_2 0x39
+#define CRT_ID_MISC_1 0x3A
+#define CRT_ID_DISPLAY_FIFO 0x3B
+#define CRT_ID_LACE_RETR_START 0x3C
+/* S3 extensions: System Control Registers */
+#define CRT_ID_SYSTEM_CONFIG 0x40
+#define CRT_ID_BIOS_FLAG 0x41
+#define CRT_ID_LACE_CONTROL 0x42
+#define CRT_ID_EXT_MODE 0x43
+#define CRT_ID_HWGC_MODE 0x45 /* HWGC = Hardware Graphics Cursor */
+#define CRT_ID_HWGC_ORIGIN_X_HI 0x46
+#define CRT_ID_HWGC_ORIGIN_X_LO 0x47
+#define CRT_ID_HWGC_ORIGIN_Y_HI 0x48
+#define CRT_ID_HWGC_ORIGIN_Y_LO 0x49
+#define CRT_ID_HWGC_FG_STACK 0x4A
+#define CRT_ID_HWGC_BG_STACK 0x4B
+#define CRT_ID_HWGC_START_AD_HI 0x4C
+#define CRT_ID_HWGC_START_AD_LO 0x4D
+#define CRT_ID_HWGC_DSTART_X 0x4E
+#define CRT_ID_HWGC_DSTART_Y 0x4F
+/* S3 extensions: System Extension Registers */
+#define CRT_ID_EXT_SYS_CNTL_1 0x50
+#define CRT_ID_EXT_SYS_CNTL_2 0x51
+#define CRT_ID_EXT_BIOS_FLAG_1 0x52
+#define CRT_ID_EXT_MEM_CNTL_1 0x53
+#define CRT_ID_EXT_MEM_CNTL_2 0x54
+#define CRT_ID_EXT_DAC_CNTL 0x55
+#define CRT_ID_EX_SYNC_1 0x56
+#define CRT_ID_EX_SYNC_2 0x57
+#define CRT_ID_LAW_CNTL 0x58 /* LAW = Linear Address Window */
+#define CRT_ID_LAW_POS_HI 0x59
+#define CRT_ID_LAW_POS_LO 0x5A
+#define CRT_ID_GOUT_PORT 0x5C
+#define CRT_ID_EXT_HOR_OVF 0x5D
+#define CRT_ID_EXT_VER_OVF 0x5E
+#define CRT_ID_EXT_MEM_CNTL_3 0x60
+#define CRT_ID_EX_SYNC_3 0x63
+#define CRT_ID_EXT_MISC_CNTL 0x65
+#define CRT_ID_EXT_MISC_CNTL_1 0x66
+#define CRT_ID_EXT_MISC_CNTL_2 0x67
+#define CRT_ID_CONFIG_3 0x68
+#define CRT_ID_EXT_SYS_CNTL_3 0x69
+#define CRT_ID_EXT_SYS_CNTL_4 0x6A
+#define CRT_ID_EXT_BIOS_FLAG_3 0x6B
+#define CRT_ID_EXT_BIOS_FLAG_4 0x6C
+
+/* Enhanced Commands Registers: */
+#define ECR_SUBSYSTEM_STAT 0x42E8
+#define ECR_SUBSYSTEM_CNTL 0x42E8
+#define ECR_ADV_FUNC_CNTL 0x4AE8
+#define ECR_CURRENT_Y_POS 0x82E8
+#define ECR_CURRENT_Y_POS2 0x82EA /* Trio64 only */
+#define ECR_CURRENT_X_POS 0x86E8
+#define ECR_CURRENT_X_POS2 0x86EA /* Trio64 only */
+#define ECR_DEST_Y__AX_STEP 0x8AE8
+#define ECR_DEST_Y2__AX_STEP2 0x8AEA /* Trio64 only */
+#define ECR_DEST_X__DIA_STEP 0x8EE8
+#define ECR_DEST_X2__DIA_STEP2 0x8EEA /* Trio64 only */
+#define ECR_ERR_TERM 0x92E8
+#define ECR_ERR_TERM2 0x92EA /* Trio64 only */
+#define ECR_MAJ_AXIS_PIX_CNT 0x96E8
+#define ECR_MAJ_AXIS_PIX_CNT2 0x96EA /* Trio64 only */
+#define ECR_GP_STAT 0x9AE8 /* GP = Graphics Processor */
+#define ECR_DRAW_CMD 0x9AE8
+#define ECR_DRAW_CMD2 0x9AEA /* Trio64 only */
+#define ECR_SHORT_STROKE 0x9EE8
+#define ECR_BKGD_COLOR 0xA2E8 /* BKGD = Background */
+#define ECR_FRGD_COLOR 0xA6E8 /* FRGD = Foreground */
+#define ECR_BITPLANE_WRITE_MASK 0xAAE8
+#define ECR_BITPLANE_READ_MASK 0xAEE8
+#define ECR_COLOR_COMPARE 0xB2E8
+#define ECR_BKGD_MIX 0xB6E8
+#define ECR_FRGD_MIX 0xBAE8
+#define ECR_READ_REG_DATA 0xBEE8
+#define ECR_ID_MIN_AXIS_PIX_CNT 0x00
+#define ECR_ID_SCISSORS_TOP 0x01
+#define ECR_ID_SCISSORS_LEFT 0x02
+#define ECR_ID_SCISSORS_BUTTOM 0x03
+#define ECR_ID_SCISSORS_RIGHT 0x04
+#define ECR_ID_PIX_CNTL 0x0A
+#define ECR_ID_MULT_CNTL_MISC_2 0x0D
+#define ECR_ID_MULT_CNTL_MISC 0x0E
+#define ECR_ID_READ_SEL 0x0F
+#define ECR_PIX_TRANS 0xE2E8
+#define ECR_PIX_TRANS_EXT 0xE2EA
+#define ECR_PATTERN_Y 0xEAE8 /* Trio64 only */
+#define ECR_PATTERN_X 0xEAEA /* Trio64 only */
+
+
+/* Pass-through */
+#define PASS_ADDRESS 0x40001
+#define PASS_ADDRESS_W 0x40001
+
+/* Video DAC */
+#define VDAC_ADDRESS 0x03c8
+#define VDAC_ADDRESS_W 0x03c8
+#define VDAC_ADDRESS_R 0x03c7
+#define VDAC_STATE 0x03c7
+#define VDAC_DATA 0x03c9
+#define VDAC_MASK 0x03c6
+
+
+#define WGfx(ba, idx, val) \
+do { vgaw(ba, GCT_ADDRESS, idx); vgaw(ba, GCT_ADDRESS_W , val); } while (0)
+
+#define WSeq(ba, idx, val) \
+do { vgaw(ba, SEQ_ADDRESS, idx); vgaw(ba, SEQ_ADDRESS_W , val); } while (0)
+
+#define WCrt(ba, idx, val) \
+do { vgaw(ba, CRT_ADDRESS, idx); vgaw(ba, CRT_ADDRESS_W , val); } while (0)
+
+#define WAttr(ba, idx, val) \
+do { \
+ unsigned char tmp;\
+ tmp = vgar(ba, ACT_ADDRESS_RESET);\
+ vgaw(ba, ACT_ADDRESS_W, idx);\
+ vgaw(ba, ACT_ADDRESS_W, val);\
+} while (0)
+
+#define SetTextPlane(ba, m) \
+do { \
+ WGfx(ba, GCT_ID_READ_MAP_SELECT, m & 3 );\
+ WSeq(ba, SEQ_ID_MAP_MASK, (1 << (m & 3)));\
+} while (0)
+
+ /* --------------------------------- */
+ /* prototypes */
+ /* --------------------------------- */
+
+/* in cvision_core.c */
+inline void __delay(unsigned long usecs);
+inline void GfxBusyWait(volatile caddr_t board);
+inline void GfxFifoWait(volatile caddr_t board);
+inline unsigned char RAttr(volatile caddr_t board, short idx);
+inline unsigned char RSeq(volatile caddr_t board, short idx);
+inline unsigned char RCrt(volatile caddr_t board, short idx);
+inline unsigned char RGfx(volatile caddr_t board, short idx);
+inline void cv64_write_port(unsigned short bits,
+ volatile unsigned char *board);
+inline void cvscreen(int toggle, volatile unsigned char *board);
+inline void gfx_on_off(int toggle, volatile unsigned char *board);
+#if 0
+unsigned short cv64_compute_clock(unsigned long freq);
+int cv_has_4mb(volatile caddr_t fb);
+void cv64_board_init(void);
+void cv64_load_video_mode(struct fb_var_screeninfo *video_mode);
+#endif
+
+void cvision_bitblt(u_short sx, u_short sy, u_short dx, u_short dy, u_short w,
+ u_short h);
+void cvision_clear(u_short dx, u_short dy, u_short w, u_short h, u_short bg);
diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c
index 906554641..e0da396bf 100644
--- a/drivers/video/dnfb.c
+++ b/drivers/video/dnfb.c
@@ -14,7 +14,7 @@
#include <linux/fb.h>
#include <linux/module.h>
-#include "fbcon-mfb.h"
+#include <video/fbcon-mfb.h>
/* apollo video HW definitions */
@@ -306,7 +306,7 @@ static void dnfb_set_disp(int con, struct fb_info *info)
#ifdef FBCON_HAS_MFB
disp[con].dispsw = &fbcon_mfb;
#else
- disp[con].dispsw = NULL;
+ disp[con].dispsw = &fbcon_dummy;
#endif
}
@@ -321,6 +321,7 @@ void dnfb_init(void)
fb_info.blank=&dnfbcon_blank;
fb_info.node = -1;
fb_info.fbops = &dnfb_ops;
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
outb(RESET_CREG, AP_CONTROL_3A);
outw(0x0, AP_WRITE_ENABLE);
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
index d3e339e4f..5f1780bd8 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbcmap.c
@@ -31,10 +31,6 @@ static void memcpy_fs(int fsfromto, void *to, void *from, int len)
}
}
-#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7fff-(val))>>16)
-#define CNVT_FROMHW(val,width) (((width) ? ((((val)<<16)-(val)) / \
- ((1<<(width))-1)) : 0))
-
static u16 red2[] = {
0x0000, 0xaaaa
};
@@ -163,9 +159,10 @@ void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
* Get the colormap for a screen
*/
-int fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc,
+int fb_get_cmap(struct fb_cmap *cmap, int kspc,
int (*getcolreg)(u_int, u_int *, u_int *, u_int *, u_int *,
- struct fb_info *), struct fb_info *info)
+ struct fb_info *),
+ struct fb_info *info)
{
int i, start;
u16 *red, *green, *blue, *transp;
@@ -181,10 +178,6 @@ int fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc,
for (i = 0; i < cmap->len; i++) {
if (getcolreg(start++, &hred, &hgreen, &hblue, &htransp, info))
return 0;
- hred = CNVT_FROMHW(hred, var->red.length);
- hgreen = CNVT_FROMHW(hgreen, var->green.length);
- hblue = CNVT_FROMHW(hblue, var->blue.length);
- htransp = CNVT_FROMHW(htransp, var->transp.length);
if (kspc) {
*red = hred;
*green = hgreen;
@@ -212,9 +205,10 @@ int fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc,
* Set the colormap for a screen
*/
-int fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc,
+int fb_set_cmap(struct fb_cmap *cmap, int kspc,
int (*setcolreg)(u_int, u_int, u_int, u_int, u_int,
- struct fb_info *), struct fb_info *info)
+ struct fb_info *),
+ struct fb_info *info)
{
int i, start;
u16 *red, *green, *blue, *transp;
@@ -243,10 +237,6 @@ int fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc,
else
htransp = 0;
}
- hred = CNVT_TOHW(hred, var->red.length);
- hgreen = CNVT_TOHW(hgreen, var->green.length);
- hblue = CNVT_TOHW(hblue, var->blue.length);
- htransp = CNVT_TOHW(htransp, var->transp.length);
red++;
green++;
blue++;
diff --git a/drivers/video/fbcon-afb.c b/drivers/video/fbcon-afb.c
index a8c01d6a0..205c1347d 100644
--- a/drivers/video/fbcon-afb.c
+++ b/drivers/video/fbcon-afb.c
@@ -15,8 +15,8 @@
#include <linux/string.h>
#include <linux/fb.h>
-#include "fbcon.h"
-#include "fbcon-afb.h"
+#include <video/fbcon.h>
+#include <video/fbcon-afb.h>
/*
@@ -174,22 +174,22 @@ void fbcon_afb_bmove(struct display *p, int sy, int sx, int dy, int dx,
u_short i, j;
if (sx == 0 && dx == 0 && width == p->next_line) {
- src = p->screen_base+sy*p->fontheight*width;
- dest = p->screen_base+dy*p->fontheight*width;
+ src = p->screen_base+sy*fontheight(p)*width;
+ dest = p->screen_base+dy*fontheight(p)*width;
i = p->var.bits_per_pixel;
do {
- mymemmove(dest, src, height*p->fontheight*width);
+ mymemmove(dest, src, height*fontheight(p)*width);
src += p->next_plane;
dest += p->next_plane;
} while (--i);
} else if (dy <= sy) {
- src0 = p->screen_base+sy*p->fontheight*p->next_line+sx;
- dest0 = p->screen_base+dy*p->fontheight*p->next_line+dx;
+ src0 = p->screen_base+sy*fontheight(p)*p->next_line+sx;
+ dest0 = p->screen_base+dy*fontheight(p)*p->next_line+dx;
i = p->var.bits_per_pixel;
do {
src = src0;
dest = dest0;
- j = height*p->fontheight;
+ j = height*fontheight(p);
do {
mymemmove(dest, src, width);
src += p->next_line;
@@ -199,13 +199,13 @@ void fbcon_afb_bmove(struct display *p, int sy, int sx, int dy, int dx,
dest0 += p->next_plane;
} while (--i);
} else {
- src0 = p->screen_base+(sy+height)*p->fontheight*p->next_line+sx;
- dest0 = p->screen_base+(dy+height)*p->fontheight*p->next_line+dx;
+ src0 = p->screen_base+(sy+height)*fontheight(p)*p->next_line+sx;
+ dest0 = p->screen_base+(dy+height)*fontheight(p)*p->next_line+dx;
i = p->var.bits_per_pixel;
do {
src = src0;
dest = dest0;
- j = height*p->fontheight;
+ j = height*fontheight(p);
do {
src -= p->next_line;
dest -= p->next_line;
@@ -224,13 +224,13 @@ void fbcon_afb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
u_short i, j;
int bg;
- dest0 = p->screen_base+sy*p->fontheight*p->next_line+sx;
+ dest0 = p->screen_base+sy*fontheight(p)*p->next_line+sx;
bg = attr_bgcol_ec(p,conp);
i = p->var.bits_per_pixel;
do {
dest = dest0;
- j = height*p->fontheight;
+ j = height*fontheight(p);
do {
if (bg & 1)
mymemset(dest, width);
@@ -250,8 +250,8 @@ void fbcon_afb_putc(struct vc_data *conp, struct display *p, int c, int yy,
u_short i, j;
int fg, bg;
- dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx;
- cdat0 = p->fontdata+(c&p->charmask)*p->fontheight;
+ dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
+ cdat0 = p->fontdata+(c&p->charmask)*fontheight(p);
fg = attr_fgcol(p,c);
bg = attr_bgcol(p,c);
@@ -264,7 +264,7 @@ void fbcon_afb_putc(struct vc_data *conp, struct display *p, int c, int yy,
expand += 512;
if (fg & 1)
expand += 256;
- j = p->fontheight;
+ j = fontheight(p);
do {
*dest = expand[*cdat++];
dest += p->next_line;
@@ -289,7 +289,7 @@ void fbcon_afb_putcs(struct vc_data *conp, struct display *p,
u16 c1, c2, c3, c4;
int fg0, bg0, fg, bg;
- dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx;
+ dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
fg0 = attr_fgcol(p,*s);
bg0 = attr_bgcol(p,*s);
@@ -299,7 +299,7 @@ void fbcon_afb_putcs(struct vc_data *conp, struct display *p,
dest1 = dest0++;
xx++;
- cdat10 = p->fontdata+c1*p->fontheight;
+ cdat10 = p->fontdata+c1*fontheight(p);
fg = fg0;
bg = bg0;
@@ -312,7 +312,7 @@ void fbcon_afb_putcs(struct vc_data *conp, struct display *p,
expand += 512;
if (fg & 1)
expand += 256;
- j = p->fontheight;
+ j = fontheight(p);
do {
*dest = expand[*cdat1++];
dest += p->next_line;
@@ -328,10 +328,10 @@ void fbcon_afb_putcs(struct vc_data *conp, struct display *p,
c4 = s[3] & p->charmask;
dest1 = dest0;
- cdat10 = p->fontdata+c1*p->fontheight;
- cdat20 = p->fontdata+c2*p->fontheight;
- cdat30 = p->fontdata+c3*p->fontheight;
- cdat40 = p->fontdata+c4*p->fontheight;
+ cdat10 = p->fontdata+c1*fontheight(p);
+ cdat20 = p->fontdata+c2*fontheight(p);
+ cdat30 = p->fontdata+c3*fontheight(p);
+ cdat40 = p->fontdata+c4*fontheight(p);
fg = fg0;
bg = bg0;
@@ -347,7 +347,7 @@ void fbcon_afb_putcs(struct vc_data *conp, struct display *p,
expand += 512;
if (fg & 1)
expand += 256;
- j = p->fontheight;
+ j = fontheight(p);
do {
#if defined(__BIG_ENDIAN)
*(u32 *)dest = expand[*cdat1++]<<24 |
@@ -381,7 +381,7 @@ void fbcon_afb_revc(struct display *p, int xx, int yy)
u_short i, j;
int mask;
- dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx;
+ dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
mask = p->fgcol ^ p->bgcol;
/*
@@ -394,7 +394,7 @@ void fbcon_afb_revc(struct display *p, int xx, int yy)
do {
if (mask & 1) {
dest = dest0;
- j = p->fontheight;
+ j = fontheight(p);
do {
*dest = ~*dest;
dest += p->next_line;
diff --git a/drivers/video/fbcon-afb.h b/drivers/video/fbcon-afb.h
deleted file mode 100644
index c82d98c41..000000000
--- a/drivers/video/fbcon-afb.h
+++ /dev/null
@@ -1,27 +0,0 @@
- /*
- * 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,
- int height, int width);
-extern void fbcon_afb_clear(struct vc_data *conp, struct display *p, int sy,
- int sx, int height, int width);
-extern void fbcon_afb_putc(struct vc_data *conp, struct display *p, int c,
- int yy, int xx);
-extern void fbcon_afb_putcs(struct vc_data *conp, struct display *p,
- const 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 221fbc572..a05848f5b 100644
--- a/drivers/video/fbcon-cfb16.c
+++ b/drivers/video/fbcon-cfb16.c
@@ -9,23 +9,20 @@
* more details.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/fb.h>
-#include "fbcon.h"
-#include "fbcon-cfb16.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb16.h>
/*
* 16 bpp packed pixels
*/
-u16 fbcon_cfb16_cmap[16];
-
static u32 tab_cfb16[] = {
#if defined(__BIG_ENDIAN)
0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
@@ -45,28 +42,28 @@ void fbcon_cfb16_setup(struct display *p)
void fbcon_cfb16_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
- int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
+ int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
u8 *src, *dst;
- if (sx == 0 && dx == 0 && width * p->fontwidth * 2 == bytes) {
+ if (sx == 0 && dx == 0 && width * fontwidth(p) * 2 == bytes) {
mymemmove(p->screen_base + dy * linesize,
p->screen_base + sy * linesize,
height * linesize);
return;
}
- if (p->fontwidthlog) {
- sx <<= p->fontwidthlog+1;
- dx <<= p->fontwidthlog+1;
- width <<= p->fontwidthlog+1;
+ if (fontwidthlog(p)) {
+ sx <<= fontwidthlog(p)+1;
+ dx <<= fontwidthlog(p)+1;
+ width <<= fontwidthlog(p)+1;
} else {
- sx *= p->fontwidth*2;
- dx *= p->fontwidth*2;
- width *= p->fontwidth*2;
+ sx *= fontwidth(p)*2;
+ dx *= fontwidth(p)*2;
+ width *= fontwidth(p)*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--;) {
+ for (rows = height * fontheight(p); rows--;) {
mymemmove(dst, src, width);
src += bytes;
dst += bytes;
@@ -74,7 +71,7 @@ void fbcon_cfb16_bmove(struct display *p, int sy, int sx, int dy, int dx,
} else {
src = p->screen_base + (sy+height) * linesize + sx - bytes;
dst = p->screen_base + (dy+height) * linesize + dx - bytes;
- for (rows = height * p->fontheight; rows--;) {
+ for (rows = height * fontheight(p); rows--;) {
mymemmove(dst, src, width);
src -= bytes;
dst -= bytes;
@@ -82,36 +79,43 @@ void fbcon_cfb16_bmove(struct display *p, int sy, int sx, int dy, int dx,
}
}
+static inline void rectfill(u8 *dest, int width, int height, u32 data,
+ int linesize)
+{
+ int i;
+
+ data |= data<<16;
+
+ while (height-- > 0) {
+ u32 *p = (u32 *)dest;
+ for (i = 0; i < width/4; i++) {
+ *p++ = data;
+ *p++ = data;
+ }
+ if (width & 2)
+ *p++ = data;
+ if (width & 1)
+ *(u16 *)p = data;
+ dest += linesize;
+ }
+}
+
void fbcon_cfb16_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;
+ u8 *dest;
+ int bytes = p->next_line, lines = height * fontheight(p);
u32 bgx;
- dest = p->screen_base + sy * p->fontheight * bytes + sx * p->fontwidth * 2;
+ dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 2;
- bgx = fbcon_cfb16_cmap[attr_bgcol_ec(p, conp)];
- bgx |= (bgx << 16);
+ bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
- 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;
- dest += 8;
- }
- 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 *= fontwidth(p)/4;
+ if (width * 8 == bytes)
+ rectfill(dest, lines * width * 4, 1, bgx, bytes);
+ else
+ rectfill(dest, width * 4, lines, bgx, bytes);
}
void fbcon_cfb16_putc(struct vc_data *conp, struct display *p, int c, int yy,
@@ -121,38 +125,32 @@ void fbcon_cfb16_putc(struct vc_data *conp, struct display *p, int c, int yy,
int bytes = p->next_line, rows;
u32 eorx, fgx, bgx;
- dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 2;
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
- fgx = fbcon_cfb16_cmap[attr_fgcol(p, c)];
- bgx = fbcon_cfb16_cmap[attr_bgcol(p, c)];
+ fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
+ bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
fgx |= (fgx << 16);
bgx |= (bgx << 16);
eorx = fgx ^ bgx;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
- switch (p->fontwidth) {
+ switch (fontwidth(p)) {
case 4:
case 8:
-#endif
- cdat = p->fontdata + (c & p->charmask) * p->fontheight;
- for (rows = p->fontheight; rows--; dest += bytes) {
+ cdat = p->fontdata + (c & p->charmask) * fontheight(p);
+ for (rows = fontheight(p); 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
- {
+ if (fontwidth(p) == 8) {
((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) {
+ cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1);
+ for (rows = fontheight(p); rows--; dest += bytes) {
bits = *cdat++;
((u32 *)dest)[0] = (tab_cfb16[bits >> 6] & eorx) ^ bgx;
((u32 *)dest)[1] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx;
@@ -161,14 +159,13 @@ void fbcon_cfb16_putc(struct vc_data *conp, struct display *p, int c, int yy,
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) {
+ if (fontwidth(p) == 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,
@@ -179,44 +176,37 @@ void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p,
int rows, bytes = p->next_line;
u32 eorx, fgx, bgx;
- 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)];
+ dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
+ fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, *s)];
+ bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, *s)];
fgx |= (fgx << 16);
bgx |= (bgx << 16);
eorx = fgx ^ bgx;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
- switch (p->fontwidth) {
+ switch (fontwidth(p)) {
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) {
+ cdat = p->fontdata + c * fontheight(p);
+ for (rows = fontheight(p), 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
- {
-
+ if (fontwidth(p) == 8) {
((u32 *)dest)[2] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx;
((u32 *)dest)[3] = (tab_cfb16[bits & 3] & eorx) ^ bgx;
}
}
- dest0 += p->fontwidth*2;;
+ dest0 += fontwidth(p)*2;;
}
-#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) {
+ cdat = p->fontdata + (c * fontheight(p) << 1);
+ for (rows = fontheight(p), 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;
@@ -225,16 +215,15 @@ void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p,
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) {
+ if (fontwidth(p) == 16) {
((u32 *)dest)[6] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx;
((u32 *)dest)[7] = (tab_cfb16[bits & 3] & eorx) ^ bgx;
}
}
- dest0 += p->fontwidth*2;
+ dest0 += fontwidth(p)*2;
}
break;
}
-#endif
}
void fbcon_cfb16_revc(struct display *p, int xx, int yy)
@@ -242,13 +231,9 @@ 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 * 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) {
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p)*2;
+ for (rows = fontheight(p); rows--; dest += bytes) {
+ switch (fontwidth(p)) {
case 16:
((u32 *)dest)[6] ^= 0xffffffff; ((u32 *)dest)[7] ^= 0xffffffff;
/* FALL THROUGH */
@@ -261,42 +246,27 @@ void fbcon_cfb16_revc(struct display *p, int xx, int yy)
case 4:
((u32 *)dest)[0] ^= 0xffffffff; ((u32 *)dest)[1] ^= 0xffffffff;
}
-#endif
}
}
-void fbcon_cfb16_clear_margins(struct vc_data *conp, struct display *p)
+void fbcon_cfb16_clear_margins(struct vc_data *conp, struct display *p,
+ int bottom_only)
{
- 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;
+ unsigned int right_start = conp->vc_cols*fontwidth(p);
+ unsigned int bottom_start = conp->vc_rows*fontheight(p);
+ unsigned int right_width, bottom_width;
- bgx = fbcon_cfb16_cmap[attr_bgcol_ec(p, conp)];
- bgx |= (bgx << 16);
+ bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
- 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;
- }
+ if (!bottom_only && (right_width = p->var.xres-right_start))
+ rectfill(p->screen_base+right_start*2, right_width,
+ p->var.yres_virtual, bgx, bytes);
+ if ((bottom_width = p->var.yres-bottom_start))
+ rectfill(p->screen_base+(p->var.yoffset+bottom_start)*bytes,
+ right_start, bottom_width, bgx, bytes);
}
@@ -333,4 +303,4 @@ EXPORT_SYMBOL(fbcon_cfb16_clear);
EXPORT_SYMBOL(fbcon_cfb16_putc);
EXPORT_SYMBOL(fbcon_cfb16_putcs);
EXPORT_SYMBOL(fbcon_cfb16_revc);
-EXPORT_SYMBOL(fbcon_cfb16_cmap);
+EXPORT_SYMBOL(fbcon_cfb16_clear_margins);
diff --git a/drivers/video/fbcon-cfb16.h b/drivers/video/fbcon-cfb16.h
deleted file mode 100644
index ebff9bcb9..000000000
--- a/drivers/video/fbcon-cfb16.h
+++ /dev/null
@@ -1,29 +0,0 @@
- /*
- * 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);
-extern void fbcon_cfb16_bmove(struct display *p, int sy, int sx, int dy,
- int dx, int height, int width);
-extern void fbcon_cfb16_clear(struct vc_data *conp, struct display *p, int sy,
- int sx, int height, int width);
-extern void fbcon_cfb16_putc(struct vc_data *conp, struct display *p, int c,
- int yy, int xx);
-extern void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p,
- const 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 60bed6275..e25fadaae 100644
--- a/drivers/video/fbcon-cfb2.c
+++ b/drivers/video/fbcon-cfb2.c
@@ -16,8 +16,8 @@
#include <linux/string.h>
#include <linux/fb.h>
-#include "fbcon.h"
-#include "fbcon-cfb2.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb2.h>
/*
@@ -57,7 +57,7 @@ void fbcon_cfb2_setup(struct display *p)
void fbcon_cfb2_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
- int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
+ int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
u8 *src,*dst;
if (sx == 0 && dx == 0 && width * 2 == bytes) {
@@ -69,7 +69,7 @@ void fbcon_cfb2_bmove(struct display *p, int sy, int sx, int dy, int dx,
if (dy < sy || (dy == sy && dx < sx)) {
src = p->screen_base + sy * linesize + sx * 2;
dst = p->screen_base + dy * linesize + dx * 2;
- for (rows = height * p->fontheight ; rows-- ;) {
+ for (rows = height * fontheight(p) ; rows-- ;) {
mymemmove(dst, src, width * 2);
src += bytes;
dst += bytes;
@@ -80,7 +80,7 @@ void fbcon_cfb2_bmove(struct display *p, int sy, int sx, int dy, int dx,
- bytes;
dst = p->screen_base + (dy+height) * linesize + dx * 2
- bytes;
- for (rows = height * p->fontheight ; rows-- ;) {
+ for (rows = height * fontheight(p) ; rows-- ;) {
mymemmove(dst, src, width * 2);
src -= bytes;
dst -= bytes;
@@ -93,10 +93,10 @@ void fbcon_cfb2_clear(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width)
{
u8 *dest0,*dest;
- int bytes=p->next_line,lines=height * p->fontheight, rows, i;
+ int bytes=p->next_line,lines=height * fontheight(p), rows, i;
u32 bgx;
- dest = p->screen_base + sy * p->fontheight * bytes + sx * 2;
+ dest = p->screen_base + sy * fontheight(p) * bytes + sx * 2;
bgx=attr_bgcol_ec(p,conp);
bgx |= (bgx << 2); /* expand the colour to 16 bits */
@@ -128,8 +128,8 @@ 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;
- dest = p->screen_base + yy * p->fontheight * bytes + xx * 2;
- cdat = p->fontdata + (c & p->charmask) * p->fontheight;
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * 2;
+ cdat = p->fontdata + (c & p->charmask) * fontheight(p);
fgx=3;/*attr_fgcol(p,c);*/
bgx=attr_bgcol(p,c);
@@ -139,7 +139,7 @@ void fbcon_cfb2_putc(struct vc_data *conp, struct display *p, int c, int yy,
bgx |= (bgx << 4);
eorx = fgx ^ bgx;
- for (rows = p->fontheight ; rows-- ; dest += bytes) {
+ for (rows = fontheight(p) ; rows-- ; dest += bytes) {
((u8 *)dest)[0]=
(nibbletab_cfb2[*cdat >> 4] & eorx) ^ bgx;
((u8 *)dest)[1]=
@@ -155,7 +155,7 @@ void fbcon_cfb2_putcs(struct vc_data *conp, struct display *p, const unsigned sh
int rows,bytes=p->next_line;
u32 eorx, fgx, bgx;
- dest0 = p->screen_base + yy * p->fontheight * bytes + xx * 2;
+ dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * 2;
fgx=3/*attr_fgcol(p,*s)*/;
bgx=attr_bgcol(p,*s);
fgx |= (fgx << 2);
@@ -165,9 +165,9 @@ void fbcon_cfb2_putcs(struct vc_data *conp, struct display *p, const unsigned sh
eorx = fgx ^ bgx;
while (count--) {
c = *s++ & p->charmask;
- cdat = p->fontdata + c * p->fontheight;
+ cdat = p->fontdata + c * fontheight(p);
- for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+ for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
((u8 *)dest)[0]=
(nibbletab_cfb2[*cdat >> 4] & eorx) ^ bgx;
((u8 *)dest)[1]=
@@ -182,8 +182,8 @@ void fbcon_cfb2_revc(struct display *p, int xx, int yy)
u8 *dest;
int bytes=p->next_line, rows;
- dest = p->screen_base + yy * p->fontheight * bytes + xx * 2;
- for (rows = p->fontheight ; rows-- ; dest += bytes) {
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * 2;
+ for (rows = fontheight(p) ; rows-- ; dest += bytes) {
((u16 *)dest)[0] ^= 0xffff;
}
}
diff --git a/drivers/video/fbcon-cfb2.h b/drivers/video/fbcon-cfb2.h
deleted file mode 100644
index 1cb29c5a9..000000000
--- a/drivers/video/fbcon-cfb2.h
+++ /dev/null
@@ -1,27 +0,0 @@
- /*
- * 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,
- int height, int width);
-extern void fbcon_cfb2_clear(struct vc_data *conp, struct display *p, int sy,
- int sx, int height, int width);
-extern void fbcon_cfb2_putc(struct vc_data *conp, struct display *p, int c,
- int yy, int xx);
-extern void fbcon_cfb2_putcs(struct vc_data *conp, struct display *p,
- const 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 49c023ef3..488aac290 100644
--- a/drivers/video/fbcon-cfb24.c
+++ b/drivers/video/fbcon-cfb24.c
@@ -9,23 +9,20 @@
* more details.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/fb.h>
-#include "fbcon.h"
-#include "fbcon-cfb24.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb24.h>
/*
* 24 bpp packed pixels
*/
-u32 fbcon_cfb24_cmap[16];
-
void fbcon_cfb24_setup(struct display *p)
{
p->next_line = p->line_length ? p->line_length : p->var.xres_virtual*3;
@@ -35,29 +32,29 @@ void fbcon_cfb24_setup(struct display *p)
void fbcon_cfb24_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
- int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
+ int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
u8 *src, *dst;
- if (sx == 0 && dx == 0 && width * p->fontwidth * 3 == bytes) {
+ if (sx == 0 && dx == 0 && width * fontwidth(p) * 3 == bytes) {
mymemmove(p->screen_base + dy * linesize,
p->screen_base + sy * linesize,
height * linesize);
return;
}
- if (p->fontwidthlog) {
- sx <<= p->fontwidthlog;
- dx <<= p->fontwidthlog;
- width <<= p->fontwidthlog;
+ if (fontwidthlog(p)) {
+ sx <<= fontwidthlog(p);
+ dx <<= fontwidthlog(p);
+ width <<= fontwidthlog(p);
} else {
- sx *= p->fontwidth;
- dx *= p->fontwidth;
- width *= p->fontwidth;
+ sx *= fontwidth(p);
+ dx *= fontwidth(p);
+ width *= fontwidth(p);
}
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--;) {
+ for (rows = height * fontheight(p); rows--;) {
mymemmove(dst, src, width);
src += bytes;
dst += bytes;
@@ -65,7 +62,7 @@ void fbcon_cfb24_bmove(struct display *p, int sy, int sx, int dy, int dx,
} else {
src = p->screen_base + (sy+height) * linesize + sx - bytes;
dst = p->screen_base + (dy+height) * linesize + dx - bytes;
- for (rows = height * p->fontheight; rows--;) {
+ for (rows = height * fontheight(p); rows--;) {
mymemmove(dst, src, width);
src -= bytes;
dst -= bytes;
@@ -73,48 +70,63 @@ void fbcon_cfb24_bmove(struct display *p, int sy, int sx, int dy, int dx,
}
}
-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;
+#define convert4to3(in1, in2, in3, in4, out1, out2, out3) \
+ do { \
+ out1 = (in1<<8) | (in2>>16); \
+ out2 = (in2<<16) | (in3>>8); \
+ out3 = (in3<<24) | in4; \
+ } while (0);
#elif defined(__LITTLE_ENDIAN)
- *dest++ = (d1<<8) | (d2>>16);
- *dest++ = (d2<<16) | (d3>>8);
- *dest++ = (d3<<24) | d4;
+#define convert4to3(in1, in2, in3, in4, out1, out2, out3) \
+ do { \
+ out1 = in1 | (in2<<24); \
+ out2 = (in2>> 8) | (in3<<16); \
+ out3 = (in3>>16) | (in4<< 8); \
+ } while (0);
#else
#error FIXME: No endianness??
#endif
+
+static inline void store4pixels(u32 d1, u32 d2, u32 d3, u32 d4, u32 *dest)
+{
+ convert4to3(d1, d2, d3, d4, *dest++, *dest++, *dest++);
+}
+
+static inline void rectfill(u8 *dest, int width, int height, u32 data,
+ int linesize)
+{
+ u32 d1, d2, d3;
+ int i;
+
+ convert4to3(data, data, data, data, d1, d2, d3);
+ while (height-- > 0) {
+ u32 *p = (u32 *)dest;
+ for (i = 0; i < width/4; i++) {
+ *p++ = d1;
+ *p++ = d2;
+ *p++ = d3;
+ }
+ dest += linesize;
+ }
}
void fbcon_cfb24_clear(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width)
{
- u8 *dest0, *dest;
- int bytes = p->next_line, lines = height * p->fontheight, rows, i;
+ u8 *dest;
+ int bytes = p->next_line, lines = height * fontheight(p);
u32 bgx;
- dest = p->screen_base + sy * p->fontheight * bytes + sx * p->fontwidth * 3;
+ dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 3;
- bgx = fbcon_cfb24_cmap[attr_bgcol_ec(p, conp)];
+ bgx = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
- 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) {
- dest = dest0;
- for (i = 0; i < width; i++) {
- store4pixels(bgx, bgx, bgx, bgx, (u32 *)dest);
- dest += 12;
- }
- }
- }
+ width *= fontwidth(p)/4;
+ if (width * 12 == bytes)
+ rectfill(dest, lines * width * 4, 1, bgx, bytes);
+ else
+ rectfill(dest, width * 4, lines, bgx, bytes);
}
void fbcon_cfb24_putc(struct vc_data *conp, struct display *p, int c, int yy,
@@ -124,34 +136,31 @@ void fbcon_cfb24_putc(struct vc_data *conp, struct display *p, int c, int yy,
int bytes = p->next_line, rows;
u32 eorx, fgx, bgx, d1, d2, d3, d4;
- dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 3;
- if (p->fontwidth <= 8)
- cdat = p->fontdata + (c & p->charmask) * p->fontheight;
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 3;
+ if (fontwidth(p) <= 8)
+ cdat = p->fontdata + (c & p->charmask) * fontheight(p);
else
- cdat = p->fontdata + ((c & p->charmask) * p->fontheight << 1);
+ cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1);
- fgx = fbcon_cfb24_cmap[attr_fgcol(p, c)];
- bgx = fbcon_cfb24_cmap[attr_bgcol(p, c)];
+ fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, c)];
+ bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, c)];
eorx = fgx ^ bgx;
- for (rows = p->fontheight; rows--; dest += bytes) {
+ for (rows = fontheight(p); 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)
+ if (fontwidth(p) < 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)
+ if (fontwidth(p) < 12)
continue;
bits = *cdat++;
d1 = (-(bits >> 7) & eorx) ^ bgx;
@@ -159,14 +168,13 @@ void fbcon_cfb24_putc(struct vc_data *conp, struct display *p, int c, int yy,
d3 = (-(bits >> 5 & 1) & eorx) ^ bgx;
d4 = (-(bits >> 4 & 1) & eorx) ^ bgx;
store4pixels(d1, d2, d3, d4, (u32 *)(dest+24));
- if (p->fontwidth < 16)
+ if (fontwidth(p) < 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
}
}
@@ -178,39 +186,32 @@ void fbcon_cfb24_putcs(struct vc_data *conp, struct display *p,
int rows, bytes = p->next_line;
u32 eorx, fgx, bgx, d1, d2, d3, d4;
- 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)];
+ dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 3;
+ fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, *s)];
+ bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, *s)];
eorx = fgx ^ bgx;
while (count--) {
c = *s++ & p->charmask;
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
- cdat = p->fontdata + c * p->fontheight;
-#else
- if (p->fontwidth <= 8)
- cdat = p->fontdata + c * p->fontheight;
+ if (fontwidth(p) <= 8)
+ cdat = p->fontdata + c * fontheight(p);
else
- cdat = p->fontdata + (c * p->fontheight << 1);
-#endif
- for (rows = p->fontheight, dest = dest0; rows--; dest += bytes) {
+ cdat = p->fontdata + (c * fontheight(p) << 1);
+ for (rows = fontheight(p), 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)
+ if (fontwidth(p) < 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)
+ if (fontwidth(p) < 12)
continue;
bits = *cdat++;
d1 = (-(bits >> 7) & eorx) ^ bgx;
@@ -218,16 +219,15 @@ void fbcon_cfb24_putcs(struct vc_data *conp, struct display *p,
d3 = (-(bits >> 5 & 1) & eorx) ^ bgx;
d4 = (-(bits >> 4 & 1) & eorx) ^ bgx;
store4pixels(d1, d2, d3, d4, (u32 *)(dest+24));
- if (p->fontwidth < 16)
+ if (fontwidth(p) < 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 += p->fontwidth*3;
+ dest0 += fontwidth(p)*3;
}
}
@@ -236,15 +236,9 @@ 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 * 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) {
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 3;
+ for (rows = fontheight(p); rows--; dest += bytes) {
+ switch (fontwidth(p)) {
case 16:
((u32 *)dest)[9] ^= 0xffffffff; ((u32 *)dest)[10] ^= 0xffffffff;
((u32 *)dest)[11] ^= 0xffffffff; /* FALL THROUGH */
@@ -258,39 +252,27 @@ void fbcon_cfb24_revc(struct display *p, int xx, int yy)
((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)
+void fbcon_cfb24_clear_margins(struct vc_data *conp, struct display *p,
+ int bottom_only)
{
- 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;
- }
- }
+
+ unsigned int right_start = conp->vc_cols*fontwidth(p);
+ unsigned int bottom_start = conp->vc_rows*fontheight(p);
+ unsigned int right_width, bottom_width;
+
+ bgx = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+
+ if (!bottom_only && (right_width = p->var.xres-right_start))
+ rectfill(p->screen_base+right_start*3, right_width,
+ p->var.yres_virtual, bgx, bytes);
+ if ((bottom_width = p->var.yres-bottom_start))
+ rectfill(p->screen_base+(p->var.yoffset+bottom_start)*bytes,
+ right_start, bottom_width, bgx, bytes);
}
@@ -327,4 +309,4 @@ EXPORT_SYMBOL(fbcon_cfb24_clear);
EXPORT_SYMBOL(fbcon_cfb24_putc);
EXPORT_SYMBOL(fbcon_cfb24_putcs);
EXPORT_SYMBOL(fbcon_cfb24_revc);
-EXPORT_SYMBOL(fbcon_cfb24_cmap);
+EXPORT_SYMBOL(fbcon_cfb24_clear_margins);
diff --git a/drivers/video/fbcon-cfb24.h b/drivers/video/fbcon-cfb24.h
deleted file mode 100644
index 83cee1209..000000000
--- a/drivers/video/fbcon-cfb24.h
+++ /dev/null
@@ -1,29 +0,0 @@
- /*
- * 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);
-extern void fbcon_cfb24_bmove(struct display *p, int sy, int sx, int dy,
- int dx, int height, int width);
-extern void fbcon_cfb24_clear(struct vc_data *conp, struct display *p, int sy,
- int sx, int height, int width);
-extern void fbcon_cfb24_putc(struct vc_data *conp, struct display *p, int c,
- int yy, int xx);
-extern void fbcon_cfb24_putcs(struct vc_data *conp, struct display *p,
- const 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 1a1c48bcf..cd1e80a7d 100644
--- a/drivers/video/fbcon-cfb32.c
+++ b/drivers/video/fbcon-cfb32.c
@@ -9,23 +9,20 @@
* more details.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/fb.h>
-#include "fbcon.h"
-#include "fbcon-cfb32.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb32.h>
/*
* 32 bpp packed pixels
*/
-u32 fbcon_cfb32_cmap[16];
-
void fbcon_cfb32_setup(struct display *p)
{
p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<2;
@@ -35,28 +32,28 @@ void fbcon_cfb32_setup(struct display *p)
void fbcon_cfb32_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
- int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
+ int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
u8 *src, *dst;
- if (sx == 0 && dx == 0 && width * p->fontwidth * 4 == bytes) {
+ if (sx == 0 && dx == 0 && width * fontwidth(p) * 4 == bytes) {
mymemmove(p->screen_base + dy * linesize,
p->screen_base + sy * linesize,
height * linesize);
return;
}
- if (p->fontwidthlog) {
- sx <<= p->fontwidthlog+2;
- dx <<= p->fontwidthlog+2;
- width <<= p->fontwidthlog+2;
+ if (fontwidthlog(p)) {
+ sx <<= fontwidthlog(p)+2;
+ dx <<= fontwidthlog(p)+2;
+ width <<= fontwidthlog(p)+2;
} else {
- sx *= p->fontwidth*4;
- dx *= p->fontwidth*4;
- width *= p->fontwidth*4;
+ sx *= fontwidth(p)*4;
+ dx *= fontwidth(p)*4;
+ width *= fontwidth(p)*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--;) {
+ for (rows = height * fontheight(p); rows--;) {
mymemmove(dst, src, width);
src += bytes;
dst += bytes;
@@ -64,7 +61,7 @@ void fbcon_cfb32_bmove(struct display *p, int sy, int sx, int dy, int dx,
} else {
src = p->screen_base + (sy+height) * linesize + sx - bytes;
dst = p->screen_base + (dy+height) * linesize + dx - bytes;
- for (rows = height * p->fontheight; rows--;) {
+ for (rows = height * fontheight(p); rows--;) {
mymemmove(dst, src, width);
src -= bytes;
dst -= bytes;
@@ -72,39 +69,45 @@ void fbcon_cfb32_bmove(struct display *p, int sy, int sx, int dy, int dx,
}
}
+static inline void rectfill(u8 *dest, int width, int height, u32 data,
+ int linesize)
+{
+ int i;
+
+ while (height-- > 0) {
+ u32 *p = (u32 *)dest;
+ for (i = 0; i < width/4; i++) {
+ *p++ = data;
+ *p++ = data;
+ *p++ = data;
+ *p++ = data;
+ }
+ if (width & 2) {
+ *p++ = data;
+ *p++ = data;
+ }
+ if (width & 1)
+ *p++ = data;
+ dest += linesize;
+ }
+}
+
void fbcon_cfb32_clear(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width)
{
- u8 *dest0, *dest;
- int bytes = p->next_line, lines = height * p->fontheight, rows, i;
+ u8 *dest;
+ int bytes = p->next_line, lines = height * fontheight(p);
u32 bgx;
- dest = p->screen_base + sy * p->fontheight * bytes + sx * p->fontwidth * 4;
+ dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 4;
- bgx = fbcon_cfb32_cmap[attr_bgcol_ec(p, conp)];
+ bgx = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
- 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;
- dest += 16;
- }
- else {
- dest0 = dest;
- for (rows = lines; rows--; dest0 += bytes) {
- dest = dest0;
- for (i = 0; i < width; i++) {
- ((u32 *)dest)[0] = bgx;
- ((u32 *)dest)[1] = bgx;
- ((u32 *)dest)[2] = bgx;
- ((u32 *)dest)[3] = bgx;
- dest += 16;
- }
- }
- }
+ width *= fontwidth(p)/4;
+ if (width * 16 == bytes)
+ rectfill(dest, lines * width * 4, 1, bgx, bytes);
+ else
+ rectfill(dest, width * 4, lines, bgx, bytes);
}
void fbcon_cfb32_putc(struct vc_data *conp, struct display *p, int c, int yy,
@@ -114,48 +117,40 @@ void fbcon_cfb32_putc(struct vc_data *conp, struct display *p, int c, int yy,
int bytes = p->next_line, rows;
u32 eorx, fgx, bgx;
- 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;
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4;
+ if (fontwidth(p) <= 8)
+ cdat = p->fontdata + (c & p->charmask) * fontheight(p);
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)];
+ cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1);
+ fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, c)];
+ bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, c)];
eorx = fgx ^ bgx;
- for (rows = p->fontheight; rows--; dest += bytes) {
+ for (rows = fontheight(p); 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)
+ if (fontwidth(p) < 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)
+ if (fontwidth(p) < 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)
+ if (fontwidth(p) < 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
}
}
@@ -167,51 +162,43 @@ void fbcon_cfb32_putcs(struct vc_data *conp, struct display *p,
int rows, bytes = p->next_line;
u32 eorx, fgx, bgx;
- 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)];
+ dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4;
+ fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, *s)];
+ bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, *s)];
eorx = fgx ^ bgx;
while (count--) {
c = *s++ & p->charmask;
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
- cdat = p->fontdata + c * p->fontheight;
-#else
- if (p->fontwidth <= 8)
- cdat = p->fontdata + c * p->fontheight;
+ if (fontwidth(p) <= 8)
+ cdat = p->fontdata + c * fontheight(p);
else
- cdat = p->fontdata + (c * p->fontheight << 1);
-#endif
- for (rows = p->fontheight, dest = dest0; rows--; dest += bytes) {
+ cdat = p->fontdata + (c * fontheight(p) << 1);
+ for (rows = fontheight(p), 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)
+ if (fontwidth(p) < 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)
+ if (fontwidth(p) < 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)
+ if (fontwidth(p) < 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 += p->fontwidth*4;
+ dest0 += fontwidth(p)*4;
}
}
@@ -220,15 +207,9 @@ 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 * 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) {
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4;
+ for (rows = fontheight(p); rows--; dest += bytes) {
+ switch (fontwidth(p)) {
case 16:
((u32 *)dest)[12] ^= 0xffffffff; ((u32 *)dest)[13] ^= 0xffffffff;
((u32 *)dest)[14] ^= 0xffffffff; ((u32 *)dest)[15] ^= 0xffffffff;
@@ -246,36 +227,27 @@ void fbcon_cfb32_revc(struct display *p, int xx, int yy)
((u32 *)dest)[2] ^= 0xffffffff; ((u32 *)dest)[3] ^= 0xffffffff;
/* FALL THROUGH */
}
-#endif
}
}
-void fbcon_cfb32_clear_margins(struct vc_data *conp, struct display *p)
+void fbcon_cfb32_clear_margins(struct vc_data *conp, struct display *p,
+ int bottom_only)
{
- 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;
+ unsigned int right_start = conp->vc_cols*fontwidth(p);
+ unsigned int bottom_start = conp->vc_rows*fontheight(p);
+ unsigned int right_width, bottom_width;
- bgx = fbcon_cfb32_cmap[attr_bgcol_ec(p, conp)];
+ bgx = ((u32 *)p->dispsw_data)[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;
- }
+ if (!bottom_only && (right_width = p->var.xres-right_start))
+ rectfill(p->screen_base+right_start*4, right_width,
+ p->var.yres_virtual, bgx, bytes);
+ if ((bottom_width = p->var.yres-bottom_start))
+ rectfill(p->screen_base+(p->var.yoffset+bottom_start)*bytes,
+ right_start, bottom_width, bgx, bytes);
}
@@ -312,4 +284,4 @@ EXPORT_SYMBOL(fbcon_cfb32_clear);
EXPORT_SYMBOL(fbcon_cfb32_putc);
EXPORT_SYMBOL(fbcon_cfb32_putcs);
EXPORT_SYMBOL(fbcon_cfb32_revc);
-EXPORT_SYMBOL(fbcon_cfb32_cmap);
+EXPORT_SYMBOL(fbcon_cfb32_clear_margins);
diff --git a/drivers/video/fbcon-cfb32.h b/drivers/video/fbcon-cfb32.h
deleted file mode 100644
index 500528b04..000000000
--- a/drivers/video/fbcon-cfb32.h
+++ /dev/null
@@ -1,29 +0,0 @@
- /*
- * 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);
-extern void fbcon_cfb32_bmove(struct display *p, int sy, int sx, int dy,
- int dx, int height, int width);
-extern void fbcon_cfb32_clear(struct vc_data *conp, struct display *p, int sy,
- int sx, int height, int width);
-extern void fbcon_cfb32_putc(struct vc_data *conp, struct display *p, int c,
- int yy, int xx);
-extern void fbcon_cfb32_putcs(struct vc_data *conp, struct display *p,
- const 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 4d3f196bf..78b87ffe7 100644
--- a/drivers/video/fbcon-cfb4.c
+++ b/drivers/video/fbcon-cfb4.c
@@ -16,8 +16,8 @@
#include <linux/string.h>
#include <linux/fb.h>
-#include "fbcon.h"
-#include "fbcon-cfb4.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb4.h>
/*
@@ -57,7 +57,7 @@ void fbcon_cfb4_setup(struct display *p)
void fbcon_cfb4_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
- int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
+ int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
u8 *src,*dst;
if (sx == 0 && dx == 0 && width * 4 == bytes) {
@@ -69,7 +69,7 @@ void fbcon_cfb4_bmove(struct display *p, int sy, int sx, int dy, int dx,
if (dy < sy || (dy == sy && dx < sx)) {
src = p->screen_base + sy * linesize + sx * 4;
dst = p->screen_base + dy * linesize + dx * 4;
- for (rows = height * p->fontheight ; rows-- ;) {
+ for (rows = height * fontheight(p) ; rows-- ;) {
mymemmove(dst, src, width * 4);
src += bytes;
dst += bytes;
@@ -80,7 +80,7 @@ void fbcon_cfb4_bmove(struct display *p, int sy, int sx, int dy, int dx,
- bytes;
dst = p->screen_base + (dy+height) * linesize + dx * 4
- bytes;
- for (rows = height * p->fontheight ; rows-- ;) {
+ for (rows = height * fontheight(p) ; rows-- ;) {
mymemmove(dst, src, width * 4);
src -= bytes;
dst -= bytes;
@@ -93,12 +93,12 @@ void fbcon_cfb4_clear(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width)
{
u8 *dest0,*dest;
- int bytes=p->next_line,lines=height * p->fontheight, rows, i;
+ int bytes=p->next_line,lines=height * fontheight(p), rows, i;
u32 bgx;
/* if(p->screen_base!=0xFDD00020)
mac_boom(1);*/
- dest = p->screen_base + sy * p->fontheight * bytes + sx * 4;
+ dest = p->screen_base + sy * fontheight(p) * bytes + sx * 4;
bgx=attr_bgcol_ec(p,conp);
bgx |= (bgx << 4); /* expand the colour to 32bits */
@@ -130,10 +130,10 @@ 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;
- dest = p->screen_base + yy * p->fontheight * bytes + xx * 4;
- cdat = p->fontdata + (c & p->charmask) * p->fontheight;
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * 4;
+ cdat = p->fontdata + (c & p->charmask) * fontheight(p);
- fgx=15;/*attr_fgcol(p,c);*/
+ fgx=attr_fgcol(p,c);
bgx=attr_bgcol(p,c);
fgx |= (fgx << 4);
fgx |= (fgx << 8);
@@ -141,7 +141,7 @@ void fbcon_cfb4_putc(struct vc_data *conp, struct display *p, int c, int yy,
bgx |= (bgx << 8);
eorx = fgx ^ bgx;
- for (rows = p->fontheight ; rows-- ; dest += bytes) {
+ for (rows = fontheight(p) ; rows-- ; dest += bytes) {
((u16 *)dest)[0]=
(nibbletab_cfb4[*cdat >> 4] & eorx) ^ bgx;
((u16 *)dest)[1]=
@@ -157,8 +157,8 @@ void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p,
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,*s)*/;
+ dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * 4;
+ fgx=attr_fgcol(p,*s);
bgx=attr_bgcol(p,*s);
fgx |= (fgx << 4);
fgx |= (fgx << 8);
@@ -169,9 +169,9 @@ void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p,
eorx = fgx ^ bgx;
while (count--) {
c = *s++ & p->charmask;
- cdat = p->fontdata + c * p->fontheight;
+ cdat = p->fontdata + c * fontheight(p);
- for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+ for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
((u16 *)dest)[0]=
(nibbletab_cfb4[*cdat >> 4] & eorx) ^ bgx;
((u16 *)dest)[1]=
@@ -186,9 +186,9 @@ void fbcon_cfb4_revc(struct display *p, int xx, int yy)
u8 *dest;
int bytes=p->next_line, rows;
- dest = p->screen_base + yy * p->fontheight * bytes + xx * 4;
- for (rows = p->fontheight ; rows-- ; dest += bytes) {
- ((u32 *)dest)[0] ^= 0x0f0f0f0f;
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * 4;
+ for (rows = fontheight(p) ; rows-- ; dest += bytes) {
+ ((u32 *)dest)[0] ^= 0xffffffff;
}
}
diff --git a/drivers/video/fbcon-cfb4.h b/drivers/video/fbcon-cfb4.h
deleted file mode 100644
index df08288cd..000000000
--- a/drivers/video/fbcon-cfb4.h
+++ /dev/null
@@ -1,27 +0,0 @@
- /*
- * 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,
- int height, int width);
-extern void fbcon_cfb4_clear(struct vc_data *conp, struct display *p, int sy,
- int sx, int height, int width);
-extern void fbcon_cfb4_putc(struct vc_data *conp, struct display *p, int c,
- int yy, int xx);
-extern void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p,
- const 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 b4de49b3b..5fe78bc30 100644
--- a/drivers/video/fbcon-cfb8.c
+++ b/drivers/video/fbcon-cfb8.c
@@ -9,15 +9,14 @@
* more details.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/fb.h>
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
/*
@@ -49,24 +48,24 @@ void fbcon_cfb8_setup(struct display *p)
void fbcon_cfb8_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
- int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
+ int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
u8 *src,*dst;
- if (sx == 0 && dx == 0 && width * p->fontwidth == bytes) {
+ if (sx == 0 && dx == 0 && width * fontwidth(p) == bytes) {
mymemmove(p->screen_base + dy * linesize,
p->screen_base + sy * linesize,
height * linesize);
return;
}
- if (p->fontwidthlog) {
- sx <<= p->fontwidthlog; dx <<= p->fontwidthlog; width <<= p->fontwidthlog;
+ if (fontwidthlog(p)) {
+ sx <<= fontwidthlog(p); dx <<= fontwidthlog(p); width <<= fontwidthlog(p);
} else {
- sx *= p->fontwidth; dx *= p->fontwidth; width *= p->fontwidth;
+ sx *= fontwidth(p); dx *= fontwidth(p); width *= fontwidth(p);
}
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-- ;) {
+ for (rows = height * fontheight(p) ; rows-- ;) {
mymemmove(dst, src, width);
src += bytes;
dst += bytes;
@@ -74,7 +73,7 @@ void fbcon_cfb8_bmove(struct display *p, int sy, int sx, int dy, int dx,
} else {
src = p->screen_base + (sy+height) * linesize + sx - bytes;
dst = p->screen_base + (dy+height) * linesize + dx - bytes;
- for (rows = height * p->fontheight ; rows-- ;) {
+ for (rows = height * fontheight(p) ; rows-- ;) {
mymemmove(dst, src, width);
src -= bytes;
dst -= bytes;
@@ -82,24 +81,31 @@ void fbcon_cfb8_bmove(struct display *p, int sy, int sx, int dy, int dx,
}
}
+static inline void rectfill(u8 *dest, int width, int height, u8 data,
+ int linesize)
+{
+ while (height-- > 0) {
+ memset(dest, data, width);
+ dest += linesize;
+ }
+}
+
void fbcon_cfb8_clear(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width)
{
u8 *dest;
- int bytes=p->next_line,lines=height * p->fontheight, rows;
+ int bytes=p->next_line,lines=height * fontheight(p);
u8 bgx;
- dest = p->screen_base + sy * p->fontheight * bytes + sx * p->fontwidth;
+ dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p);
bgx=attr_bgcol_ec(p,conp);
- if (sx == 0 && p->fontwidth == 8 && width * 8 == bytes)
- memset(dest, bgx, lines * width * p->fontwidth);
- else {
- width *= p->fontwidth;
- for (rows = lines; rows-- ; dest += bytes)
- memset(dest, bgx, width);
- }
+ width *= fontwidth(p);
+ if (width == bytes)
+ rectfill(dest, lines * width, 1, bgx, bytes);
+ else
+ rectfill(dest, width, lines, bgx, bytes);
}
void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c, int yy,
@@ -109,11 +115,11 @@ 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;
- dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth;
- if (p->fontwidth <= 8)
- cdat = p->fontdata + (c & p->charmask) * p->fontheight;
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
+ if (fontwidth(p) <= 8)
+ cdat = p->fontdata + (c & p->charmask) * fontheight(p);
else
- cdat = p->fontdata + ((c & p->charmask) * p->fontheight << 1);
+ cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1);
fgx=attr_fgcol(p,c);
bgx=attr_bgcol(p,c);
@@ -123,33 +129,29 @@ void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c, int yy,
bgx |= (bgx << 16);
eorx = fgx ^ bgx;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
- switch (p->fontwidth) {
+ switch (fontwidth(p)) {
case 4:
- for (rows = p->fontheight ; rows-- ; dest += bytes)
+ for (rows = fontheight(p) ; rows-- ; dest += bytes)
((u32 *)dest)[0]= (nibbletab_cfb8[*cdat++ >> 4] & eorx) ^ bgx;
break;
case 8:
-#endif
- for (rows = p->fontheight ; rows-- ; dest += bytes) {
+ for (rows = fontheight(p) ; 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) {
+ for (rows = fontheight(p) ; 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)
+ if (fontwidth(p) == 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,
@@ -160,7 +162,7 @@ void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p,
int rows,bytes=p->next_line;
u32 eorx, fgx, bgx;
- dest0 = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth;
+ dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
fgx=attr_fgcol(p,*s);
bgx=attr_bgcol(p,*s);
fgx |= (fgx << 8);
@@ -168,51 +170,47 @@ void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p,
bgx |= (bgx << 8);
bgx |= (bgx << 16);
eorx = fgx ^ bgx;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
- switch (p->fontwidth) {
+ switch (fontwidth(p)) {
case 4:
while (count--) {
c = *s++ & p->charmask;
- cdat = p->fontdata + c * p->fontheight;
+ cdat = p->fontdata + c * fontheight(p);
- for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes)
+ for (rows = fontheight(p), 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;
+ cdat = p->fontdata + c * fontheight(p);
- for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+ for (rows = fontheight(p), 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);
+ cdat = p->fontdata + (c * fontheight(p) << 1);
- for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+ for (rows = fontheight(p), 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)
+ if (fontwidth(p) == 16)
((u32 *)dest)[3]= (nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx;
cdat += 2;
}
- dest0+=p->fontwidth;
+ dest0+=fontwidth(p);
}
break;
}
-#endif
}
void fbcon_cfb8_revc(struct display *p, int xx, int yy)
@@ -220,44 +218,36 @@ 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 * p->fontwidth;
- for (rows = p->fontheight ; rows-- ; dest += bytes) {
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
- ((u32 *)dest)[1] ^= 0x0f0f0f0f;
- ((u32 *)dest)[0] ^= 0x0f0f0f0f;
-#else
- switch (p->fontwidth) {
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
+ for (rows = fontheight(p) ; rows-- ; dest += bytes) {
+ switch (fontwidth(p)) {
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)
+void fbcon_cfb8_clear_margins(struct vc_data *conp, struct display *p,
+ int bottom_only)
{
- 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;
+ unsigned int right_start = conp->vc_cols*fontwidth(p);
+ unsigned int bottom_start = conp->vc_rows*fontheight(p);
+ unsigned int right_width, bottom_width;
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);
+ if (!bottom_only && (right_width = p->var.xres-right_start))
+ rectfill(p->screen_base+right_start, right_width, p->var.yres_virtual,
+ bgx, bytes);
+ if ((bottom_width = p->var.yres-bottom_start))
+ rectfill(p->screen_base+(p->var.yoffset+bottom_start)*bytes,
+ right_start, bottom_width, bgx, bytes);
}
@@ -294,3 +284,4 @@ EXPORT_SYMBOL(fbcon_cfb8_clear);
EXPORT_SYMBOL(fbcon_cfb8_putc);
EXPORT_SYMBOL(fbcon_cfb8_putcs);
EXPORT_SYMBOL(fbcon_cfb8_revc);
+EXPORT_SYMBOL(fbcon_cfb8_clear_margins);
diff --git a/drivers/video/fbcon-cfb8.h b/drivers/video/fbcon-cfb8.h
deleted file mode 100644
index e1d8170ed..000000000
--- a/drivers/video/fbcon-cfb8.h
+++ /dev/null
@@ -1,28 +0,0 @@
- /*
- * 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,
- int height, int width);
-extern void fbcon_cfb8_clear(struct vc_data *conp, struct display *p, int sy,
- int sx, int height, int width);
-extern void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c,
- int yy, int xx);
-extern void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p,
- const 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 b87a1d10c..183f05a46 100644
--- a/drivers/video/fbcon-ilbm.c
+++ b/drivers/video/fbcon-ilbm.c
@@ -15,8 +15,8 @@
#include <linux/string.h>
#include <linux/fb.h>
-#include "fbcon.h"
-#include "fbcon-ilbm.h"
+#include <video/fbcon.h>
+#include <video/fbcon-ilbm.h>
/*
@@ -45,25 +45,25 @@ void fbcon_ilbm_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
if (sx == 0 && dx == 0 && width == p->next_plane)
- mymemmove(p->screen_base+dy*p->fontheight*p->next_line,
- p->screen_base+sy*p->fontheight*p->next_line,
- height*p->fontheight*p->next_line);
+ mymemmove(p->screen_base+dy*fontheight(p)*p->next_line,
+ p->screen_base+sy*fontheight(p)*p->next_line,
+ height*fontheight(p)*p->next_line);
else {
u8 *src, *dest;
u_int i;
if (dy <= sy) {
- src = p->screen_base+sy*p->fontheight*p->next_line+sx;
- dest = p->screen_base+dy*p->fontheight*p->next_line+dx;
- for (i = p->var.bits_per_pixel*height*p->fontheight; i--;) {
+ src = p->screen_base+sy*fontheight(p)*p->next_line+sx;
+ dest = p->screen_base+dy*fontheight(p)*p->next_line+dx;
+ for (i = p->var.bits_per_pixel*height*fontheight(p); i--;) {
mymemmove(dest, src, width);
src += p->next_plane;
dest += p->next_plane;
}
} else {
- src = p->screen_base+(sy+height)*p->fontheight*p->next_line+sx;
- dest = p->screen_base+(dy+height)*p->fontheight*p->next_line+dx;
- for (i = p->var.bits_per_pixel*height*p->fontheight; i--;) {
+ src = p->screen_base+(sy+height)*fontheight(p)*p->next_line+sx;
+ dest = p->screen_base+(dy+height)*fontheight(p)*p->next_line+dx;
+ for (i = p->var.bits_per_pixel*height*fontheight(p); i--;) {
src -= p->next_plane;
dest -= p->next_plane;
mymemmove(dest, src, width);
@@ -79,10 +79,10 @@ void fbcon_ilbm_clear(struct vc_data *conp, struct display *p, int sy, int sx,
u_int i, rows;
int bg, bg0;
- dest = p->screen_base+sy*p->fontheight*p->next_line+sx;
+ dest = p->screen_base+sy*fontheight(p)*p->next_line+sx;
bg0 = attr_bgcol_ec(p,conp);
- for (rows = height*p->fontheight; rows--;) {
+ for (rows = height*fontheight(p); rows--;) {
bg = bg0;
for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
if (bg & 1)
@@ -102,12 +102,12 @@ void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c, int yy,
u8 d;
int fg0, bg0, fg, bg;
- dest = p->screen_base+yy*p->fontheight*p->next_line+xx;
- cdat = p->fontdata+(c&p->charmask)*p->fontheight;
+ dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
+ cdat = p->fontdata+(c&p->charmask)*fontheight(p);
fg0 = attr_fgcol(p,c);
bg0 = attr_bgcol(p,c);
- for (rows = p->fontheight; rows--;) {
+ for (rows = fontheight(p); rows--;) {
d = *cdat++;
fg = fg0;
bg = bg0;
@@ -153,7 +153,7 @@ void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p,
u32 d;
int fg0, bg0, fg, bg;
- dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx;
+ dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
fg0 = attr_fgcol(p,*s);
bg0 = attr_bgcol(p,*s);
@@ -163,8 +163,8 @@ void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p,
dest = dest0++;
xx++;
- cdat1 = p->fontdata+c1*p->fontheight;
- for (rows = p->fontheight; rows--;) {
+ cdat1 = p->fontdata+c1*fontheight(p);
+ for (rows = fontheight(p); rows--;) {
d = *cdat1++;
fg = fg0;
bg = bg0;
@@ -191,11 +191,11 @@ void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p,
c4 = s[3] & p->charmask;
dest = dest0;
- cdat1 = p->fontdata+c1*p->fontheight;
- cdat2 = p->fontdata+c2*p->fontheight;
- cdat3 = p->fontdata+c3*p->fontheight;
- cdat4 = p->fontdata+c4*p->fontheight;
- for (rows = p->fontheight; rows--;) {
+ cdat1 = p->fontdata+c1*fontheight(p);
+ cdat2 = p->fontdata+c2*fontheight(p);
+ cdat3 = p->fontdata+c3*fontheight(p);
+ cdat4 = p->fontdata+c4*fontheight(p);
+ for (rows = fontheight(p); rows--;) {
#if defined(__BIG_ENDIAN)
d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++;
#elif defined(__LITTLE_ENDIAN)
@@ -234,7 +234,7 @@ void fbcon_ilbm_revc(struct display *p, int xx, int yy)
u_int rows, i;
int mask;
- dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx;
+ dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
mask = p->fgcol ^ p->bgcol;
/*
@@ -246,7 +246,7 @@ void fbcon_ilbm_revc(struct display *p, int xx, int yy)
for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
if (mask & 1) {
dest = dest0;
- for (rows = p->fontheight; rows--; dest += p->next_line)
+ for (rows = fontheight(p); rows--; dest += p->next_line)
*dest = ~*dest;
}
mask >>= 1;
diff --git a/drivers/video/fbcon-ilbm.h b/drivers/video/fbcon-ilbm.h
deleted file mode 100644
index 13292f287..000000000
--- a/drivers/video/fbcon-ilbm.h
+++ /dev/null
@@ -1,27 +0,0 @@
- /*
- * 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,
- int height, int width);
-extern void fbcon_ilbm_clear(struct vc_data *conp, struct display *p, int sy,
- int sx, int height, int width);
-extern void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c,
- int yy, int xx);
-extern void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p,
- const 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 3cd8ab81e..c8d6838be 100644
--- a/drivers/video/fbcon-iplan2p2.c
+++ b/drivers/video/fbcon-iplan2p2.c
@@ -19,8 +19,8 @@
#include <asm/byteorder.h>
-#include "fbcon.h"
-#include "fbcon-iplan2p2.h"
+#include <video/fbcon.h>
+#include <video/fbcon-iplan2p2.h>
/*
@@ -169,18 +169,25 @@ void fbcon_iplan2p2_bmove(struct display *p, int sy, int sx, int dy, int dx,
/* Special (but often used) case: Moving whole lines can be
* done with memmove()
*/
- mymemmove(p->screen_base + dy * p->next_line * p->fontheight,
- p->screen_base + sy * p->next_line * p->fontheight,
- p->next_line * height * p->fontheight);
+ mymemmove(p->screen_base + dy * p->next_line * fontheight(p),
+ p->screen_base + sy * p->next_line * fontheight(p),
+ p->next_line * height * fontheight(p));
} else {
int rows, cols;
u8 *src;
u8 *dst;
int bytes = p->next_line;
- int linesize = bytes * p->fontheight;
- u_int colsize = height * p->fontheight;
+ int linesize;
+ u_int colsize;
u_int upwards = (dy < sy) || (dy == sy && dx < sx);
+ if (fontheightlog(p)) {
+ linesize = bytes << fontheightlog(p);
+ colsize = height << fontheightlog(p);
+ } else {
+ linesize = bytes * fontheight(p);
+ colsize = height * fontheight(p);
+ }
if ((sx & 1) == (dx & 1)) {
/* odd->odd or even->even */
if (upwards) {
@@ -258,19 +265,30 @@ void fbcon_iplan2p2_clear(struct vc_data *conp, struct display *p, int sy,
u8 *start;
int rows;
int bytes = p->next_line;
- int lines = height * p->fontheight;
+ int lines;
u32 size;
u32 cval;
u16 pcval;
cval = expand2l (COLOR_2P (attr_bgcol_ec(p,conp)));
+ if (fontheightlog(p))
+ lines = height << fontheightlog(p);
+ else
+ lines = height * fontheight(p);
+
if (sx == 0 && width * 2 == bytes) {
- offset = sy * bytes * p->fontheight;
+ if (fontheightlog(p))
+ offset = (sy * bytes) << fontheightlog(p);
+ else
+ offset = sy * bytes * fontheight(p);
size = lines * bytes;
memset_even_2p(p->screen_base+offset, size, cval);
} else {
- offset = (sy * bytes * p->fontheight) + (sx>>1)*4 + (sx & 1);
+ if (fontheightlog(p))
+ offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*4 + (sx & 1);
+ else
+ offset = sy * bytes * fontheight(p) + (sx>>1)*4 + (sx & 1);
start = p->screen_base + offset;
pcval = expand2w(COLOR_2P(attr_bgcol_ec(p,conp)));
@@ -306,14 +324,21 @@ void fbcon_iplan2p2_putc(struct vc_data *conp, struct display *p, int c,
int bytes = p->next_line;
u16 eorx, fgx, bgx, fdx;
- dest = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*4 + (xx & 1);
- cdat = p->fontdata + (c & p->charmask) * p->fontheight;
+ if (fontheightlog(p)) {
+ dest = (p->screen_base + ((yy * bytes) << fontheightlog(p)) +
+ (xx>>1)*4 + (xx & 1));
+ cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
+ } else {
+ dest = (p->screen_base + yy * bytes * fontheight(p) +
+ (xx>>1)*4 + (xx & 1));
+ cdat = p->fontdata + (c & p->charmask) * fontheight(p);
+ }
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) {
+ for (rows = fontheight(p) ; rows-- ; dest += bytes) {
fdx = dup2w(*cdat++);
movepw(dest, (fdx & eorx) ^ bgx);
}
@@ -330,16 +355,24 @@ void fbcon_iplan2p2_putcs(struct vc_data *conp, struct display *p,
u16 eorx, fgx, bgx, fdx;
bytes = p->next_line;
- dest0 = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*4 + (xx & 1);
+ if (fontheightlog(p))
+ dest0 = (p->screen_base + ((yy * bytes) << fontheightlog(p)) +
+ (xx>>1)*4 + (xx & 1));
+ else
+ dest0 = (p->screen_base + yy * bytes * fontheight(p) +
+ (xx>>1)*4 + (xx & 1));
fgx = expand2w(COLOR_2P(attr_fgcol(p,*s)));
bgx = expand2w(COLOR_2P(attr_bgcol(p,*s)));
eorx = fgx ^ bgx;
while (count--) {
c = *s++ & p->charmask;
- cdat = p->fontdata + (c * p->fontheight);
+ if (fontheightlog(p))
+ cdat = p->fontdata + (c << fontheightlog(p));
+ else
+ cdat = p->fontdata + c * fontheight(p);
- for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+ for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
fdx = dup2w(*cdat++);
movepw(dest, (fdx & eorx) ^ bgx);
}
@@ -353,9 +386,13 @@ void fbcon_iplan2p2_revc(struct display *p, int xx, int yy)
int j;
int bytes;
- dest = p->screen_base + yy * p->fontheight * p->next_line + (xx>>1)*4 +
- (xx & 1);
- j = p->fontheight;
+ if (fontheightlog(p))
+ dest = (p->screen_base + ((yy * p->next_line) << fontheightlog(p)) +
+ (xx>>1)*4 + (xx & 1));
+ else
+ dest = (p->screen_base + yy * p->next_line * fontheight(p) +
+ (xx>>1)*4 + (xx & 1));
+ j = fontheight(p);
bytes = p->next_line;
while (j--) {
/* This should really obey the individual character's
@@ -368,6 +405,30 @@ void fbcon_iplan2p2_revc(struct display *p, int xx, int yy)
}
}
+void fbcon_iplan2p2_clear_margins(struct vc_data *conp, struct display *p,
+ int bottom_only)
+{
+ u32 offset;
+ int bytes;
+ int lines;
+ u32 cval;
+
+/* No need to handle right margin, cannot occur with fontwidth == 8 */
+
+ bytes = p->next_line;
+ if (fontheightlog(p)) {
+ lines = p->var.yres - (conp->vc_rows << fontheightlog(p));
+ offset = ((p->yscroll + conp->vc_rows) * bytes) << fontheightlog(p);
+ } else {
+ lines = p->var.yres - conp->vc_rows * fontheight(p);
+ offset = (p->yscroll + conp->vc_rows) * bytes * fontheight(p);
+ }
+ if (lines) {
+ cval = expand2l(COLOR_2P(attr_bgcol_ec(p,conp)));
+ memset_even_2p(p->screen_base+offset, lines * bytes, cval);
+ }
+}
+
/*
* `switch' for the low level operations
@@ -376,7 +437,7 @@ 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, NULL,
- NULL, NULL, FONTWIDTH(8)
+ NULL, fbcon_iplan2p2_clear_margins, FONTWIDTH(8)
};
@@ -402,3 +463,4 @@ EXPORT_SYMBOL(fbcon_iplan2p2_clear);
EXPORT_SYMBOL(fbcon_iplan2p2_putc);
EXPORT_SYMBOL(fbcon_iplan2p2_putcs);
EXPORT_SYMBOL(fbcon_iplan2p2_revc);
+EXPORT_SYMBOL(fbcon_iplan2p2_clear_margins);
diff --git a/drivers/video/fbcon-iplan2p2.h b/drivers/video/fbcon-iplan2p2.h
deleted file mode 100644
index 07b5a0d31..000000000
--- a/drivers/video/fbcon-iplan2p2.h
+++ /dev/null
@@ -1,27 +0,0 @@
- /*
- * 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,
- int dx, int height, int width);
-extern void fbcon_iplan2p2_clear(struct vc_data *conp, struct display *p,
- int sy, int sx, int height, int width);
-extern void fbcon_iplan2p2_putc(struct vc_data *conp, struct display *p, int c,
- int yy, int xx);
-extern void fbcon_iplan2p2_putcs(struct vc_data *conp, struct display *p,
- const 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 4bd21c366..04b4a8422 100644
--- a/drivers/video/fbcon-iplan2p4.c
+++ b/drivers/video/fbcon-iplan2p4.c
@@ -19,8 +19,8 @@
#include <asm/byteorder.h>
-#include "fbcon.h"
-#include "fbcon-iplan2p4.h"
+#include <video/fbcon.h>
+#include <video/fbcon-iplan2p4.h>
/*
@@ -177,18 +177,25 @@ void fbcon_iplan2p4_bmove(struct display *p, int sy, int sx, int dy, int dx,
/* Special (but often used) case: Moving whole lines can be
*done with memmove()
*/
- mymemmove(p->screen_base + dy * p->next_line * p->fontheight,
- p->screen_base + sy * p->next_line * p->fontheight,
- p->next_line * height * p->fontheight);
+ mymemmove(p->screen_base + dy * p->next_line * fontheight(p),
+ p->screen_base + sy * p->next_line * fontheight(p),
+ p->next_line * height * fontheight(p));
} else {
int rows, cols;
u8 *src;
u8 *dst;
int bytes = p->next_line;
- int linesize = bytes * p->fontheight;
- u_int colsize = height * p->fontheight;
+ int linesize;
+ u_int colsize;
u_int upwards = (dy < sy) || (dy == sy && dx < sx);
+ if (fontheightlog(p)) {
+ linesize = bytes << fontheightlog(p);
+ colsize = height << fontheightlog(p);
+ } else {
+ linesize = bytes * fontheight(p);
+ colsize = height * fontheight(p);
+ }
if ((sx & 1) == (dx & 1)) {
/* odd->odd or even->even */
@@ -269,18 +276,29 @@ void fbcon_iplan2p4_clear(struct vc_data *conp, struct display *p, int sy,
u8 *start;
int rows;
int bytes = p->next_line;
- int lines = height * p->fontheight;
+ int lines;
u32 size;
u32 cval1, cval2, pcval;
expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2);
+ if (fontheightlog(p))
+ lines = height << fontheightlog(p);
+ else
+ lines = height * fontheight(p);
+
if (sx == 0 && width * 4 == bytes) {
- offset = sy * bytes * p->fontheight;
+ if (fontheightlog(p))
+ offset = (sy * bytes) << fontheightlog(p);
+ else
+ offset = sy * bytes * fontheight(p);
size = lines * bytes;
memset_even_4p(p->screen_base+offset, size, cval1, cval2);
} else {
- offset = (sy * bytes * p->fontheight) + (sx>>1)*8 + (sx & 1);
+ if (fontheightlog(p))
+ offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*8 + (sx & 1);
+ else
+ offset = sy * bytes * fontheight(p) + (sx>>1)*8 + (sx & 1);
start = p->screen_base + offset;
pcval = expand4l(attr_bgcol_ec(p,conp));
@@ -316,14 +334,21 @@ void fbcon_iplan2p4_putc(struct vc_data *conp, struct display *p, int c,
int bytes = p->next_line;
u32 eorx, fgx, bgx, fdx;
- dest = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*8 + (xx & 1);
- cdat = p->fontdata + (c & p->charmask) * p->fontheight;
+ if (fontheightlog(p)) {
+ dest = (p->screen_base + ((yy * bytes) << fontheightlog(p)) +
+ (xx>>1)*8 + (xx & 1));
+ cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
+ } else {
+ dest = (p->screen_base + yy * bytes * fontheight(p) +
+ (xx>>1)*8 + (xx & 1));
+ cdat = p->fontdata + (c & p->charmask) * fontheight(p);
+ }
fgx = expand4l(attr_fgcol(p,c));
bgx = expand4l(attr_bgcol(p,c));
eorx = fgx ^ bgx;
- for(rows = p->fontheight ; rows-- ; dest += bytes) {
+ for(rows = fontheight(p) ; rows-- ; dest += bytes) {
fdx = dup4l(*cdat++);
movepl(dest, (fdx & eorx) ^ bgx);
}
@@ -340,7 +365,12 @@ void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p,
u32 eorx, fgx, bgx, fdx;
bytes = p->next_line;
- dest0 = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*8 + (xx & 1);
+ if (fontheightlog(p))
+ dest0 = (p->screen_base + ((yy * bytes) << fontheightlog(p)) +
+ (xx>>1)*8 + (xx & 1));
+ else
+ dest0 = (p->screen_base + yy * bytes * fontheight(p) +
+ (xx>>1)*8 + (xx & 1));
fgx = expand4l(attr_fgcol(p,*s));
bgx = expand4l(attr_bgcol(p,*s));
eorx = fgx ^ bgx;
@@ -354,9 +384,12 @@ void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p,
*/
c = *s++ & p->charmask;
- cdat = p->fontdata + (c * p->fontheight);
+ if (fontheightlog(p))
+ cdat = p->fontdata + (c << fontheightlog(p));
+ else
+ cdat = p->fontdata + c * fontheight(p);
- for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+ for(rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
fdx = dup4l(*cdat++);
movepl(dest, (fdx & eorx) ^ bgx);
}
@@ -370,9 +403,13 @@ void fbcon_iplan2p4_revc(struct display *p, int xx, int yy)
int j;
int bytes;
- dest = p->screen_base + yy * p->fontheight * p->next_line + (xx>>1)*8 +
- (xx & 1);
- j = p->fontheight;
+ if (fontheightlog(p))
+ dest = (p->screen_base + ((yy * p->next_line) << fontheightlog(p)) +
+ (xx>>1)*8 + (xx & 1));
+ else
+ dest = (p->screen_base + yy * p->next_line * fontheight(p) +
+ (xx>>1)*8 + (xx & 1));
+ j = fontheight(p);
bytes = p->next_line;
while (j--) {
@@ -388,6 +425,30 @@ void fbcon_iplan2p4_revc(struct display *p, int xx, int yy)
}
}
+void fbcon_iplan2p4_clear_margins(struct vc_data *conp, struct display *p,
+ int bottom_only)
+{
+ u32 offset;
+ int bytes;
+ int lines;
+ u32 cval1, cval2;
+
+/* No need to handle right margin, cannot occur with fontwidth == 8 */
+
+ bytes = p->next_line;
+ if (fontheightlog(p)) {
+ lines = p->var.yres - (conp->vc_rows << fontheightlog(p));
+ offset = ((p->yscroll + conp->vc_rows) * bytes) << fontheightlog(p);
+ } else {
+ lines = p->var.yres - conp->vc_rows * fontheight(p);
+ offset = (p->yscroll + conp->vc_rows) * bytes * fontheight(p);
+ }
+ if (lines) {
+ expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2);
+ memset_even_4p(p->screen_base+offset, lines * bytes, cval1, cval2);
+ }
+}
+
/*
* `switch' for the low level operations
@@ -396,7 +457,7 @@ 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, NULL,
- NULL, NULL, FONTWIDTH(8)
+ NULL, fbcon_iplan2p4_clear_margins, FONTWIDTH(8)
};
@@ -422,3 +483,4 @@ EXPORT_SYMBOL(fbcon_iplan2p4_clear);
EXPORT_SYMBOL(fbcon_iplan2p4_putc);
EXPORT_SYMBOL(fbcon_iplan2p4_putcs);
EXPORT_SYMBOL(fbcon_iplan2p4_revc);
+EXPORT_SYMBOL(fbcon_iplan2p4_clear_margins);
diff --git a/drivers/video/fbcon-iplan2p4.h b/drivers/video/fbcon-iplan2p4.h
deleted file mode 100644
index 6d501a58e..000000000
--- a/drivers/video/fbcon-iplan2p4.h
+++ /dev/null
@@ -1,27 +0,0 @@
- /*
- * 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,
- int dx, int height, int width);
-extern void fbcon_iplan2p4_clear(struct vc_data *conp, struct display *p,
- int sy, int sx, int height, int width);
-extern void fbcon_iplan2p4_putc(struct vc_data *conp, struct display *p, int c,
- int yy, int xx);
-extern void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p,
- const 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 aa2f4d2f1..dbdd56ac8 100644
--- a/drivers/video/fbcon-iplan2p8.c
+++ b/drivers/video/fbcon-iplan2p8.c
@@ -19,8 +19,8 @@
#include <asm/byteorder.h>
-#include "fbcon.h"
-#include "fbcon-iplan2p8.h"
+#include <video/fbcon.h>
+#include <video/fbcon-iplan2p8.h>
/*
@@ -209,18 +209,25 @@ void fbcon_iplan2p8_bmove(struct display *p, int sy, int sx, int dy, int dx,
/* Special (but often used) case: Moving whole lines can be
* done with memmove()
*/
- fast_memmove(p->screen_base + dy * p->next_line * p->fontheight,
- p->screen_base + sy * p->next_line * p->fontheight,
- p->next_line * height * p->fontheight);
+ fast_memmove(p->screen_base + dy * p->next_line * fontheight(p),
+ p->screen_base + sy * p->next_line * fontheight(p),
+ p->next_line * height * fontheight(p));
} else {
int rows, cols;
u8 *src;
u8 *dst;
int bytes = p->next_line;
- int linesize = bytes * p->fontheight;
- u_int colsize = height * p->fontheight;
+ int linesize;
+ u_int colsize;
u_int upwards = (dy < sy) || (dy == sy && dx < sx);
+ if (fontheightlog(p)) {
+ linesize = bytes << fontheightlog(p);
+ colsize = height << fontheightlog(p);
+ } else {
+ linesize = bytes * fontheight(p);
+ colsize = height * fontheight(p);
+ }
if ((sx & 1) == (dx & 1)) {
/* odd->odd or even->even */
@@ -301,18 +308,29 @@ void fbcon_iplan2p8_clear(struct vc_data *conp, struct display *p, int sy,
u8 *start;
int rows;
int bytes = p->next_line;
- int lines = height * p->fontheight;
+ int lines;
u32 size;
u32 cval1, cval2, cval3, cval4, pcval1, pcval2;
expand8ql(attr_bgcol_ec(p,conp), &cval1, &cval2, &cval3, &cval4);
+ if (fontheightlog(p))
+ lines = height << fontheightlog(p);
+ else
+ lines = height * fontheight(p);
+
if (sx == 0 && width * 8 == bytes) {
- offset = sy * bytes * p->fontheight;
+ if (fontheightlog(p))
+ offset = (sy * bytes) << fontheightlog(p);
+ else
+ offset = sy * bytes * fontheight(p);
size = lines * bytes;
memset_even_8p(p->screen_base+offset, size, cval1, cval2, cval3, cval4);
} else {
- offset = (sy * bytes * p->fontheight) + (sx>>1)*16 + (sx & 1);
+ if (fontheightlog(p))
+ offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*16 + (sx & 1);
+ else
+ offset = sy * bytes * fontheight(p) + (sx>>1)*16 + (sx & 1);
start = p->screen_base + offset;
expand8dl(attr_bgcol_ec(p,conp), &pcval1, &pcval2);
@@ -348,14 +366,21 @@ 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;
- dest = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*16 + (xx & 1);
- cdat = p->fontdata + (c & p->charmask) * p->fontheight;
+ if (fontheightlog(p)) {
+ dest = (p->screen_base + ((yy * bytes) << fontheightlog(p)) +
+ (xx>>1)*16 + (xx & 1));
+ cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
+ } else {
+ dest = (p->screen_base + yy * bytes * fontheight(p) +
+ (xx>>1)*16 + (xx & 1));
+ cdat = p->fontdata + (c & p->charmask) * fontheight(p);
+ }
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) {
+ for(rows = fontheight(p) ; rows-- ; dest += bytes) {
fdx = dup4l(*cdat++);
movepl2(dest, (fdx & eorx1) ^ bgx1, (fdx & eorx2) ^ bgx2);
}
@@ -372,8 +397,12 @@ void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p,
u32 eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
bytes = p->next_line;
- dest0 = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*16 +
- (xx & 1);
+ if (fontheightlog(p))
+ dest0 = (p->screen_base + ((yy * bytes) << fontheightlog(p)) +
+ (xx>>1)*16 + (xx & 1));
+ else
+ dest0 = (p->screen_base + yy * bytes * fontheight(p) +
+ (xx>>1)*16 + (xx & 1));
expand8dl(attr_fgcol(p,*s), &fgx1, &fgx2);
expand8dl(attr_bgcol(p,*s), &bgx1, &bgx2);
@@ -389,9 +418,12 @@ void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p,
*/
c = *s++ & p->charmask;
- cdat = p->fontdata + (c * p->fontheight);
+ if (fontheightlog(p))
+ cdat = p->fontdata + (c << fontheightlog(p));
+ else
+ cdat = p->fontdata + c * fontheight(p);
- for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+ for(rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
fdx = dup4l(*cdat++);
movepl2(dest, (fdx & eorx1) ^ bgx1, (fdx & eorx2) ^ bgx2);
}
@@ -405,9 +437,13 @@ void fbcon_iplan2p8_revc(struct display *p, int xx, int yy)
int j;
int bytes;
- dest = p->screen_base + yy * p->fontheight * p->next_line + (xx>>1)*16 +
- (xx & 1);
- j = p->fontheight;
+ if (fontheightlog(p))
+ dest = (p->screen_base + ((yy * p->next_line) << fontheightlog(p)) +
+ (xx>>1)*16 + (xx & 1));
+ else
+ dest = (p->screen_base + yy * p->next_line * fontheight(p) +
+ (xx>>1)*16 + (xx & 1));
+ j = fontheight(p);
bytes = p->next_line;
while (j--) {
@@ -425,6 +461,31 @@ void fbcon_iplan2p8_revc(struct display *p, int xx, int yy)
}
}
+void fbcon_iplan2p8_clear_margins(struct vc_data *conp, struct display *p,
+ int bottom_only)
+{
+ u32 offset;
+ int bytes;
+ int lines;
+ u32 cval1, cval2, cval3, cval4;
+
+/* No need to handle right margin, cannot occur with fontwidth == 8 */
+
+ bytes = p->next_line;
+ if (fontheightlog(p)) {
+ lines = p->var.yres - (conp->vc_rows << fontheightlog(p));
+ offset = ((p->yscroll + conp->vc_rows) * bytes) << fontheightlog(p);
+ } else {
+ lines = p->var.yres - conp->vc_rows * fontheight(p);
+ offset = (p->yscroll + conp->vc_rows) * bytes * fontheight(p);
+ }
+ if (lines) {
+ expand8ql(attr_bgcol_ec(p,conp), &cval1, &cval2, &cval3, &cval4);
+ memset_even_8p(p->screen_base+offset, lines * bytes,
+ cval1, cval2, cval3, cval4);
+ }
+}
+
/*
* `switch' for the low level operations
@@ -433,7 +494,7 @@ 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, NULL,
- NULL, NULL, FONTWIDTH(8)
+ NULL, fbcon_iplan2p8_clear_margins, FONTWIDTH(8)
};
@@ -459,3 +520,4 @@ EXPORT_SYMBOL(fbcon_iplan2p8_clear);
EXPORT_SYMBOL(fbcon_iplan2p8_putc);
EXPORT_SYMBOL(fbcon_iplan2p8_putcs);
EXPORT_SYMBOL(fbcon_iplan2p8_revc);
+EXPORT_SYMBOL(fbcon_iplan2p8_clear_margins);
diff --git a/drivers/video/fbcon-iplan2p8.h b/drivers/video/fbcon-iplan2p8.h
deleted file mode 100644
index ba298f84c..000000000
--- a/drivers/video/fbcon-iplan2p8.h
+++ /dev/null
@@ -1,27 +0,0 @@
- /*
- * 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,
- int dx, int height, int width);
-extern void fbcon_iplan2p8_clear(struct vc_data *conp, struct display *p,
- int sy, int sx, int height, int width);
-extern void fbcon_iplan2p8_putc(struct vc_data *conp, struct display *p, int c,
- int yy, int xx);
-extern void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p,
- const 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 a4bac8fae..f2508e4cb 100644
--- a/drivers/video/fbcon-mac.c
+++ b/drivers/video/fbcon-mac.c
@@ -19,8 +19,8 @@
#include <linux/fb.h>
#include <linux/delay.h>
-#include "fbcon.h"
-#include "fbcon-mac.h"
+#include <video/fbcon.h>
+#include <video/fbcon-mac.h>
/*
@@ -57,24 +57,24 @@ void fbcon_mac_bmove(struct display *p, int sy, int sx, int dy, int dx,
int dl,dr,dt,db,dw,dlo;
int move_up;
- src = (u8 *) (p->screen_base + sy * p->fontheight * p->next_line);
- dest = (u8 *) (p->screen_base + dy * p->fontheight * p->next_line);
+ src = (u8 *) (p->screen_base + sy * fontheight(p) * p->next_line);
+ dest = (u8 *) (p->screen_base + dy * fontheight(p) * p->next_line);
if( sx == 0 && width == p->conp->vc_cols) {
- s = height * p->fontheight * p->next_line;
+ s = height * fontheight(p) * p->next_line;
mymemmove(dest, src, s);
return;
}
- l = sx * p->fontwidth;
- r = l + width * p->fontwidth;
- t = sy * p->fontheight;
- b = t + height * p->fontheight;
+ l = sx * fontwidth(p);
+ r = l + width * fontwidth(p);
+ t = sy * fontheight(p);
+ b = t + height * fontheight(p);
- dl = dx * p->fontwidth;
- dr = dl + width * p->fontwidth;
- dt = dy * p->fontheight;
- db = dt + height * p->fontheight;
+ dl = dx * fontwidth(p);
+ dr = dl + width * fontwidth(p);
+ dt = dy * fontheight(p);
+ db = dt + height * fontheight(p);
/* w is the # pixels between two long-aligned points, left and right */
w = (r&~31) - ((l+31)&~31);
@@ -143,8 +143,8 @@ void fbcon_mac_bmove(struct display *p, int sy, int sx, int dy, int dx,
if (sy <= sx) {
i = b;
move_up = 0;
- src += height * p->fontheight;
- dest += height * p->fontheight;
+ src += height * fontheight(p);
+ dest += height * fontheight(p);
} else {
i = t;
move_up = 1;
@@ -195,22 +195,22 @@ 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->vc_attr);
+ inverse = conp ? attr_reverse(p,conp->vc_attr) : 0;
pixel = inverse ? PIXEL_WHITE_MAC : PIXEL_BLACK_MAC;
- dest = (u8 *) (p->screen_base + sy * p->fontheight * p->next_line);
+ dest = (u8 *) (p->screen_base + sy * fontheight(p) * p->next_line);
if( sx == 0 && width == p->conp->vc_cols) {
- s = height * p->fontheight * p->next_line;
+ s = height * fontheight(p) * p->next_line;
if (inverse)
mymemclear(dest, s);
else
mymemset(dest, s);
}
- l = sx * p->fontwidth;
- r = l + width * p->fontwidth;
- t = sy * p->fontheight;
- b = t + height * p->fontheight;
+ l = sx * fontwidth(p);
+ r = l + width * fontwidth(p);
+ t = sy * fontheight(p);
+ b = t + height * fontheight(p);
/* w is the # pixels between two long-aligned points, left and right */
w = (r&~31) - ((l+31)&~31);
/* lo is the # pixels between the left edge and a long-aligned left pixel */
@@ -272,23 +272,23 @@ void fbcon_mac_putc(struct vc_data *conp, struct display *p, int c, int yy,
u8 d;
int j;
- cdat = p->fontdata+(c&p->charmask)*p->fontheight;
+ cdat = p->fontdata+(c&p->charmask)*fontheight(p);
bold = attr_bold(p,c);
ch_reverse = attr_reverse(p,c);
ch_underline = attr_underline(p,c);
- for (rows = 0; rows < p->fontheight; rows++) {
+ for (rows = 0; rows < fontheight(p); rows++) {
d = *cdat++;
if (!conp->vc_can_do_color) {
- if (ch_underline && rows == (p->fontheight-2))
+ if (ch_underline && rows == (fontheight(p)-2))
d = 0xff;
else if (bold)
d |= d>>1;
if (ch_reverse)
d = ~d;
}
- for (j = 0; j < p->fontwidth; j++) {
- plot_pixel_mac(p, (d & 0x80) >> 7, (xx*p->fontwidth) + j, (yy*p->fontheight) + rows);
+ for (j = 0; j < fontwidth(p); j++) {
+ plot_pixel_mac(p, (d & 0x80) >> 7, (xx*fontwidth(p)) + j, (yy*fontheight(p)) + rows);
d <<= 1;
}
}
@@ -311,9 +311,9 @@ void fbcon_mac_revc(struct display *p, int xx, int yy)
{
u_int rows, j;
- for (rows = 0; rows < p->fontheight; rows++) {
- for (j = 0; j < p->fontwidth; j++) {
- plot_pixel_mac (p, PIXEL_INVERT_MAC, (xx*p->fontwidth)+j, (yy*p->fontheight)+rows);
+ for (rows = 0; rows < fontheight(p); rows++) {
+ for (j = 0; j < fontwidth(p); j++) {
+ plot_pixel_mac (p, PIXEL_INVERT_MAC, (xx*fontwidth(p))+j, (yy*fontheight(p))+rows);
}
}
}
diff --git a/drivers/video/fbcon-mac.h b/drivers/video/fbcon-mac.h
deleted file mode 100644
index 62d2ae6d3..000000000
--- a/drivers/video/fbcon-mac.h
+++ /dev/null
@@ -1,27 +0,0 @@
- /*
- * 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,
- int height, int width);
-extern void fbcon_mac_clear(struct vc_data *conp, struct display *p, int sy,
- int sx, int height, int width);
-extern void fbcon_mac_putc(struct vc_data *conp, struct display *p, int c,
- int yy, int xx);
-extern void fbcon_mac_putcs(struct vc_data *conp, struct display *p,
- const 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 b8f575859..32f1ea8d4 100644
--- a/drivers/video/fbcon-mfb.c
+++ b/drivers/video/fbcon-mfb.c
@@ -15,8 +15,8 @@
#include <linux/string.h>
#include <linux/fb.h>
-#include "fbcon.h"
-#include "fbcon-mfb.h"
+#include <video/fbcon.h>
+#include <video/fbcon-mfb.h>
/*
@@ -39,21 +39,21 @@ void fbcon_mfb_bmove(struct display *p, int sy, int sx, int dy, int dx,
u_int rows;
if (sx == 0 && dx == 0 && width == p->next_line) {
- src = p->screen_base+sy*p->fontheight*width;
- dest = p->screen_base+dy*p->fontheight*width;
- mymemmove(dest, src, height*p->fontheight*width);
+ src = p->screen_base+sy*fontheight(p)*width;
+ dest = p->screen_base+dy*fontheight(p)*width;
+ mymemmove(dest, src, height*fontheight(p)*width);
} else if (dy <= sy) {
- src = p->screen_base+sy*p->fontheight*p->next_line+sx;
- dest = p->screen_base+dy*p->fontheight*p->next_line+dx;
- for (rows = height*p->fontheight; rows--;) {
+ src = p->screen_base+sy*fontheight(p)*p->next_line+sx;
+ dest = p->screen_base+dy*fontheight(p)*p->next_line+dx;
+ for (rows = height*fontheight(p); rows--;) {
mymemmove(dest, src, width);
src += p->next_line;
dest += p->next_line;
}
} else {
- src = p->screen_base+((sy+height)*p->fontheight-1)*p->next_line+sx;
- dest = p->screen_base+((dy+height)*p->fontheight-1)*p->next_line+dx;
- for (rows = height*p->fontheight; rows--;) {
+ src = p->screen_base+((sy+height)*fontheight(p)-1)*p->next_line+sx;
+ dest = p->screen_base+((dy+height)*fontheight(p)-1)*p->next_line+dx;
+ for (rows = height*fontheight(p); rows--;) {
mymemmove(dest, src, width);
src -= p->next_line;
dest -= p->next_line;
@@ -66,17 +66,18 @@ void fbcon_mfb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
{
u8 *dest;
u_int rows;
+ int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
- dest = p->screen_base+sy*p->fontheight*p->next_line+sx;
+ dest = p->screen_base+sy*fontheight(p)*p->next_line+sx;
if (sx == 0 && width == p->next_line) {
- if (attr_reverse(p,conp->vc_attr))
- mymemset(dest, height*p->fontheight*width);
+ if (inverse)
+ mymemset(dest, height*fontheight(p)*width);
else
- mymemclear(dest, height*p->fontheight*width);
+ mymemclear(dest, height*fontheight(p)*width);
} else
- for (rows = height*p->fontheight; rows--; dest += p->next_line)
- if (attr_reverse(p,conp->vc_attr))
+ for (rows = height*fontheight(p); rows--; dest += p->next_line)
+ if (inverse)
mymemset(dest, width);
else
mymemclear_small(dest, width);
@@ -89,13 +90,13 @@ void fbcon_mfb_putc(struct vc_data *conp, struct display *p, int c, int yy,
u_int rows, bold, revs, underl;
u8 d;
- dest = p->screen_base+yy*p->fontheight*p->next_line+xx;
- cdat = p->fontdata+(c&p->charmask)*p->fontheight;
+ dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
+ cdat = p->fontdata+(c&p->charmask)*fontheight(p);
bold = attr_bold(p,c);
revs = attr_reverse(p,c);
underl = attr_underline(p,c);
- for (rows = p->fontheight; rows--; dest += p->next_line) {
+ for (rows = fontheight(p); rows--; dest += p->next_line) {
d = *cdat++;
if (underl && !rows)
d = 0xff;
@@ -115,7 +116,7 @@ void fbcon_mfb_putcs(struct vc_data *conp, struct display *p,
u8 d;
u16 c;
- dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx;
+ dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
bold = attr_bold(p,*s);
revs = attr_reverse(p,*s);
underl = attr_underline(p,*s);
@@ -123,8 +124,8 @@ void fbcon_mfb_putcs(struct vc_data *conp, struct display *p,
while (count--) {
c = *s++ & p->charmask;
dest = dest0++;
- cdat = p->fontdata+c*p->fontheight;
- for (rows = p->fontheight; rows--; dest += p->next_line) {
+ cdat = p->fontdata+c*fontheight(p);
+ for (rows = fontheight(p); rows--; dest += p->next_line) {
d = *cdat++;
if (underl && !rows)
d = 0xff;
@@ -142,11 +143,33 @@ void fbcon_mfb_revc(struct display *p, int xx, int yy)
u8 *dest;
u_int rows;
- dest = p->screen_base+yy*p->fontheight*p->next_line+xx;
- for (rows = p->fontheight; rows--; dest += p->next_line)
+ dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
+ for (rows = fontheight(p); rows--; dest += p->next_line)
*dest = ~*dest;
}
+void fbcon_mfb_clear_margins(struct vc_data *conp, struct display *p,
+ int bottom_only)
+{
+ u8 *dest;
+ int height, bottom;
+ int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
+
+ /* XXX Need to handle right margin? */
+
+ height = p->var.yres - conp->vc_rows * fontheight(p);
+ if (!height)
+ return;
+ bottom = conp->vc_rows + p->yscroll;
+ if (bottom >= p->vrows)
+ bottom -= p->vrows;
+ dest = p->screen_base + bottom * fontheight(p) * p->next_line;
+ if (inverse)
+ mymemset(dest, height * p->next_line);
+ else
+ mymemclear(dest, height * p->next_line);
+}
+
/*
* `switch' for the low level operations
@@ -154,7 +177,8 @@ 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, NULL, NULL, NULL, FONTWIDTH(8)
+ fbcon_mfb_putcs, fbcon_mfb_revc, NULL, NULL, fbcon_mfb_clear_margins,
+ FONTWIDTH(8)
};
@@ -180,3 +204,4 @@ EXPORT_SYMBOL(fbcon_mfb_clear);
EXPORT_SYMBOL(fbcon_mfb_putc);
EXPORT_SYMBOL(fbcon_mfb_putcs);
EXPORT_SYMBOL(fbcon_mfb_revc);
+EXPORT_SYMBOL(fbcon_mfb_clear_margins);
diff --git a/drivers/video/fbcon-mfb.h b/drivers/video/fbcon-mfb.h
deleted file mode 100644
index 77f312e31..000000000
--- a/drivers/video/fbcon-mfb.h
+++ /dev/null
@@ -1,27 +0,0 @@
- /*
- * 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,
- int height, int width);
-extern void fbcon_mfb_clear(struct vc_data *conp, struct display *p, int sy,
- int sx, int height, int width);
-extern void fbcon_mfb_putc(struct vc_data *conp, struct display *p, int c,
- int yy, int xx);
-extern void fbcon_mfb_putcs(struct vc_data *conp, struct display *p,
- const 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
index 3ea8a5234..fa4d387b8 100644
--- a/drivers/video/fbcon-vga.c
+++ b/drivers/video/fbcon-vga.c
@@ -18,8 +18,8 @@
#include <asm/io.h>
-#include "fbcon.h"
-#include "fbcon-vga.h"
+#include <video/fbcon.h>
+#include <video/fbcon-vga.h>
/*
diff --git a/drivers/video/fbcon-vga.h b/drivers/video/fbcon-vga.h
deleted file mode 100644
index 7d62e213c..000000000
--- a/drivers/video/fbcon-vga.h
+++ /dev/null
@@ -1,27 +0,0 @@
- /*
- * 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 c2b7abd51..9bdc9020b 100644
--- a/drivers/video/fbcon.c
+++ b/drivers/video/fbcon.c
@@ -29,6 +29,8 @@
* added by
* Jakub Jelinek (jj@ultra.linux.cz)
*
+ * Random hacking by Martin Mares <mj@ucw.cz>
+ *
*
* The low level operations for the various display memory organizations are
* now in separate source files.
@@ -54,8 +56,6 @@
#undef FBCONDEBUG
-#define FLASHING_CURSOR 1
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -94,9 +94,9 @@
#define INCLUDE_LINUX_LOGO_DATA
#include <asm/linux_logo.h>
-#include "fbcon.h"
-#include "fbcon-mac.h" /* for 6x11 font on mac */
-#include "font.h"
+#include <video/fbcon.h>
+#include <video/fbcon-mac.h> /* for 6x11 font on mac */
+#include <video/font.h>
#ifdef FBCONDEBUG
# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
@@ -112,6 +112,14 @@ struct display fb_display[MAX_NR_CONSOLES];
static int logo_lines;
static int logo_shown = -1;
+#define REFCOUNT(fd) (((int *)(fd))[-1])
+#define FNTSIZE(fd) (((int *)(fd))[-2])
+#define FNTCHARCNT(fd) (((int *)(fd))[-3])
+#define FNTSUM(fd) (((int *)(fd))[-4])
+#define FONT_EXTRA_WORDS 4
+
+static void fbcon_free_font(struct display *p);
+
/*
* Emmanuel: fbcon will now use a hardware cursor if the
* low-level driver provides a non-NULL dispsw->cursor pointer,
@@ -120,12 +128,12 @@ static int logo_shown = -1;
* if dispsw->cursor is NULL, use Atari alike software cursor
*/
-#if FLASHING_CURSOR
static int cursor_drawn = 0;
-#define CURSOR_DRAW_DELAY (2)
+#define CURSOR_DRAW_DELAY (1)
/* # VBL ints between cursor state changes */
+#define ARM_CURSOR_BLINK_RATE (10)
#define AMIGA_CURSOR_BLINK_RATE (20)
#define ATARI_CURSOR_BLINK_RATE (42)
#define MAC_CURSOR_BLINK_RATE (32)
@@ -135,16 +143,12 @@ static int vbl_cursor_cnt = 0;
static int cursor_on = 0;
static int cursor_blink_rate;
-static __inline__ void CURSOR_UNDRAWN(void)
+static inline void cursor_undrawn(void)
{
vbl_cursor_cnt = 0;
cursor_drawn = 0;
}
-#endif
-/*
- * Scroll Method
- */
#define divides(a, b) ((!(a) || (b)%(a)) ? 0 : 1)
@@ -180,9 +184,7 @@ static int fbcon_scrolldelta(struct vc_data *conp, int lines);
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);
static __inline__ void ywrap_up(int unit, struct vc_data *conp,
struct display *p, int count);
@@ -197,8 +199,6 @@ static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx,
static int fbcon_show_logo(void);
-#if FLASHING_CURSOR
-
#ifdef CONFIG_MAC
/*
* On the Macintoy, there may or may not be a working VBL int. We need to prob
@@ -225,13 +225,12 @@ static void cursor_timer_handler(unsigned long dev_addr)
cursor_timer.next = cursor_timer.next = NULL;
add_timer(&cursor_timer);
}
-#endif
/*
* Low Level Operations
*/
-static struct display_switch fbcon_dummy;
+struct display_switch fbcon_dummy;
/* NOTE: fbcon cannot be __initfunc: it may be called from take_over_console later */
@@ -271,39 +270,43 @@ static const char *fbcon_startup(void)
* probe for VBL interrupts.
*/
if (MACH_IS_MAC) {
- int ct = 0;
- /*
- * Probe for VBL: set temp. handler ...
- */
- irqres = request_irq(IRQ_MAC_VBL, fbcon_vbl_detect, 0,
- "console/cursor", fbcon_vbl_detect);
- /*
- * ... and spin for 20 ms ...
- */
- while (!vbl_detected && ++ct<1000)
- udelay(20);
+ int ct = 0;
+ /*
+ * Probe for VBL: set temp. handler ...
+ */
+ irqres = request_irq(IRQ_MAC_VBL, fbcon_vbl_detect, 0,
+ "console/cursor", fbcon_vbl_detect);
+ vbl_detected = 0;
+
+ /*
+ * ... and spin for 20 ms ...
+ */
+ while (!vbl_detected && ++ct<1000)
+ udelay(20);
- if(ct==1000)
- printk("fbcon_startup: No VBL detected, using timer based cursor.\n");
+ if(ct==1000)
+ printk("fbcon_startup: No VBL detected, using timer based cursor.\n");
- if (vbl_detected) {
- /*
- * interrupt based cursor ok
- */
- cursor_blink_rate = MAC_CURSOR_BLINK_RATE;
- irqres = request_irq(IRQ_MAC_VBL, fbcon_vbl_handler, 0,
- "console/cursor", fbcon_vbl_handler);
- } else {
- /*
- * VBL not detected: fall through, use timer based cursor
- */
- irqres = 1;
- /* free interrupt here ?? */
- }
+ free_irq(IRQ_MAC_VBL, fbcon_vbl_detect);
+
+ if (vbl_detected) {
+ /*
+ * interrupt based cursor ok
+ */
+ cursor_blink_rate = MAC_CURSOR_BLINK_RATE;
+ irqres = request_irq(IRQ_MAC_VBL, fbcon_vbl_handler, 0,
+ "console/cursor", fbcon_vbl_handler);
+ } else {
+ /*
+ * VBL not detected: fall through, use timer based cursor
+ */
+ irqres = 1;
+ }
}
#endif /* CONFIG_MAC */
#if defined(__arm__) && defined(IRQ_VSYNCPULSE)
+ cursor_blink_rate = ARM_CURSOR_BLINK_RATE;
irqres = request_irq(IRQ_VSYNCPULSE, fbcon_vbl_handler, SA_SHIRQ,
"console/cursor", fbcon_vbl_handler);
#endif
@@ -329,9 +332,6 @@ static void fbcon_init(struct vc_data *conp, int init)
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);
@@ -340,7 +340,17 @@ static void fbcon_init(struct vc_data *conp, int init)
fb_display[unit].var.bits_per_pixel);
fb_display[unit].conp = conp;
fb_display[unit].fb_info = info;
+ /* clear out the cmap so we don't have dangling pointers */
+ fb_display[unit].cmap.len = 0;
+ fb_display[unit].cmap.red = 0;
+ fb_display[unit].cmap.green = 0;
+ fb_display[unit].cmap.blue = 0;
+ fb_display[unit].cmap.transp = 0;
fbcon_setup(unit, init, !init);
+ /* Must be done after fbcon_setup to prevent excess updates */
+ conp->vc_display_fg = &info->display_fg;
+ if (!info->display_fg)
+ info->display_fg = conp;
}
@@ -349,7 +359,8 @@ static void fbcon_deinit(struct vc_data *conp)
int unit = conp->vc_num;
struct display *p = &fb_display[unit];
- p->dispsw = NULL;
+ fbcon_free_font(p);
+ p->dispsw = &fbcon_dummy;
p->conp = 0;
}
@@ -364,29 +375,34 @@ static int fbcon_changevar(int con)
static __inline__ void updatescrollmode(struct display *p)
{
- if (p->scrollmode == SCROLL_YREDRAW)
+ int m;
+ if (p->scrollmode & __SCROLL_YFIXED)
return;
- if (divides(p->ywrapstep, p->fontheight) &&
- divides(p->fontheight, p->var.yres_virtual))
- p->scrollmode = SCROLL_YWRAP;
- else if (divides(p->ypanstep, p->fontheight) &&
- p->var.yres_virtual >= p->var.yres+p->fontheight)
- p->scrollmode = SCROLL_YPAN;
+ if (divides(p->ywrapstep, fontheight(p)) &&
+ divides(fontheight(p), p->var.yres_virtual))
+ m = __SCROLL_YWRAP;
+ else if (divides(p->ypanstep, fontheight(p)) &&
+ p->var.yres_virtual >= p->var.yres+fontheight(p))
+ m = __SCROLL_YPAN;
+ else if (p->scrollmode & __SCROLL_YNOMOVE)
+ m = __SCROLL_YREDRAW;
else
- p->scrollmode = SCROLL_YMOVE;
+ m = __SCROLL_YMOVE;
+ p->scrollmode = (p->scrollmode & ~__SCROLL_YMASK) | m;
}
static void fbcon_font_widths(struct display *p)
{
int i;
- p->fontwidthlog = 0;
+
+ p->_fontwidthlog = 0;
for (i = 2; i <= 6; i++)
- if (p->fontwidth == (1 << i))
- p->fontwidthlog = i;
- p->fontheightlog = 0;
+ if (fontwidth(p) == (1 << i))
+ p->_fontwidthlog = i;
+ p->_fontheightlog = 0;
for (i = 2; i <= 6; i++)
- if (p->fontheight == (1 << i))
- p->fontheightlog = i;
+ if (fontheight(p) == (1 << i))
+ p->_fontheightlog = i;
}
#define fontwidthvalid(p,w) ((p)->dispsw->fontwidthmask & FONTWIDTH(w))
@@ -398,22 +414,52 @@ static void fbcon_setup(int con, int init, int logo)
int nr_rows, nr_cols;
int old_rows, old_cols;
unsigned short *save = NULL, *r, *q;
- /* Only if not module */
- int initmem_freed = 1;
+ int i, charcnt = 256;
struct fbcon_font_desc *font;
- if (con != fg_console || initmem_freed || p->type == FB_TYPE_TEXT)
+
+ if (con != fg_console || (p->fb_info->flags & FBINFO_FLAG_MODULE) ||
+ p->type == FB_TYPE_TEXT)
logo = 0;
p->var.xoffset = p->var.yoffset = p->yscroll = 0; /* reset wrap/pan */
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++)
+ if (i != con && fb_display[i].fb_info == p->fb_info &&
+ fb_display[i].conp && fb_display[i].fontdata)
+ break;
+
+ fbcon_free_font(p);
+ if (i < MAX_NR_CONSOLES) {
+ struct display *q = &fb_display[i];
+
+ if (fontwidthvalid(p,fontwidth(q))) {
+ /* If we are not the first console on this
+ fb, copy the font from that console */
+ p->_fontwidth = q->_fontwidth;
+ p->_fontheight = q->_fontheight;
+ p->_fontwidthlog = q->_fontwidthlog;
+ p->_fontheightlog = q->_fontheightlog;
+ p->fontdata = q->fontdata;
+ p->userfont = q->userfont;
+ if (p->userfont) {
+ REFCOUNT(p->fontdata)++;
+ charcnt = FNTCHARCNT(p->fontdata);
+ }
+ con_copy_unimap(con, i);
+ }
+ }
- if (!p->fb_info->fontname[0] ||
- !(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)) {
+ if (!p->fontdata) {
+ if (!p->fb_info->fontname[0] ||
+ !(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,fontwidth(p))) {
#ifdef CONFIG_MAC
if (MACH_IS_MAC)
/* ++Geert: hack to make 6x11 fonts work on mac */
@@ -422,26 +468,26 @@ static void fbcon_setup(int con, int init, int logo)
#endif
{
/* ++Geert: changed from panic() to `correct and continue' */
- printk(KERN_ERR "fbcon_setup: No support for fontwidth %d\n", p->fontwidth);
+ printk(KERN_ERR "fbcon_setup: No support for fontwidth %d\n", fontwidth(p));
p->dispsw = &fbcon_dummy;
}
}
if (p->dispsw->set_font)
- p->dispsw->set_font(p, p->fontwidth, p->fontheight);
+ p->dispsw->set_font(p, fontwidth(p), fontheight(p));
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;
+ nr_cols = p->var.xres/fontwidth(p);
+ nr_rows = p->var.yres/fontheight(p);
if (logo) {
/* Need to make room for the logo */
int cnt;
int step;
- logo_lines = (LOGO_H + p->fontheight - 1) / p->fontheight;
+ logo_lines = (LOGO_H + fontheight(p) - 1) / fontheight(p);
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++)
@@ -454,7 +500,7 @@ static void fbcon_setup(int con, int init, int logo)
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);
+ scr_memcpyw_to(save + cnt * nr_cols, r, 2 * i);
r = q;
}
}
@@ -483,42 +529,53 @@ static void fbcon_setup(int con, int init, int logo)
conp->vc_cols = nr_cols;
conp->vc_rows = nr_rows;
}
- p->vrows = p->var.yres_virtual/p->fontheight;
+ p->vrows = p->var.yres_virtual/fontheight(p);
+ if ((p->var.yres % fontheight(p)) &&
+ (p->var.yres_virtual % fontheight(p) < p->var.yres % fontheight(p)))
+ p->vrows--;
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;
+ conp->vc_complement_mask = conp->vc_can_do_color ? 0x7700 : 0x0800;
+ if (charcnt == 256) {
+ p->conp->vc_hi_font_mask = 0;
+ p->fgshift = 8;
+ p->bgshift = 12;
+ p->charmask = 0xff;
+ } else {
+ p->conp->vc_hi_font_mask = 0x100;
+ p->conp->vc_complement_mask <<= 1;
+ p->fgshift = 9;
+ p->bgshift = 13;
+ p->charmask = 0x1ff;
+ }
- if (!p->dispsw) {
+ if (p->dispsw == &fbcon_dummy)
printk(KERN_WARNING "fbcon_setup: type %d (aux %d, depth %d) not "
"supported\n", p->type, p->type_aux, p->var.bits_per_pixel);
- p->dispsw = &fbcon_dummy;
- }
p->dispsw->setup(p);
p->fgcol = p->var.bits_per_pixel > 2 ? 7 : (1<<p->var.bits_per_pixel)-1;
p->bgcol = 0;
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 (conp->vc_cols != nr_cols || conp->vc_rows != nr_rows)
+ vc_resize_con(nr_rows, nr_cols, con);
+ else if (CON_IS_VISIBLE(conp) &&
+ vt_cons[conp->vc_num]->vc_mode == KD_TEXT) {
+ if (p->dispsw->clear_margins)
+ p->dispsw->clear_margins(conp, p, 0);
+ update_screen(con);
+ }
if (save) {
q = (unsigned short *)(conp->vc_origin + conp->vc_size_row * old_rows);
- scr_memcpyw(q, save, logo_lines * nr_cols * 2);
+ scr_memcpyw_from(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 */
+ logo_shown = -2;
conp->vc_top = logo_lines;
}
}
@@ -574,7 +631,7 @@ static void fbcon_clear(struct vc_data *conp, int sy, int sx, int height,
if ((sy <= p->cursor_y) && (p->cursor_y < sy+height) &&
(sx <= p->cursor_x) && (p->cursor_x < sx+width)) {
- CURSOR_UNDRAWN();
+ cursor_undrawn();
redraw_cursor = 1;
}
@@ -601,9 +658,12 @@ static void fbcon_putc(struct vc_data *conp, int c, int ypos, int xpos)
if (!p->can_soft_blank && console_blanked)
return;
+
+ if (vt_cons[unit]->vc_mode != KD_TEXT)
+ return;
if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) {
- CURSOR_UNDRAWN();
+ cursor_undrawn();
redraw_cursor = 1;
}
@@ -624,9 +684,12 @@ static void fbcon_putcs(struct vc_data *conp, const unsigned short *s, int count
if (!p->can_soft_blank && console_blanked)
return;
+ if (vt_cons[unit]->vc_mode != KD_TEXT)
+ return;
+
if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) &&
(p->cursor_x < (xpos + count))) {
- CURSOR_UNDRAWN();
+ cursor_undrawn();
redraw_cursor = 1;
}
p->dispsw->putcs(conp, p, s, count, real_y(p, ypos), xpos);
@@ -653,29 +716,28 @@ static void fbcon_cursor(struct vc_data *conp, int mode)
(mode == CM_ERASE) == !cursor_on)
return;
- 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;
- }
+ 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;
+ }
}
-#if FLASHING_CURSOR
static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp)
{
struct display *p;
@@ -691,7 +753,6 @@ static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp)
vbl_cursor_cnt = cursor_blink_rate;
}
}
-#endif
static int scrollback_phys_max = 0;
static int scrollback_max = 0;
@@ -704,7 +765,7 @@ static __inline__ void ywrap_up(int unit, struct vc_data *conp,
if (p->yscroll >= p->vrows) /* Deal with wrap */
p->yscroll -= p->vrows;
p->var.xoffset = 0;
- p->var.yoffset = p->yscroll*p->fontheight;
+ p->var.yoffset = p->yscroll*fontheight(p);
p->var.vmode |= FB_VMODE_YWRAP;
p->fb_info->updatevar(unit, p->fb_info);
scrollback_max += count;
@@ -721,7 +782,7 @@ static __inline__ void ywrap_down(int unit, struct vc_data *conp,
if (p->yscroll < 0) /* Deal with wrap */
p->yscroll += p->vrows;
p->var.xoffset = 0;
- p->var.yoffset = p->yscroll*p->fontheight;
+ p->var.yoffset = p->yscroll*fontheight(p);
p->var.vmode |= FB_VMODE_YWRAP;
p->fb_info->updatevar(unit, p->fb_info);
scrollback_max -= count;
@@ -741,9 +802,11 @@ static __inline__ void ypan_up(int unit, struct vc_data *conp,
p->yscroll -= p->vrows-conp->vc_rows;
}
p->var.xoffset = 0;
- p->var.yoffset = p->yscroll*p->fontheight;
+ p->var.yoffset = p->yscroll*fontheight(p);
p->var.vmode &= ~FB_VMODE_YWRAP;
p->fb_info->updatevar(unit, p->fb_info);
+ if (p->dispsw->clear_margins)
+ p->dispsw->clear_margins(conp, p, 1);
scrollback_max += count;
if (scrollback_max > scrollback_phys_max)
scrollback_max = scrollback_phys_max;
@@ -761,9 +824,11 @@ static __inline__ void ypan_down(int unit, struct vc_data *conp,
p->yscroll += p->vrows-conp->vc_rows;
}
p->var.xoffset = 0;
- p->var.yoffset = p->yscroll*p->fontheight;
+ p->var.yoffset = p->yscroll*fontheight(p);
p->var.vmode &= ~FB_VMODE_YWRAP;
p->fb_info->updatevar(unit, p->fb_info);
+ if (p->dispsw->clear_margins)
+ p->dispsw->clear_margins(conp, p, 1);
scrollback_max -= count;
if (scrollback_max < 0)
scrollback_max = 0;
@@ -777,6 +842,7 @@ static void fbcon_redraw(struct vc_data *conp, struct display *p,
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 *)
@@ -790,14 +856,16 @@ static void fbcon_redraw(struct vc_data *conp, struct display *p,
if (attr != (c & 0xff00)) {
attr = c & 0xff00;
if (s > start) {
- p->dispsw->putcs(conp, p, start, s - start, line, x);
+ p->dispsw->putcs(conp, p, start, s - start,
+ real_y(p, 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);
+ p->dispsw->putcs(conp, p, start, s - start,
+ real_y(p, line), x);
x += s - start + 1;
start = s + 1;
} else {
@@ -810,7 +878,7 @@ static void fbcon_redraw(struct vc_data *conp, struct display *p,
d++;
} while (s < le);
if (s > start)
- p->dispsw->putcs(conp, p, start, s - start, line, x);
+ p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x);
if (offset > 0)
line++;
else {
@@ -828,6 +896,7 @@ void fbcon_redraw_bmove(struct display *p, int sy, int sx, int dy, int dx, int h
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 *)
@@ -880,7 +949,7 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir,
if (!p->can_soft_blank && console_blanked)
return 0;
- if (!count)
+ if (!count || vt_cons[unit]->vc_mode != KD_TEXT)
return 0;
fbcon_cursor(conp, CM_ERASE);
@@ -895,133 +964,119 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir,
case SM_UP:
if (count > conp->vc_rows) /* Maximum realistic size */
count = conp->vc_rows;
- if (vt_cons[unit]->vc_mode == KD_TEXT)
- switch (p->scrollmode) {
- case SCROLL_YWRAP:
- if (b-t-count > 3*conp->vc_rows>>2) {
- if (t > 0)
- fbcon_bmove(conp, 0, 0, count, 0, t,
- conp->vc_cols);
- ywrap_up(unit, conp, p, count);
- if (conp->vc_rows-b > 0)
- fbcon_bmove(conp, b-count, 0, b, 0,
- conp->vc_rows-b, conp->vc_cols);
- } else
- fbcon_bmove(conp, t+count, 0, t, 0, b-t-count,
- conp->vc_cols);
- fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
- break;
-
- case SCROLL_YPAN:
- 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);
- ypan_up(unit, conp, p, count);
- if (conp->vc_rows-b > 0)
- fbcon_bmove(conp, b-count, 0, b, 0,
- conp->vc_rows-b, conp->vc_cols);
- } else
- fbcon_bmove(conp, t+count, 0, t, 0, b-t-count,
- conp->vc_cols);
- fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
- break;
-
- case SCROLL_YMOVE:
- p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count,
- conp->vc_cols);
- 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);
+ switch (p->scrollmode & __SCROLL_YMASK) {
+ case __SCROLL_YMOVE:
+ p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count,
+ conp->vc_cols);
+ p->dispsw->clear(conp, p, b-count, 0, count,
+ conp->vc_cols);
+ break;
+
+ case __SCROLL_YWRAP:
+ if (b-t-count > 3*conp->vc_rows>>2) {
+ if (t > 0)
+ fbcon_bmove(conp, 0, 0, count, 0, t,
+ conp->vc_cols);
+ ywrap_up(unit, conp, p, count);
+ if (conp->vc_rows-b > 0)
+ fbcon_bmove(conp, b-count, 0, b, 0,
+ conp->vc_rows-b, conp->vc_cols);
+ } else if (p->scrollmode & __SCROLL_YPANREDRAW)
+ goto redraw_up;
+ else
+ fbcon_bmove(conp, t+count, 0, t, 0, b-t-count,
+ conp->vc_cols);
+ fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
+ break;
+
+ case __SCROLL_YPAN:
+ 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);
+ ypan_up(unit, conp, p, count);
+ if (conp->vc_rows-b > 0)
+ fbcon_bmove(conp, b-count, 0, b, 0,
+ conp->vc_rows-b, conp->vc_cols);
+ } else if (p->scrollmode & __SCROLL_YPANREDRAW)
+ goto redraw_up;
+ else
+ fbcon_bmove(conp, t+count, 0, t, 0, b-t-count,
+ conp->vc_cols);
fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
+ break;
+
+ case __SCROLL_YREDRAW:
+ redraw_up:
+ fbcon_redraw(conp, p, t, b-t-count, count*conp->vc_cols);
+ p->dispsw->clear(conp, p, real_y(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;
}
break;
case SM_DOWN:
if (count > conp->vc_rows) /* Maximum realistic size */
count = conp->vc_rows;
- if (vt_cons[unit]->vc_mode == KD_TEXT)
- switch (p->scrollmode) {
- case SCROLL_YWRAP:
- if (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);
- ywrap_down(unit, conp, p, count);
- if (t > 0)
- fbcon_bmove(conp, count, 0, 0, 0, t,
- conp->vc_cols);
- } else
- fbcon_bmove(conp, t, 0, t+count, 0, b-t-count,
- conp->vc_cols);
- fbcon_clear(conp, t, 0, count, conp->vc_cols);
- break;
-
- case SCROLL_YPAN:
- 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);
- ypan_down(unit, conp, p, count);
- if (t > 0)
- fbcon_bmove(conp, count, 0, 0, 0, t,
- conp->vc_cols);
- } else
- fbcon_bmove(conp, t, 0, t+count, 0, b-t-count,
- conp->vc_cols);
- fbcon_clear(conp, t, 0, count, conp->vc_cols);
- break;
-
- case SCROLL_YMOVE:
- p->dispsw->bmove(p, t, 0, t+count, 0, b-t-count,
- 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 {
- /*
- * Fixed bmove() should end Arno's frustration with copying?
- * Confucius says:
- * Man who copies in wrong direction, end up with trashed
- * data
- */
- fbcon_bmove(conp, t, 0, t+count, 0, b-t-count, conp->vc_cols);
+ switch (p->scrollmode & __SCROLL_YMASK) {
+ case __SCROLL_YMOVE:
+ p->dispsw->bmove(p, t, 0, t+count, 0, b-t-count,
+ conp->vc_cols);
+ p->dispsw->clear(conp, p, t, 0,
+ count, conp->vc_cols);
+ break;
+
+ case __SCROLL_YWRAP:
+ if (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);
+ ywrap_down(unit, conp, p, count);
+ if (t > 0)
+ fbcon_bmove(conp, count, 0, 0, 0, t,
+ conp->vc_cols);
+ } else if (p->scrollmode & __SCROLL_YPANREDRAW)
+ goto redraw_down;
+ else
+ fbcon_bmove(conp, t, 0, t+count, 0, b-t-count,
+ conp->vc_cols);
fbcon_clear(conp, t, 0, count, conp->vc_cols);
- }
- break;
+ break;
- case SM_LEFT:
- fbcon_bmove(conp, 0, t+count, 0, t, conp->vc_rows, b-t-count);
- fbcon_clear(conp, 0, b-count, conp->vc_rows, count);
- break;
+ case __SCROLL_YPAN:
+ 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);
+ ypan_down(unit, conp, p, count);
+ if (t > 0)
+ fbcon_bmove(conp, count, 0, 0, 0, t,
+ conp->vc_cols);
+ } else if (p->scrollmode & __SCROLL_YPANREDRAW)
+ goto redraw_down;
+ else
+ fbcon_bmove(conp, t, 0, t+count, 0, b-t-count,
+ conp->vc_cols);
+ fbcon_clear(conp, t, 0, count, conp->vc_cols);
+ break;
- case SM_RIGHT:
- fbcon_bmove(conp, 0, t, 0, t+count, conp->vc_rows, b-t-count);
- fbcon_clear(conp, 0, t, conp->vc_rows, count);
- break;
+ case __SCROLL_YREDRAW:
+ redraw_down:
+ fbcon_redraw(conp, p, b - 1, b-t-count, -count*conp->vc_cols);
+ p->dispsw->clear(conp, p, real_y(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;
+ }
}
return 0;
}
@@ -1100,12 +1155,12 @@ static int fbcon_switch(struct vc_data *conp)
conp2->vc_top = 0;
logo_shown = -1;
}
- p->var.yoffset = p->yscroll*p->fontheight;
- switch (p->scrollmode) {
- case SCROLL_YWRAP:
+ p->var.yoffset = p->yscroll = 0;
+ switch (p->scrollmode & __SCROLL_YMASK) {
+ case __SCROLL_YWRAP:
scrollback_phys_max = p->vrows-conp->vc_rows;
break;
- case SCROLL_YPAN:
+ case __SCROLL_YPAN:
scrollback_phys_max = p->vrows-2*conp->vc_rows;
if (scrollback_phys_max < 0)
scrollback_phys_max = 0;
@@ -1118,9 +1173,17 @@ static int fbcon_switch(struct vc_data *conp)
scrollback_current = 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);
+ (*info->switch_con)(unit, info);
+ if (p->dispsw->clear_margins && vt_cons[unit]->vc_mode == KD_TEXT)
+ p->dispsw->clear_margins(conp, p, 0);
+ if (logo_shown == -2) {
+ logo_shown = fg_console;
+ fbcon_show_logo(); /* This is protected above by initmem_freed */
+ update_region(fg_console,
+ conp->vc_origin + conp->vc_size_row * conp->vc_top,
+ conp->vc_size_row * (conp->vc_bottom - conp->vc_top) / 2);
+ return 0;
+ }
return 1;
}
@@ -1151,7 +1214,7 @@ static int fbcon_blank(struct vc_data *conp, int blank)
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);
+ p->dispsw->clear(conp, p, 0, 0, conp->vc_rows, conp->vc_cols);
return 0;
} else {
/* Tell console.c that it has to restore the screen itself */
@@ -1162,67 +1225,77 @@ static int fbcon_blank(struct vc_data *conp, int blank)
return 0;
}
+static void fbcon_free_font(struct display *p)
+{
+ if (p->userfont && p->fontdata &&
+ (--REFCOUNT(p->fontdata) == 0))
+ kfree(p->fontdata - FONT_EXTRA_WORDS*sizeof(int));
+ p->fontdata = NULL;
+ p->userfont = 0;
+}
static inline int fbcon_get_font(int unit, struct console_font_op *op)
{
struct display *p = &fb_display[unit];
u8 *data = op->data;
+ u8 *fontdata = p->fontdata;
int i, j;
#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
- if (p->fontwidth != 8) return -EINVAL;
+ if (fontwidth(p) != 8) return -EINVAL;
#endif
- op->width = p->fontwidth;
- op->height = p->fontheight;
+ op->width = fontwidth(p);
+ op->height = fontheight(p);
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;
+ for (j = 0; j < fontheight(p); j++)
+ *data++ = *fontdata++;
+ memset(data, 0, 32-j);
+ data += 32 - j;
}
}
#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];
+ for (j = 0; j < fontheight(p); j++) {
+ *data++ = *(u16 *)fontdata >> 8;
+ *data++ = *(u16 *)fontdata;
+ fontdata += sizeof(u16);
}
- data += 2 * (32 - p->fontheight);
+ memset(data, 0, 2*(32-j));
+ data += 2 * (32 - j);
}
} 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;
+ for (j = 0; j < fontheight(p); j++) {
+ *data++ = *(u32 *)fontdata >> 24;
+ *data++ = *(u32 *)fontdata >> 16;
+ *data++ = *(u32 *)fontdata >> 8;
+ fontdata += sizeof(u32);
}
- data += 3 * (32 - p->fontheight);
+ memset(data, 0, 3*(32-j));
+ data += 3 * (32 - j);
}
} 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];
+ for (j = 0; j < fontheight(p); j++) {
+ *data++ = *(u32 *)fontdata >> 24;
+ *data++ = *(u32 *)fontdata >> 16;
+ *data++ = *(u32 *)fontdata >> 8;
+ *data++ = *(u32 *)fontdata;
+ fontdata += sizeof(u32);
}
- data += 4 * (32 - p->fontheight);
+ memset(data, 0, 4*(32-j));
+ data += 4 * (32 - j);
}
}
#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_do_set_font(int unit, struct console_font_op *op, u8 *data, int userfont)
{
struct display *p = &fb_display[unit];
@@ -1233,12 +1306,12 @@ static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int
char *old_data = NULL;
if (!fontwidthvalid(p,w)) {
- if (userfont)
- kfree(data);
+ if (userfont && op->op != KD_FONT_OP_COPY)
+ kfree(data - FONT_EXTRA_WORDS*sizeof(int));
return -ENXIO;
}
- resize = (w != p->fontwidth) || (h != p->fontheight);
+ resize = (w != fontwidth(p)) || (h != fontheight(p));
if (p->userfont)
old_data = p->fontdata;
if (userfont)
@@ -1248,8 +1321,8 @@ static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int
p->fontdata = data;
if ((p->userfont = userfont))
REFCOUNT(data)++;
- p->fontwidth = w;
- p->fontheight = h;
+ 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;
@@ -1268,19 +1341,19 @@ static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int
if (resize) {
/* reset wrap/pan */
p->var.xoffset = p->var.yoffset = p->yscroll = 0;
- 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;
+ if ((p->var.yres % h) && (p->var.yres_virtual % h < p->var.yres % h))
+ p->vrows--;
updatescrollmode(p);
vc_resize_con( p->var.yres/h, p->var.xres/w, unit );
- } else if (unit == fg_console)
- update_screen( unit );
+ } else if (CON_IS_VISIBLE(p->conp) && vt_cons[unit]->vc_mode == KD_TEXT) {
+ if (p->dispsw->clear_margins)
+ p->dispsw->clear_margins(p->conp, p, 0);
+ update_screen(unit);
+ }
if (old_data && (--REFCOUNT(old_data) == 0))
- kfree( old_data - 4*sizeof(int) );
+ kfree(old_data - FONT_EXTRA_WORDS*sizeof(int));
return 0;
}
@@ -1297,8 +1370,8 @@ static inline int fbcon_copy_font(int unit, struct console_font_op *op)
od = &fb_display[h];
if (od->fontdata == p->fontdata)
return 0; /* already the same font... */
- op->width = od->fontwidth;
- op->height = od->fontheight;
+ op->width = fontwidth(od);
+ op->height = fontheight(od);
return fbcon_do_set_font(unit, op, od->fontdata, od->userfont);
}
@@ -1309,9 +1382,10 @@ static inline int fbcon_set_font(int unit, struct console_font_op *op)
int size = h;
int i, j, k;
u8 *new_data, *data = op->data, c, *p;
+#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
u32 d;
+#else
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
if (w != 8)
return -EINVAL;
#endif
@@ -1327,57 +1401,59 @@ static inline int fbcon_set_font(int unit, struct console_font_op *op)
}
size *= op->charcount;
- if (!(new_data = kmalloc( 4*sizeof(int)+size, GFP_USER )))
+ if (!(new_data = kmalloc(FONT_EXTRA_WORDS*sizeof(int)+size, GFP_USER)))
return -ENOMEM;
- new_data += 4*sizeof(int);
+ new_data += FONT_EXTRA_WORDS*sizeof(int);
FNTSIZE(new_data) = size;
FNTCHARCNT(new_data) = op->charcount;
REFCOUNT(new_data) = 0; /* usage counter */
k = 0;
- p = data;
+ p = new_data;
if (w <= 8) {
for (i = 0; i < op->charcount; i++) {
for (j = 0; j < h; j++) {
- c = *p++;
+ c = *data++;
k += c;
- new_data[i*h+j] = c;
+ *p++ = c;
}
- p += 32 - h;
+ data += 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;
+ d = (data[0] << 8) | data[1];
+ data += 2;
k += d;
- ((u16 *)new_data)[i*h+j] = d;
+ *(u16 *)p = d;
+ p += sizeof(u16);
}
- p += 2*(32 - h);
+ data += 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;
+ d = (data[0] << 24) |
+ (data[1] << 16) |
+ (data[2] << 8);
+ data += 3;
} else {
- d = (p[0] << 24) |
- (p[1] << 16) |
- (p[2] << 8) |
- p[3];
- p += 4;
+ d = (data[0] << 24) |
+ (data[1] << 16) |
+ (data[2] << 8) |
+ data[3];
+ data += 4;
}
k += d;
- ((u32 *)new_data)[i*h+j] = d;
+ *(u32 *)p = d;
+ p += sizeof(u32);
}
if (w <= 24)
- p += 3*(32 - h);
+ data += 3*(32 - h);
else
- p += 4*(32 - h);
+ data += 4*(32 - h);
}
}
#endif
@@ -1389,7 +1465,7 @@ static inline int fbcon_set_font(int unit, struct console_font_op *op)
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));
+ kfree(new_data - FONT_EXTRA_WORDS*sizeof(int));
new_data = fb_display[i].fontdata;
break;
}
@@ -1495,11 +1571,11 @@ static int fbcon_scrolldelta(struct vc_data *conp, int lines)
offset = p->yscroll-scrollback_current;
limit = p->vrows;
- switch (p->scrollmode) {
- case SCROLL_YWRAP:
+ switch (p->scrollmode && __SCROLL_YMASK) {
+ case __SCROLL_YWRAP:
p->var.vmode |= FB_VMODE_YWRAP;
break;
- case SCROLL_YPAN:
+ case __SCROLL_YPAN:
limit -= conp->vc_rows;
p->var.vmode &= ~FB_VMODE_YWRAP;
break;
@@ -1509,13 +1585,18 @@ static int fbcon_scrolldelta(struct vc_data *conp, int lines)
else if (offset >= limit)
offset -= limit;
p->var.xoffset = 0;
- p->var.yoffset = offset*p->fontheight;
+ p->var.yoffset = offset*fontheight(p);
p->fb_info->updatevar(unit, p->fb_info);
if (!offset)
fbcon_cursor(conp, CM_DRAW);
return 0;
}
+static inline unsigned safe_shift(unsigned d,int n)
+{
+ return n<0 ? d>>-n : d<<n;
+}
+
__initfunc(static int fbcon_show_logo( void ))
{
struct display *p = &fb_display[fg_console]; /* draw to vt in foreground */
@@ -1532,10 +1613,10 @@ __initfunc(static int fbcon_show_logo( void ))
return 0;
/* Set colors if visual is PSEUDOCOLOR and we have enough colors, or for
- * TRUECOLOR */
+ * DIRECTCOLOR */
if ((p->visual == FB_VISUAL_PSEUDOCOLOR && depth >= 4) ||
- p->visual == FB_VISUAL_TRUECOLOR) {
- int is_truecolor = (p->visual == FB_VISUAL_TRUECOLOR);
+ p->visual == FB_VISUAL_DIRECTCOLOR) {
+ int is_truecolor = (p->visual == FB_VISUAL_DIRECTCOLOR);
int use_256 = (!is_truecolor && depth >= 8) ||
(is_truecolor && depth >= 24);
int first_col = use_256 ? 32 : depth > 4 ? 16 : 0;
@@ -1588,7 +1669,7 @@ __initfunc(static int fbcon_show_logo( void ))
#if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \
defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS)
- if (p->visual == FB_VISUAL_TRUECOLOR) {
+ if (p->visual == FB_VISUAL_DIRECTCOLOR) {
unsigned int val; /* max. depth 32! */
int bdepth;
int redshift, greenshift, blueshift;
@@ -1629,13 +1710,21 @@ __initfunc(static int fbcon_show_logo( void ))
val = (pix << redshift) |
(pix << greenshift) |
(pix << blueshift);
+#ifdef __LITTLE_ENDIAN
for( i = 0; i < bdepth; ++i )
+#else
+ for( i = bdepth-1; i >= 0; --i )
+#endif
*dst++ = val >> (i*8);
pix = (*src & 0x0f) | 0x10; /* lower nibble */
val = (pix << redshift) |
(pix << greenshift) |
(pix << blueshift);
+#ifdef __LITTLE_ENDIAN
+ for( i = 0; i < bdepth; ++i )
+#else
for( i = bdepth-1; i >= 0; --i )
+#endif
*dst++ = val >> (i*8);
}
}
@@ -1645,7 +1734,7 @@ __initfunc(static int fbcon_show_logo( void ))
#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)) {
+ if ((depth % 8 == 0) && (p->visual == FB_VISUAL_TRUECOLOR)) {
/* Modes without color mapping, needs special data transformation... */
unsigned int val; /* max. depth 32! */
int bdepth = depth/8;
@@ -1665,9 +1754,9 @@ __initfunc(static int fbcon_show_logo( void ))
for( y1 = 0; y1 < LOGO_H; y1++ ) {
dst = fb + y1*line + x*bdepth;
for( x1 = 0; x1 < LOGO_W; x1++, src++ ) {
- val = ((linux_logo_red[*src-32] & redmask) << redshift) |
- ((linux_logo_green[*src-32] & greenmask) << greenshift) |
- ((linux_logo_blue[*src-32] & bluemask) << blueshift);
+ val = safe_shift((linux_logo_red[*src-32] & redmask), redshift) |
+ safe_shift((linux_logo_green[*src-32] & greenmask), greenshift) |
+ safe_shift((linux_logo_blue[*src-32] & bluemask), blueshift);
#ifdef __LITTLE_ENDIAN
for( i = 0; i < bdepth; ++i )
#else
@@ -1702,8 +1791,15 @@ __initfunc(static int fbcon_show_logo( void ))
unsigned char val, mask;
int plane = p->next_plane;
+#if defined(CONFIG_FBCON_IPLAN2P2) || defined(CONFIG_FBCON_IPLAN2P4) || \
+ defined(CONFIG_FBCON_IPLAN2P8)
+ int line_length = p->line_length;
+
/* for support of Atari interleaved planes */
-#define MAP_X(x) (plane > line ? x : (x & ~1)*depth + (x & 1))
+#define MAP_X(x) (line_length ? x : (x & ~1)*depth + (x & 1))
+#else
+#define MAP_X(x) (x)
+#endif
/* 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)))
@@ -1766,7 +1862,7 @@ __initfunc(static int fbcon_show_logo( void ))
/* Modes not yet supported: packed pixels with depth != 8 (does such a
* thing exist in reality?) */
- return done ? (LOGO_H + p->fontheight - 1) / p->fontheight : 0 ;
+ return done ? (LOGO_H + fontheight(p) - 1) / fontheight(p) : 0 ;
}
/*
@@ -1801,7 +1897,7 @@ struct consw fb_con = {
static void fbcon_dummy_op(void) {}
-static struct display_switch fbcon_dummy = {
+struct display_switch fbcon_dummy = {
(void *)fbcon_dummy_op, /* fbcon_dummy_setup */
(void *)fbcon_dummy_op, /* fbcon_dummy_bmove */
(void *)fbcon_dummy_op, /* fbcon_dummy_clear */
@@ -1818,3 +1914,4 @@ static struct display_switch fbcon_dummy = {
EXPORT_SYMBOL(fb_display);
EXPORT_SYMBOL(fbcon_redraw_bmove);
+EXPORT_SYMBOL(fbcon_dummy);
diff --git a/drivers/video/fbcon.h b/drivers/video/fbcon.h
deleted file mode 100644
index 98091ba0c..000000000
--- a/drivers/video/fbcon.h
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * linux/drivers/video/fbcon.h -- Low level frame buffer based console driver
- *
- * 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.
- */
-
-#ifndef __VIDEO_FBCON_H
-#define __VIDEO_FBCON_H
-
-#include <linux/config.h>
-#include <linux/console_struct.h>
-
-
- /*
- * `switch' for the Low Level Operations
- */
-
-struct display_switch {
- void (*setup)(struct display *p);
- void (*bmove)(struct display *p, int sy, int sx, int dy, int dx,
- int height, int width);
- void (*clear)(struct vc_data *conp, struct display *p, int sy, int sx,
- 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 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,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)->bgshift)) & 0x0f)
-
-/* Monochrome */
-#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);
-
-
-/* ================================================================= */
-/* Utility Assembler Functions */
-/* ================================================================= */
-
-
-#ifdef __mc68000__
-
-/* ====================================================================== */
-
-/* Those of a delicate disposition might like to skip the next couple of
- * pages.
- *
- * These functions are drop in replacements for memmove and
- * memset(_, 0, _). However their five instances add at least a kilobyte
- * to the object file. You have been warned.
- *
- * Not a great fan of assembler for the sake of it, but I think
- * that these routines are at least 10 times faster than their C
- * equivalents for large blits, and that's important to the lowest level of
- * a graphics driver. Question is whether some scheme with the blitter
- * would be faster. I suspect not for simple text system - not much
- * asynchrony.
- *
- * Code is very simple, just gruesome expansion. Basic strategy is to
- * increase data moved/cleared at each step to 16 bytes to reduce
- * instruction per data move overhead. movem might be faster still
- * For more than 15 bytes, we try to align the write direction on a
- * longword boundary to get maximum speed. This is even more gruesome.
- * Unaligned read/write used requires 68020+ - think this is a problem?
- *
- * Sorry!
- */
-
-
-/* ++roman: I've optimized Robert's original versions in some minor
- * aspects, e.g. moveq instead of movel, let gcc choose the registers,
- * use movem in some places...
- * For other modes than 1 plane, lots of more such assembler functions
- * were needed (e.g. the ones using movep or expanding color values).
- */
-
-/* ++andreas: more optimizations:
- subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
- addal is faster than addaw
- movep is rather expensive compared to ordinary move's
- some functions rewritten in C for clarity, no speed loss */
-
-static __inline__ void *mymemclear_small(void *s, size_t count)
-{
- if (!count)
- return(0);
-
- __asm__ __volatile__(
- "lsrl #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
- "1: lsrl #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
- "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
- "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
- "1: subql #1,%1 ; jcs 3f\n\t"
- "2: moveml %2/%3/%4/%5,%0@-\n\t"
- "dbra %1,2b\n\t"
- "3:"
- : "=a" (s), "=d" (count)
- : "d" (0), "d" (0), "d" (0), "d" (0),
- "0" ((char *)s+count), "1" (count)
- );
-
- return(0);
-}
-
-
-static __inline__ void *mymemclear(void *s, size_t count)
-{
- if (!count)
- return(0);
-
- if (count < 16) {
- __asm__ __volatile__(
- "lsrl #1,%1 ; jcc 1f ; clrb %0@+\n\t"
- "1: lsrl #1,%1 ; jcc 1f ; clrw %0@+\n\t"
- "1: lsrl #1,%1 ; jcc 1f ; clrl %0@+\n\t"
- "1: lsrl #1,%1 ; jcc 1f ; clrl %0@+ ; clrl %0@+\n\t"
- "1:"
- : "=a" (s), "=d" (count)
- : "0" (s), "1" (count)
- );
- } else {
- long tmp;
- __asm__ __volatile__(
- "movel %1,%2\n\t"
- "lsrl #1,%2 ; jcc 1f ; clrb %0@+ ; subqw #1,%1\n\t"
- "lsrl #1,%2 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
- "clrw %0@+ ; subqw #2,%1 ; jra 2f\n\t"
- "1: lsrl #1,%2 ; jcc 2f\n\t"
- "clrw %0@+ ; subqw #2,%1\n\t"
- "2: movew %1,%2; lsrl #2,%1 ; jeq 6f\n\t"
- "lsrl #1,%1 ; jcc 3f ; clrl %0@+\n\t"
- "3: lsrl #1,%1 ; jcc 4f ; clrl %0@+ ; clrl %0@+\n\t"
- "4: subql #1,%1 ; jcs 6f\n\t"
- "5: clrl %0@+; clrl %0@+ ; clrl %0@+ ; clrl %0@+\n\t"
- "dbra %1,5b ; clrw %1; subql #1,%1; jcc 5b\n\t"
- "6: movew %2,%1; btst #1,%1 ; jeq 7f ; clrw %0@+\n\t"
- "7: ; btst #0,%1 ; jeq 8f ; clrb %0@+\n\t"
- "8:"
- : "=a" (s), "=d" (count), "=d" (tmp)
- : "0" (s), "1" (count)
- );
- }
-
- return(0);
-}
-
-
-static __inline__ void *mymemset(void *s, size_t count)
-{
- if (!count)
- return(0);
-
- __asm__ __volatile__(
- "lsrl #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
- "1: lsrl #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
- "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
- "1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
- "1: subql #1,%1 ; jcs 3f\n\t"
- "2: moveml %2/%3/%4/%5,%0@-\n\t"
- "dbra %1,2b\n\t"
- "3:"
- : "=a" (s), "=d" (count)
- : "d" (-1), "d" (-1), "d" (-1), "d" (-1),
- "0" ((char *) s + count), "1" (count)
- );
-
- return(0);
-}
-
-
-static __inline__ void *mymemmove(void *d, const void *s, size_t count)
-{
- if (d < s) {
- if (count < 16) {
- __asm__ __volatile__(
- "lsrl #1,%2 ; jcc 1f ; moveb %1@+,%0@+\n\t"
- "1: lsrl #1,%2 ; jcc 1f ; movew %1@+,%0@+\n\t"
- "1: lsrl #1,%2 ; jcc 1f ; movel %1@+,%0@+\n\t"
- "1: lsrl #1,%2 ; jcc 1f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
- "1:"
- : "=a" (d), "=a" (s), "=d" (count)
- : "0" (d), "1" (s), "2" (count)
- );
- } else {
- long tmp;
- __asm__ __volatile__(
- "movel %0,%3\n\t"
- "lsrl #1,%3 ; jcc 1f ; moveb %1@+,%0@+ ; subqw #1,%2\n\t"
- "lsrl #1,%3 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
- "movew %1@+,%0@+ ; subqw #2,%2 ; jra 2f\n\t"
- "1: lsrl #1,%3 ; jcc 2f\n\t"
- "movew %1@+,%0@+ ; subqw #2,%2\n\t"
- "2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
- "lsrl #1,%2 ; jcc 3f ; movel %1@+,%0@+\n\t"
- "3: lsrl #1,%2 ; jcc 4f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
- "4: subql #1,%2 ; jcs 6f\n\t"
- "5: movel %1@+,%0@+;movel %1@+,%0@+\n\t"
- "movel %1@+,%0@+;movel %1@+,%0@+\n\t"
- "dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
- "6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@+,%0@+\n\t"
- "7: ; btst #0,%2 ; jeq 8f ; moveb %1@+,%0@+\n\t"
- "8:"
- : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
- : "0" (d), "1" (s), "2" (count)
- );
- }
- } else {
- if (count < 16) {
- __asm__ __volatile__(
- "lsrl #1,%2 ; jcc 1f ; moveb %1@-,%0@-\n\t"
- "1: lsrl #1,%2 ; jcc 1f ; movew %1@-,%0@-\n\t"
- "1: lsrl #1,%2 ; jcc 1f ; movel %1@-,%0@-\n\t"
- "1: lsrl #1,%2 ; jcc 1f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
- "1:"
- : "=a" (d), "=a" (s), "=d" (count)
- : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
- );
- } else {
- long tmp;
- __asm__ __volatile__(
- "movel %0,%3\n\t"
- "lsrl #1,%3 ; jcc 1f ; moveb %1@-,%0@- ; subqw #1,%2\n\t"
- "lsrl #1,%3 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
- "movew %1@-,%0@- ; subqw #2,%2 ; jra 2f\n\t"
- "1: lsrl #1,%3 ; jcc 2f\n\t"
- "movew %1@-,%0@- ; subqw #2,%2\n\t"
- "2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
- "lsrl #1,%2 ; jcc 3f ; movel %1@-,%0@-\n\t"
- "3: lsrl #1,%2 ; jcc 4f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
- "4: subql #1,%2 ; jcs 6f\n\t"
- "5: movel %1@-,%0@-;movel %1@-,%0@-\n\t"
- "movel %1@-,%0@-;movel %1@-,%0@-\n\t"
- "dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
- "6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@-,%0@-\n\t"
- "7: ; btst #0,%2 ; jeq 8f ; moveb %1@-,%0@-\n\t"
- "8:"
- : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
- : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
- );
- }
- }
-
- return(0);
-}
-
-
-/* ++andreas: Simple and fast version of memmove, assumes size is
- divisible by 16, suitable for moving the whole screen bitplane */
-static __inline__ void fast_memmove(char *dst, const char *src, size_t size)
-{
- if (!size)
- return;
- if (dst < src)
- __asm__ __volatile__
- ("1:"
- " moveml %0@+,%/d0/%/d1/%/a0/%/a1\n"
- " moveml %/d0/%/d1/%/a0/%/a1,%1@\n"
- " addql #8,%1; addql #8,%1\n"
- " dbra %2,1b\n"
- " clrw %2; subql #1,%2\n"
- " jcc 1b"
- : "=a" (src), "=a" (dst), "=d" (size)
- : "0" (src), "1" (dst), "2" (size / 16 - 1)
- : "d0", "d1", "a0", "a1", "memory");
- else
- __asm__ __volatile__
- ("1:"
- " subql #8,%0; subql #8,%0\n"
- " moveml %0@,%/d0/%/d1/%/a0/%/a1\n"
- " moveml %/d0/%/d1/%/a0/%/a1,%1@-\n"
- " dbra %2,1b\n"
- " clrw %2; subql #1,%2\n"
- " jcc 1b"
- : "=a" (src), "=a" (dst), "=d" (size)
- : "0" (src + size), "1" (dst + size), "2" (size / 16 - 1)
- : "d0", "d1", "a0", "a1", "memory");
-}
-
-#else /* !m68k */
-
- /*
- * Anyone who'd like to write asm functions for other CPUs?
- */
-
-static __inline__ void *mymemclear_small(void *s, size_t count)
-{
- return(memset(s, 0, count));
-}
-
-static __inline__ void *mymemclear(void *s, size_t count)
-{
- return(memset(s, 0, count));
-}
-
-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));
-}
-
-static __inline__ void fast_memmove(char *dst, const char *src, size_t size)
-{
- memmove(dst, src, size);
-}
-#endif /* !i386 */
-
-#endif /* !m68k */
-
-#endif /* __VIDEO_FBCON_H */
diff --git a/drivers/video/fbgen.c b/drivers/video/fbgen.c
index 3ff647980..c3c42ed5e 100644
--- a/drivers/video/fbgen.c
+++ b/drivers/video/fbgen.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <asm/uaccess.h>
+#include <asm/io.h>
static int currcon = 0;
@@ -114,8 +115,7 @@ int fbgen_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fbgen_hwswitch *fbhw = info2->fbhw;
if (con == currcon) /* current console ? */
- return fb_get_cmap(cmap, &fb_display[con].var, kspc, fbhw->getcolreg,
- info);
+ return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info);
else
if (fb_display[con].cmap.len) /* non default colormap ? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
@@ -144,8 +144,7 @@ int fbgen_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return err;
}
if (con == currcon) /* current console ? */
- return fb_set_cmap(cmap, &fb_display[con].var, kspc, fbhw->setcolreg,
- info);
+ return fb_set_cmap(cmap, kspc, fbhw->setcolreg, info);
else
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
@@ -245,7 +244,7 @@ void fbgen_set_disp(int con, struct fb_info_gen *info)
memset(&fix, 0, sizeof(struct fb_fix_screeninfo));
fbhw->encode_fix(&fix, &par, info);
- display->screen_base = fix.smem_start;
+ display->screen_base = phys_to_virt((unsigned long)fix.smem_start);
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
@@ -257,7 +256,7 @@ void fbgen_set_disp(int con, struct fb_info_gen *info)
display->can_soft_blank = 1;
else
display->can_soft_blank = 0;
- display->dispsw = fbhw->get_dispsw(&par, info);
+ fbhw->set_dispsw(&par, display, info);
#if 0 /* FIXME: generic inverse is not supported yet */
display->inverse = (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
#else
@@ -276,12 +275,10 @@ void fbgen_install_cmap(int con, struct fb_info_gen *info)
if (con != currcon)
return;
if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
- fbhw->setcolreg, &info->info);
+ fb_set_cmap(&fb_display[con].cmap, 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);
+ fb_set_cmap(fb_default_cmap(size), 1, fbhw->setcolreg, &info->info);
}
}
@@ -315,8 +312,8 @@ int fbgen_switch(int con, struct fb_info *info)
/* Do we have to save the colormap ? */
if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
- fbhw->getcolreg, &info2->info);
+ fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg,
+ &info2->info);
fbgen_do_set_var(&fb_display[con].var, 1, info2);
currcon = con;
/* Install new colormap */
@@ -346,7 +343,7 @@ void fbgen_blank(int blank, struct fb_info *info)
cmap.transp = NULL;
cmap.start = 0;
cmap.len = 16;
- fb_set_cmap(&cmap, &fb_display[currcon].var, 1, fbhw->setcolreg, info);
+ fb_set_cmap(&cmap, 1, fbhw->setcolreg, info);
} else
fbgen_install_cmap(currcon, info2);
}
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
new file mode 100644
index 000000000..aab80ad6b
--- /dev/null
+++ b/drivers/video/fbmem.c
@@ -0,0 +1,725 @@
+/*
+ * linux/drivers/video/fbmem.c
+ *
+ * Copyright (C) 1994 Martin Schaller
+ *
+ * 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/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/malloc.h>
+#include <linux/mman.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/console_struct.h>
+#include <linux/init.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#endif
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
+#if defined(__mc68000__) || defined(CONFIG_APUS)
+#include <asm/setup.h>
+#endif
+#ifdef __powerpc__
+#include <asm/io.h>
+#endif
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include <linux/fb.h>
+
+
+ /*
+ * Frame buffer device initialization and setup routines
+ */
+
+extern unsigned long acornfb_init(void);
+extern void acornfb_setup(char *options, int *ints);
+extern void amifb_init(void);
+extern void amifb_setup(char *options, int *ints);
+extern void atafb_init(void);
+extern void atafb_setup(char *options, int *ints);
+extern void macfb_init(void);
+extern void macfb_setup(char *options, int *ints);
+extern void cyberfb_init(void);
+extern void cyberfb_setup(char *options, int *ints);
+extern void cvppcfb_init(void);
+extern void cvppcfb_setup(char *options, int *ints);
+extern void retz3fb_init(void);
+extern void retz3fb_setup(char *options, int *ints);
+extern void clgenfb_init(void);
+extern void clgenfb_setup(char *options, int *ints);
+extern void vfb_init(void);
+extern void vfb_setup(char *options, int *ints);
+extern void offb_init(void);
+extern void offb_setup(char *options, int *ints);
+extern void atyfb_init(void);
+extern void atyfb_setup(char *options, int *ints);
+extern void igafb_init(void);
+extern void igafb_setup(char *options, int *ints);
+extern void imsttfb_init(void);
+extern void imsttfb_setup(char *options, int *ints);
+extern void dnfb_init(void);
+extern void tgafb_init(void);
+extern void virgefb_init(void);
+extern void virgefb_setup(char *options, int *ints);
+extern void resolver_video_setup(char *options, int *ints);
+extern void s3triofb_init(void);
+extern void s3triofb_setup(char *options, int *ints);
+extern void vesafb_init(void);
+extern void vesafb_setup(char *options, int *ints);
+extern void matroxfb_init(void);
+extern void matroxfb_setup(char* options, int *ints);
+extern void hpfb_init(void);
+extern void hpfb_setup(char *options, int *ints);
+extern void sbusfb_init(void);
+extern void sbusfb_setup(char *options, int *ints);
+extern void valkyriefb_init(void);
+extern void valkyriefb_setup(char *options, int *ints);
+extern void g364fb_init(void);
+
+static struct {
+ const char *name;
+ void (*init)(void);
+ void (*setup)(char *options, int *ints);
+} fb_drivers[] __initdata = {
+#ifdef CONFIG_FB_RETINAZ3
+ { "retz3", retz3fb_init, retz3fb_setup },
+#endif
+#ifdef CONFIG_FB_ACORN
+ { "acorn", acornfb_init, acornfb_setup },
+#endif
+#ifdef CONFIG_FB_AMIGA
+ { "amifb", amifb_init, amifb_setup },
+#endif
+#ifdef CONFIG_FB_ATARI
+ { "atafb", atafb_init, atafb_setup },
+#endif
+#ifdef CONFIG_FB_MAC
+ { "macfb", macfb_init, macfb_setup },
+#endif
+#ifdef CONFIG_FB_CYBER
+ { "cyber", cyberfb_init, cyberfb_setup },
+#endif
+#ifdef CONFIG_FB_CVPPC
+ { "cvppcfb", cvppcfb_init, cvppcfb_setup },
+#endif
+#ifdef CONFIG_FB_CLGEN
+ { "clgen", clgenfb_init, clgenfb_setup },
+#endif
+#ifdef CONFIG_FB_OF
+ { "offb", offb_init, offb_setup },
+#endif
+#ifdef CONFIG_FB_SBUS
+ { "sbus", sbusfb_init, sbusfb_setup },
+#endif
+#ifdef CONFIG_FB_ATY
+ { "atyfb", atyfb_init, atyfb_setup },
+#endif
+#ifdef CONFIG_FB_IGA
+ { "igafb", igafb_init, igafb_setup },
+#endif
+#ifdef CONFIG_FB_IMSTT
+ { "imsttfb", imsttfb_init, imsttfb_setup },
+#endif
+#ifdef CONFIG_APOLLO
+ { "apollo", dnfb_init, NULL },
+#endif
+#ifdef CONFIG_FB_S3TRIO
+ { "s3trio", s3triofb_init, s3triofb_setup },
+#endif
+#ifdef CONFIG_FB_TGA
+ { "tga", tgafb_init, NULL },
+#endif
+#ifdef CONFIG_FB_VIRGE
+ { "virge", virgefb_init, virgefb_setup },
+#endif
+#ifdef CONFIG_FB_VESA
+ { "vesa", vesafb_init, vesafb_setup },
+#endif
+#ifdef CONFIG_FB_MATROX
+ { "matrox", matroxfb_init, matroxfb_setup },
+#endif
+#ifdef CONFIG_FB_HP300
+ { "hpfb", hpfb_init, hpfb_setup },
+#endif
+#ifdef CONFIG_FB_VALKYRIE
+ { "valkyriefb", valkyriefb_init, valkyriefb_setup },
+#endif
+#ifdef CONFIG_FB_G364
+ { "g364", g364fb_init, NULL },
+#endif
+#ifdef CONFIG_GSP_RESOLVER
+ /* Not a real frame buffer device... */
+ { "resolver", NULL, resolver_video_setup },
+#endif
+#ifdef CONFIG_FB_VIRTUAL
+ /* Must be last to avoid that vfb becomes your primary display */
+ { "vfb", vfb_init, vfb_setup },
+#endif
+};
+
+#define NUM_FB_DRIVERS (sizeof(fb_drivers)/sizeof(*fb_drivers))
+
+static void (*pref_init_funcs[FB_MAX])(void);
+static int num_pref_init_funcs __initdata = 0;
+
+
+#define GET_INODE(i) MKDEV(FB_MAJOR, (i) << FB_MODES_SHIFT)
+#define GET_FB_VAR_IDX(node) (MINOR(node) & ((1 << FB_MODES_SHIFT)-1))
+
+struct fb_info *registered_fb[FB_MAX];
+int num_registered_fb = 0;
+
+char con2fb_map[MAX_NR_CONSOLES];
+
+static int first_fb_vc = 0;
+static int last_fb_vc = MAX_NR_CONSOLES-1;
+static int fbcon_is_default = 1;
+
+static inline int PROC_CONSOLE(void)
+{
+ if (!current->tty)
+ return fg_console;
+
+ if (current->tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
+ /* XXX Should report error here? */
+ return fg_console;
+
+ if (MINOR(current->tty->device) < 1)
+ return fg_console;
+
+ return MINOR(current->tty->device) - 1;
+}
+
+#ifdef CONFIG_PROC_FS
+static int fbmem_read_proc(char *buf, char **start, off_t offset,
+ int len, int *eof, void *private)
+{
+ struct fb_info **fi;
+
+ len = 0;
+ for (fi = registered_fb; fi < &registered_fb[FB_MAX] && len < 4000; fi++)
+ if (*fi)
+ len += sprintf(buf + len, "%d %s\n",
+ GET_FB_IDX((*fi)->node),
+ (*fi)->modename);
+ *start = buf + offset;
+ return len > offset ? len - offset : 0;
+}
+#endif
+
+static ssize_t
+fb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+ unsigned long p = *ppos;
+ struct inode *inode = file->f_dentry->d_inode;
+ int fbidx = GET_FB_IDX(inode->i_rdev);
+ struct fb_info *info = registered_fb[fbidx];
+ struct fb_ops *fb = info->fbops;
+ struct fb_fix_screeninfo fix;
+ char *base_addr;
+ ssize_t copy_size;
+
+ if (! fb || ! info->disp)
+ return -ENODEV;
+
+ fb->fb_get_fix(&fix,PROC_CONSOLE(), info);
+ base_addr=info->disp->screen_base;
+ copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
+ if (copy_to_user(buf, base_addr+p, copy_size))
+ return -EFAULT;
+ *ppos += copy_size;
+ return copy_size;
+}
+
+static ssize_t
+fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+ unsigned long p = *ppos;
+ struct inode *inode = file->f_dentry->d_inode;
+ int fbidx = GET_FB_IDX(inode->i_rdev);
+ struct fb_info *info = registered_fb[fbidx];
+ struct fb_ops *fb = info->fbops;
+ struct fb_fix_screeninfo fix;
+ char *base_addr;
+ ssize_t copy_size;
+
+ if (! fb || ! info->disp)
+ return -ENODEV;
+
+ fb->fb_get_fix(&fix, PROC_CONSOLE(), info);
+ base_addr=info->disp->screen_base;
+ copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
+ if (copy_from_user(base_addr+p, buf, copy_size))
+ return -EFAULT;
+ file->f_pos += copy_size;
+ return copy_size;
+}
+
+
+static int set_all_vcs(int fbidx, struct fb_ops *fb,
+ struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ int unit, err;
+
+ var->activate |= FB_ACTIVATE_TEST;
+ err = fb->fb_set_var(var, PROC_CONSOLE(), info);
+ var->activate &= ~FB_ACTIVATE_TEST;
+ if (err)
+ return err;
+ for (unit = 0; unit < MAX_NR_CONSOLES; unit++)
+ if (fb_display[unit].conp && con2fb_map[unit] == fbidx)
+ fb->fb_set_var(var, unit, info);
+ return 0;
+}
+
+static void set_con2fb_map(int unit, int newidx)
+{
+ int oldidx = con2fb_map[unit];
+ struct fb_info *oldfb, *newfb;
+ struct vc_data *conp;
+ char *fontdata;
+ unsigned short fontwidth, fontheight, fontwidthlog, fontheightlog;
+ int userfont;
+
+ if (newidx != con2fb_map[unit]) {
+ oldfb = registered_fb[oldidx];
+ newfb = registered_fb[newidx];
+ if (newfb->fbops->fb_open(newfb,0))
+ return;
+ oldfb->fbops->fb_release(oldfb,0);
+ conp = fb_display[unit].conp;
+ fontdata = fb_display[unit].fontdata;
+ fontwidth = fb_display[unit]._fontwidth;
+ fontheight = fb_display[unit]._fontheight;
+ fontwidthlog = fb_display[unit]._fontwidthlog;
+ fontheightlog = fb_display[unit]._fontheightlog;
+ userfont = fb_display[unit].userfont;
+ con2fb_map[unit] = newidx;
+ fb_display[unit] = *(newfb->disp);
+ fb_display[unit].conp = conp;
+ fb_display[unit].fontdata = fontdata;
+ fb_display[unit]._fontwidth = fontwidth;
+ fb_display[unit]._fontheight = fontheight;
+ fb_display[unit]._fontwidthlog = fontwidthlog;
+ fb_display[unit]._fontheightlog = fontheightlog;
+ fb_display[unit].userfont = userfont;
+ fb_display[unit].fb_info = newfb;
+ if (!newfb->changevar)
+ newfb->changevar = oldfb->changevar;
+ /* tell console var has changed */
+ if (newfb->changevar)
+ newfb->changevar(unit);
+ }
+}
+
+#ifdef CONFIG_KMOD
+static void try_to_load(int fb)
+{
+ char modname[16];
+
+ sprintf(modname, "fb%d", fb);
+ request_module(modname);
+}
+#endif /* CONFIG_KMOD */
+
+static int
+fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int fbidx = GET_FB_IDX(inode->i_rdev);
+ struct fb_info *info = registered_fb[fbidx];
+ struct fb_ops *fb = info->fbops;
+ struct fb_cmap cmap;
+ struct fb_var_screeninfo var;
+ struct fb_fix_screeninfo fix;
+ struct fb_con2fbmap con2fb;
+ int i;
+
+ if (! fb)
+ return -ENODEV;
+ switch (cmd) {
+ case FBIOGET_VSCREENINFO:
+ if ((i = fb->fb_get_var(&var, PROC_CONSOLE(), info)))
+ return i;
+ return copy_to_user((void *) arg, &var,
+ sizeof(var)) ? -EFAULT : 0;
+ case FBIOPUT_VSCREENINFO:
+ if (copy_from_user(&var, (void *) arg, sizeof(var)))
+ return -EFAULT;
+ i = var.activate & FB_ACTIVATE_ALL
+ ? set_all_vcs(fbidx, fb, &var, info)
+ : fb->fb_set_var(&var, PROC_CONSOLE(), info);
+ if (i)
+ return i;
+ if (copy_to_user((void *) arg, &var, sizeof(var)))
+ return -EFAULT;
+ return 0;
+ case FBIOGET_FSCREENINFO:
+ if ((i = fb->fb_get_fix(&fix, PROC_CONSOLE(), info)))
+ return i;
+ return copy_to_user((void *) arg, &fix, sizeof(fix)) ?
+ -EFAULT : 0;
+ case FBIOPUTCMAP:
+ if (copy_from_user(&cmap, (void *) arg, sizeof(cmap)))
+ return -EFAULT;
+ return (fb->fb_set_cmap(&cmap, 0, PROC_CONSOLE(), info));
+ case FBIOGETCMAP:
+ if (copy_from_user(&cmap, (void *) arg, sizeof(cmap)))
+ return -EFAULT;
+ return (fb->fb_get_cmap(&cmap, 0, PROC_CONSOLE(), info));
+ case FBIOPAN_DISPLAY:
+ if (copy_from_user(&var, (void *) arg, sizeof(var)))
+ return -EFAULT;
+ if ((i=fb->fb_pan_display(&var, PROC_CONSOLE(), info)))
+ return i;
+ if (copy_to_user((void *) arg, &var, sizeof(var)))
+ return -EFAULT;
+ return i;
+ case FBIOGET_CON2FBMAP:
+ if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb)))
+ return -EFAULT;
+ if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
+ return -EINVAL;
+ con2fb.framebuffer = con2fb_map[con2fb.console-1];
+ return copy_to_user((void *)arg, &con2fb,
+ sizeof(con2fb)) ? -EFAULT : 0;
+ case FBIOPUT_CON2FBMAP:
+ if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb)))
+ return - EFAULT;
+ if (con2fb.console < 0 || con2fb.console > MAX_NR_CONSOLES)
+ return -EINVAL;
+ if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
+ return -EINVAL;
+#ifdef CONFIG_KMOD
+ if (!registered_fb[con2fb.framebuffer])
+ try_to_load(con2fb.framebuffer);
+#endif /* CONFIG_KMOD */
+ if (!registered_fb[con2fb.framebuffer])
+ return -EINVAL;
+ if (con2fb.console != 0)
+ set_con2fb_map(con2fb.console-1, con2fb.framebuffer);
+ else
+ /* set them all */
+ for (i = 0; i < MAX_NR_CONSOLES; i++)
+ set_con2fb_map(i, con2fb.framebuffer);
+ return 0;
+ default:
+ return fb->fb_ioctl(inode, file, cmd, arg, PROC_CONSOLE(),
+ info);
+ }
+}
+
+static int
+fb_mmap(struct file *file, struct vm_area_struct * vma)
+{
+ int fbidx = GET_FB_IDX(file->f_dentry->d_inode->i_rdev);
+ struct fb_info *info = registered_fb[fbidx];
+ struct fb_ops *fb = info->fbops;
+ struct fb_fix_screeninfo fix;
+ struct fb_var_screeninfo var;
+ unsigned long start;
+ u32 len;
+
+ if (!fb)
+ return -ENODEV;
+ if (fb->fb_mmap)
+ return fb->fb_mmap(info, file, vma);
+ fb->fb_get_fix(&fix, PROC_CONSOLE(), info);
+
+ /* frame buffer memory */
+ start = (unsigned long)fix.smem_start;
+ len = (start & ~PAGE_MASK)+fix.smem_len;
+ start &= PAGE_MASK;
+ len = (len+~PAGE_MASK) & PAGE_MASK;
+ if (vma->vm_offset >= len) {
+ /* memory mapped io */
+ vma->vm_offset -= len;
+ fb->fb_get_var(&var, PROC_CONSOLE(), info);
+ if (var.accel_flags)
+ return -EINVAL;
+ start = (unsigned long)fix.mmio_start;
+ len = (start & ~PAGE_MASK)+fix.mmio_len;
+ start &= PAGE_MASK;
+ len = (len+~PAGE_MASK) & PAGE_MASK;
+ }
+ if ((vma->vm_end - vma->vm_start + vma->vm_offset) > len)
+ return -EINVAL;
+ vma->vm_offset += start;
+ if (vma->vm_offset & ~PAGE_MASK)
+ return -ENXIO;
+#if defined(__mc68000__)
+ if (CPU_IS_020_OR_030)
+ pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
+ if (CPU_IS_040_OR_060) {
+ pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;
+ /* Use no-cache mode, serialized */
+ pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;
+ }
+#elif defined(__powerpc__)
+ pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
+#elif defined(__alpha__)
+ /* Caching is off in the I/O space quadrant by design. */
+#elif defined(__sparc__)
+ /* Should never get here, all fb drivers should have their own
+ mmap routines */
+#elif defined(__i386__)
+ if (boot_cpu_data.x86 > 3)
+ pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+#elif defined(__mips__)
+ pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
+ pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
+#else
+#warning What do we have to do here??
+#endif
+ if (remap_page_range(vma->vm_start, vma->vm_offset,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot))
+ return -EAGAIN;
+ vma->vm_file = file;
+ file->f_count++;
+ return 0;
+}
+
+static int
+fb_open(struct inode *inode, struct file *file)
+{
+ int fbidx = GET_FB_IDX(inode->i_rdev);
+ struct fb_info *info;
+
+#ifdef CONFIG_KMOD
+ if (!(info = registered_fb[fbidx]))
+ try_to_load(fbidx);
+#endif /* CONFIG_KMOD */
+ if (!(info = registered_fb[fbidx]))
+ return -ENODEV;
+ return info->fbops->fb_open(info,1);
+}
+
+static int
+fb_release(struct inode *inode, struct file *file)
+{
+ int fbidx = GET_FB_IDX(inode->i_rdev);
+ struct fb_info *info = registered_fb[fbidx];
+
+ info->fbops->fb_release(info,1);
+ return 0;
+}
+
+static struct file_operations fb_fops = {
+ NULL, /* lseek */
+ fb_read, /* read */
+ fb_write, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ fb_ioctl, /* ioctl */
+ fb_mmap, /* mmap */
+ fb_open, /* open */
+ NULL, /* flush */
+ fb_release, /* release */
+ NULL /* fsync */
+};
+
+int
+register_framebuffer(struct fb_info *fb_info)
+{
+ int i, j;
+ static int fb_ever_opened[FB_MAX];
+ static int first = 1;
+
+ if (num_registered_fb == FB_MAX)
+ return -ENXIO;
+ num_registered_fb++;
+ for (i = 0 ; i < FB_MAX; i++)
+ if (!registered_fb[i])
+ break;
+ fb_info->node=GET_INODE(i);
+ registered_fb[i] = fb_info;
+ if (!fb_ever_opened[i]) {
+ /*
+ * We assume initial frame buffer devices can be opened this
+ * many times
+ */
+ for (j = 0; j < MAX_NR_CONSOLES; j++)
+ if (con2fb_map[j] == i)
+ fb_info->fbops->fb_open(fb_info,0);
+ fb_ever_opened[i] = 1;
+ }
+
+ if (first) {
+ first = 0;
+ take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default);
+ }
+
+ return 0;
+}
+
+int
+unregister_framebuffer(const struct fb_info *fb_info)
+{
+ int i, j;
+
+ i = GET_FB_IDX(fb_info->node);
+ for (j = 0; j < MAX_NR_CONSOLES; j++)
+ if (con2fb_map[j] == i)
+ return -EBUSY;
+ if (!registered_fb[i])
+ return -EINVAL;
+ registered_fb[i]=NULL;
+ num_registered_fb--;
+ return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_fbmem;
+#endif
+
+__initfunc(void
+fbmem_init(void))
+{
+ int i;
+
+#ifdef CONFIG_PROC_FS
+ proc_fbmem = create_proc_entry("fb", 0, 0);
+ if (proc_fbmem)
+ proc_fbmem->read_proc = fbmem_read_proc;
+#endif
+
+ if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
+ printk("unable to get major %d for fb devs\n", FB_MAJOR);
+
+ /*
+ * Probe for all builtin frame buffer devices
+ */
+ for (i = 0; i < num_pref_init_funcs; i++)
+ pref_init_funcs[i]();
+
+ for (i = 0; i < NUM_FB_DRIVERS; i++)
+ if (fb_drivers[i].init)
+ fb_drivers[i].init();
+}
+
+
+int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal,
+ const struct fb_info *fb_info)
+{
+#if 0
+ /*
+ * long long divisions .... $#%%#$
+ */
+ unsigned long long hpicos, vpicos;
+ const unsigned long long _1e12 = 1000000000000ULL;
+ const struct fb_monspecs *monspecs = &fb_info->monspecs;
+
+ hpicos = (unsigned long long)htotal*(unsigned long long)pixclock;
+ vpicos = (unsigned long long)vtotal*(unsigned long long)hpicos;
+ if (!vpicos)
+ return 0;
+
+ if (monspecs->hfmin == 0)
+ return 1;
+
+ if (hpicos*monspecs->hfmin > _1e12 || hpicos*monspecs->hfmax < _1e12 ||
+ vpicos*monspecs->vfmin > _1e12 || vpicos*monspecs->vfmax < _1e12)
+ return 0;
+#endif
+ return 1;
+}
+
+int fbmon_dpms(const struct fb_info *fb_info)
+{
+ return fb_info->monspecs.dpms;
+}
+
+
+ /*
+ * Command line options
+ */
+
+__initfunc(void video_setup(char *options, int *ints))
+{
+ int i, j;
+
+ if (!options || !*options)
+ return;
+
+ if (!strncmp(options, "map:", 4)) {
+ options += 4;
+ if (*options)
+ for (i = 0, j = 0; i < MAX_NR_CONSOLES; i++) {
+ if (!options[j])
+ j = 0;
+ con2fb_map[i] = (options[j++]-'0') % FB_MAX;
+ }
+ return;
+ }
+
+ if (!strncmp(options, "vc:", 3)) {
+ options += 3;
+ if (*options)
+ first_fb_vc = simple_strtoul(options, &options, 10) - 1;
+ if (first_fb_vc < 0)
+ first_fb_vc = 0;
+ if (*options++ == '-')
+ last_fb_vc = simple_strtoul(options, &options, 10) - 1;
+ fbcon_is_default = 0;
+ }
+
+ if (num_pref_init_funcs == FB_MAX)
+ return;
+
+ for (i = 0; i < NUM_FB_DRIVERS; i++) {
+ j = strlen(fb_drivers[i].name);
+ if (!strncmp(options, fb_drivers[i].name, j) &&
+ options[j] == ':') {
+ if (!strcmp(options+j+1, "off"))
+ fb_drivers[i].init = NULL;
+ else {
+ if (fb_drivers[i].init) {
+ pref_init_funcs[num_pref_init_funcs++] =
+ fb_drivers[i].init;
+ fb_drivers[i].init = NULL;
+ }
+ if (fb_drivers[i].setup)
+ fb_drivers[i].setup(options+j+1, ints);
+ }
+ return;
+ }
+ }
+ /*
+ * If we get here no fb was specified and we default to pass the
+ * options to the first frame buffer that has an init and a setup
+ * function.
+ */
+ for (i = 0; i < NUM_FB_DRIVERS; i++) {
+ if (fb_drivers[i].init && fb_drivers[i].setup) {
+ pref_init_funcs[num_pref_init_funcs++] =
+ fb_drivers[i].init;
+ fb_drivers[i].init = NULL;
+
+ fb_drivers[i].setup(options, ints);
+ return;
+ }
+ }
+}
+
+
+ /*
+ * Visible symbols for modules
+ */
+
+EXPORT_SYMBOL(register_framebuffer);
+EXPORT_SYMBOL(unregister_framebuffer);
diff --git a/drivers/video/font.h b/drivers/video/font.h
deleted file mode 100644
index ab4385b17..000000000
--- a/drivers/video/font.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * font.h -- `Soft' font definitions
- *
- * Created 1995 by Geert Uytterhoeven
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#ifndef _FONT_H_
-#define _FONT_H_
-
-#include <linux/types.h>
-
-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
-
-#endif /* _FONT_H_ */
diff --git a/drivers/video/font_6x11.c b/drivers/video/font_6x11.c
index 88a20e09e..362529c2b 100644
--- a/drivers/video/font_6x11.c
+++ b/drivers/video/font_6x11.c
@@ -4,7 +4,7 @@
/* */
/**********************************************/
-#include "font.h"
+#include <video/font.h>
#define FONTDATAMAX (11*256)
diff --git a/drivers/video/font_8x16.c b/drivers/video/font_8x16.c
index 26a34bce7..786619712 100644
--- a/drivers/video/font_8x16.c
+++ b/drivers/video/font_8x16.c
@@ -4,7 +4,7 @@
/* */
/**********************************************/
-#include "font.h"
+#include <video/font.h>
#define FONTDATAMAX 4096
diff --git a/drivers/video/font_8x8.c b/drivers/video/font_8x8.c
index ff0701a68..6358e671f 100644
--- a/drivers/video/font_8x8.c
+++ b/drivers/video/font_8x8.c
@@ -4,7 +4,7 @@
/* */
/**********************************************/
-#include "font.h"
+#include <video/font.h>
#define FONTDATAMAX 2048
diff --git a/drivers/video/font_acorn_8x8.c b/drivers/video/font_acorn_8x8.c
index 41acfd5f6..154d0fb39 100644
--- a/drivers/video/font_acorn_8x8.c
+++ b/drivers/video/font_acorn_8x8.c
@@ -2,7 +2,7 @@
#include <linux/config.h>
-#include "font.h"
+#include <video/font.h>
static unsigned char acorndata_8x8[] = {
/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */
diff --git a/drivers/video/font_pearl_8x8.c b/drivers/video/font_pearl_8x8.c
index 1f4e40fa6..c8d7da571 100644
--- a/drivers/video/font_pearl_8x8.c
+++ b/drivers/video/font_pearl_8x8.c
@@ -9,7 +9,7 @@
/* */
/**********************************************/
-#include "font.h"
+#include <video/font.h>
#define FONTDATAMAX 2048
diff --git a/drivers/video/font_sun12x22.c b/drivers/video/font_sun12x22.c
index 837e04203..c4cd54c7a 100644
--- a/drivers/video/font_sun12x22.c
+++ b/drivers/video/font_sun12x22.c
@@ -1,4 +1,4 @@
-#include "font.h"
+#include <video/font.h>
#define FONTDATAMAX 5632
diff --git a/drivers/video/font_sun8x16.c b/drivers/video/font_sun8x16.c
index 8bf027807..9f5bc40b4 100644
--- a/drivers/video/font_sun8x16.c
+++ b/drivers/video/font_sun8x16.c
@@ -1,4 +1,4 @@
-#include "font.h"
+#include <video/font.h>
#define FONTDATAMAX 4096
diff --git a/drivers/video/fonts.c b/drivers/video/fonts.c
index 72f29410a..52ab1a697 100644
--- a/drivers/video/fonts.c
+++ b/drivers/video/fonts.c
@@ -16,7 +16,7 @@
#if defined(__mc68000__) || defined(CONFIG_APUS)
#include <asm/setup.h>
#endif
-#include "font.h"
+#include <video/font.h>
#define NO_FONTS
@@ -90,7 +90,7 @@ struct fbcon_font_desc *fbcon_get_default_font(int xres, int yres)
for(i=0; i<num_fonts; i++) {
f = fbcon_fonts[i];
c = f->pref;
-#ifdef __mc68000__
+#if defined(__mc68000__) || defined(CONFIG_APUS)
#ifdef CONFIG_FONT_PEARL_8x8
if (MACH_IS_AMIGA && f->idx == PEARL8x8_IDX)
c = 100;
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c
index 7a7bede02..11689b150 100644
--- a/drivers/video/hpfb.c
+++ b/drivers/video/hpfb.c
@@ -22,10 +22,10 @@
#include <asm/blinken.h>
#include <asm/hwtest.h>
-#include "fbcon-mfb.h"
-#include "fbcon-cfb2.h"
-#include "fbcon-cfb4.h"
-#include "fbcon-cfb8.h"
+#include <video/fbcon-mfb.h>
+#include <video/fbcon-cfb2.h>
+#include <video/fbcon-cfb4.h>
+#include <video/fbcon-cfb8.h>
#define arraysize(x) (sizeof(x)/sizeof(*(x)))
@@ -360,6 +360,7 @@ __initfunc(int hpfb_init_one(unsigned long base))
fb_info.switch_con = &hpfb_switch;
fb_info.updatevar = &fb_update_var;
fb_info.blank = &hpfb_blank;
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
do_fb_set_var(&hpfb_defined, 1);
hpfb_get_var(&disp.var, -1, &fb_info);
diff --git a/drivers/video/iga.h b/drivers/video/iga.h
new file mode 100644
index 000000000..f68899314
--- /dev/null
+++ b/drivers/video/iga.h
@@ -0,0 +1,27 @@
+/* $Id: iga.h,v 1.1 1998/10/07 11:36:07 jj Exp $
+ * iga1682.h: Sparc/PCI iga1682 driver constants etc.
+ *
+ * Copyleft 1998 V. Roganov and G. Raiko
+ */
+
+#ifndef _IGA1682_H
+#define _IGA1682_H 1
+
+struct iga1682_info
+{
+ unsigned int total_vram;
+};
+
+#define DAC_W_INDEX 0x03C8
+#define DAC_DATA 0x03C9
+#define IGA_EXT_CNTRL 0x3CE
+#define IGA_IDX_EXT_BUS_CNTL 0x30
+#define MEM_SIZE_ALIAS 0x3
+#define MEM_SIZE_1M 0x0
+#define MEM_SIZE_2M 0x1
+#define MEM_SIZE_4M 0x2
+#define MEM_SIZE_RESERVED 0x3
+#define IGA_IDX_OVERSCAN_COLOR 0x58
+#define IGA_IDX_EXT_MEM_2 0x72
+
+#endif /* !(_IGA1682_H) */
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
new file mode 100644
index 000000000..e3a86c868
--- /dev/null
+++ b/drivers/video/igafb.c
@@ -0,0 +1,783 @@
+/*
+ * linux/drivers/video/igafb.c -- Frame buffer device for IGA 1682
+ *
+ * Copyright (C) 1998 Vladimir Roganov and Gleb Raiko
+ *
+ * This driver is partly based on the Frame buffer device for ATI Mach64
+ * and partially on VESA-related code.
+ *
+ * Copyright (C) 1997-1998 Geert Uytterhoeven
+ * Copyright (C) 1998 Bernd Harries
+ * Copyright (C) 1998 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.
+ */
+
+/******************************************************************************
+
+ TODO:
+ Despite of IGA Card has advanced graphic acceleration,
+ initial version is almost dummy and does not support it.
+ Support for video modes and acceleration must be added
+ together with accelerated X-Windows driver implementation.
+
+ (Anyone to help with this?)
+
+ Most important thing at this moment is that we have working
+ JavaEngine1 console & X with new console interface.
+
+******************************************************************************/
+
+#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/console.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/nvram.h>
+#include <linux/kd.h>
+#include <linux/vt_kern.h>
+
+#include <asm/io.h>
+
+#ifdef __sparc__
+#include <asm/pbm.h>
+#include <asm/pcic.h>
+#endif
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+
+#include "iga.h"
+
+static char igafb_name[16] = "IGA 1682";
+static char fontname[40] __initdata = { 0 };
+
+struct pci_mmap_map {
+ unsigned long voff;
+ unsigned long poff;
+ unsigned long size;
+ unsigned long prot_flag;
+ unsigned long prot_mask;
+};
+
+struct fb_info_iga {
+ struct fb_info fb_info;
+ unsigned long frame_buffer_phys;
+ unsigned long frame_buffer;
+ unsigned long io_base_phys;
+ unsigned long io_base;
+ u32 total_vram;
+ struct pci_mmap_map *mmap_map;
+ struct { u_short blue, green, red, pad; } palette[256];
+ int video_cmap_len;
+ int currcon;
+ struct display disp;
+ struct display_switch dispsw;
+ union {
+#ifdef FBCON_HAS_CFB16
+ u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+ u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u32 cfb32[16];
+#endif
+ } fbcon_cmap;
+#ifdef __sparc__
+ u8 open;
+ u8 mmaped;
+ int vtconsole;
+ int consolecnt;
+#endif
+};
+
+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
+};
+
+/*
+ * Memory-mapped I/O functions for Sparc PCI
+ */
+static inline unsigned char pci_inb (struct fb_info_iga *info,
+ unsigned int reg)
+{
+ return *(volatile unsigned char*)(info->io_base + reg);
+}
+static inline void pci_outb (struct fb_info_iga *info, unsigned char c,
+ unsigned int reg)
+{
+ *(volatile unsigned char*)(info->io_base + reg) = c;
+}
+static inline unsigned int iga_inb(struct fb_info_iga *info,
+ unsigned int reg, unsigned int idx )
+{
+ pci_outb(info, idx, reg);
+ return pci_inb(info, reg + 1);
+}
+static inline void iga_outb(struct fb_info_iga *info, unsigned char val,
+ unsigned int reg, unsigned int idx )
+{
+ pci_outb(info, idx, reg);
+ pci_outb(info, val, reg+1);
+}
+
+#endif /* __sparc__ */
+
+/*
+ * Very important functionality for the JavaEngine1 computer:
+ * make screen border black (usign special IGA registers)
+ */
+static void iga_blank_border(struct fb_info_iga *info)
+{
+ int i;
+
+ for (i=0; i < 3; i++)
+ iga_outb(info, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
+}
+
+
+/*
+ * Frame buffer device API
+ */
+
+/*
+ * Open/Release the frame buffer device
+ */
+
+static int igafb_open(struct fb_info *info, int user)
+{
+ /*
+ * Nothing, only a usage count for the moment
+ */
+ MOD_INC_USE_COUNT;
+ return(0);
+}
+
+static int igafb_release(struct fb_info *info, int user)
+{
+ MOD_DEC_USE_COUNT;
+ return(0);
+}
+
+static int igafb_update_var(int con, struct fb_info *info)
+{
+ return 0;
+}
+
+static int igafb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info)
+{
+ struct fb_info_iga *fb = (struct fb_info_iga*)info;
+
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+ strcpy(fix->id, igafb_name);
+
+ fix->smem_start = (char *)fb->frame_buffer;
+ fix->smem_len = fb->total_vram;
+ fix->xpanstep = 0;
+ fix->ypanstep = 0;
+ fix->ywrapstep = 0;
+
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->type_aux = 0;
+ fix->line_length = default_var.xres * (default_var.bits_per_pixel/8);
+ fix->visual = default_var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR
+ : FB_VISUAL_DIRECTCOLOR;
+ return 0;
+}
+
+static int igafb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ if(con == -1)
+ memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
+ else
+ *var = fb_display[con].var;
+ return 0;
+}
+
+static int igafb_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
+ return 0;
+}
+
+#ifdef __sparc__
+static int igafb_mmap(struct fb_info *info, struct file *file,
+ struct vm_area_struct *vma)
+{
+ struct fb_info_iga *fb = (struct fb_info_iga *)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);
+
+ /* 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;
+
+ 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;
+ }
+ }
+ return 0;
+}
+#endif /* __sparc__ */
+
+
+static int iga_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.
+ */
+ struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
+
+ if (regno >= info->video_cmap_len)
+ return 1;
+
+ *red = info->palette[regno].red;
+ *green = info->palette[regno].green;
+ *blue = info->palette[regno].blue;
+ *transp = 0;
+ return 0;
+}
+
+static int iga_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.
+ */
+
+ struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
+
+ if (regno >= info->video_cmap_len)
+ return 1;
+
+ info->palette[regno].red = red;
+ info->palette[regno].green = green;
+ info->palette[regno].blue = blue;
+
+ pci_outb(info, regno, DAC_W_INDEX);
+ pci_outb(info, red, DAC_DATA);
+ pci_outb(info, green, DAC_DATA);
+ pci_outb(info, blue, DAC_DATA);
+
+ if (regno << 16)
+ switch (default_var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ info->fbcon_cmap.cfb16[regno] =
+ (regno << 10) | (regno << 5) | regno;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ info->fbcon_cmap.cfb24[regno] =
+ (regno << 16) | (regno << 8) | regno;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ i = (regno << 8) | regno;
+ info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
+ break;
+#endif
+ }
+ return 0;
+}
+
+static void do_install_cmap(int con, struct fb_info *fb_info)
+{
+ struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
+
+ if (con != info->currcon)
+ return;
+ if (fb_display[con].cmap.len)
+ fb_set_cmap(&fb_display[con].cmap, 1,
+ iga_setcolreg, &info->fb_info);
+ else
+ fb_set_cmap(fb_default_cmap(info->video_cmap_len), 1,
+ iga_setcolreg, &info->fb_info);
+}
+
+static int igafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *fb_info)
+{
+ struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
+
+ if (con == info->currcon) /* current console? */
+ return fb_get_cmap(cmap, kspc, iga_getcolreg, &info->fb_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(info->video_cmap_len),
+ cmap, kspc ? 0 : 2);
+ return 0;
+}
+
+static int igafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ int err;
+ struct fb_info_iga *fb = (struct fb_info_iga*) info;
+
+ if (!fb_display[con].cmap.len) { /* no colormap allocated? */
+ err = fb_alloc_cmap(&fb_display[con].cmap,
+ fb->video_cmap_len,0);
+ if (err)
+ return err;
+ }
+ if (con == fb->currcon) /* current console? */
+ return fb_set_cmap(cmap, kspc, iga_setcolreg, info);
+ else
+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+ return 0;
+}
+
+static int igafb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ /* no panning */
+ return -EINVAL;
+}
+
+static int igafb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+ u_long arg, int con, struct fb_info *info)
+{
+ return -EINVAL;
+}
+
+/*
+ * Framebuffer option structure
+ */
+static struct fb_ops igafb_ops = {
+ igafb_open,
+ igafb_release,
+ igafb_get_fix,
+ igafb_get_var,
+ igafb_set_var,
+ igafb_get_cmap,
+ igafb_set_cmap,
+ igafb_pan_display,
+ igafb_ioctl,
+#ifdef __sparc__
+ igafb_mmap
+#else
+ NULL
+#endif
+};
+
+static void igafb_set_disp(int con, struct fb_info_iga *info)
+{
+ struct fb_fix_screeninfo fix;
+ struct display *display;
+ struct display_switch *sw;
+
+ if (con >= 0)
+ display = &fb_display[con];
+ else
+ display = &info->disp; /* used during initialization */
+
+ igafb_get_fix(&fix, con, &info->fb_info);
+
+ memset(display, 0, sizeof(struct display));
+ display->screen_base = (char*)info->frame_buffer;
+ 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;
+ igafb_get_var(&display->var, -1, &info->fb_info);
+
+ switch (default_var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ sw = &fbcon_cfb8;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 15:
+ case 16:
+ sw = &fbcon_cfb16;
+ display->dispsw_data = fbcon_cmap.cfb16;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ sw = &fbcon_cfb24;
+ display->dispsw_data = fbcon_cmap.cfb24;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ sw = &fbcon_cfb32;
+ display->dispsw_data = fbcon_cmap.cfb32;
+ break;
+#endif
+ default:
+ return;
+ }
+ memcpy(&info->dispsw, sw, sizeof(*sw));
+ display->dispsw = &info->dispsw;
+
+ display->scrollmode = SCROLL_YREDRAW;
+ info->dispsw.bmove = fbcon_redraw_bmove;
+}
+
+static int igafb_switch(int con, struct fb_info *fb_info)
+{
+ struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
+
+ /* Do we have to save the colormap? */
+ if (fb_display[info->currcon].cmap.len)
+ fb_get_cmap(&fb_display[info->currcon].cmap, 1,
+ iga_getcolreg, fb_info);
+
+ info->currcon = con;
+ /* Install new colormap */
+ do_install_cmap(con, fb_info);
+ igafb_update_var(con, fb_info);
+ return 1;
+}
+
+
+
+/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
+
+static void igafb_blank(int blank, struct fb_info *info)
+{
+ /* Not supported */
+}
+
+
+__initfunc(static int iga_init(struct fb_info_iga *info))
+{
+ char vramsz = iga_inb(info, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL)
+ & MEM_SIZE_ALIAS;
+ switch (vramsz) {
+ case MEM_SIZE_1M:
+ info->total_vram = 0x100000;
+ break;
+ case MEM_SIZE_2M:
+ info->total_vram = 0x200000;
+ break;
+ case MEM_SIZE_4M:
+ case MEM_SIZE_RESERVED:
+ info->total_vram = 0x400000;
+ break;
+ }
+
+ if (default_var.bits_per_pixel > 8) {
+ info->video_cmap_len = 16;
+ } else {
+ int i, j;
+ for(i = 0; i < 16; i++) {
+ j = color_table[i];
+ info->palette[i].red = default_red[j];
+ info->palette[i].green = default_grn[j];
+ info->palette[i].blue = default_blu[j];
+ }
+ info->video_cmap_len = 256;
+ }
+
+ strcpy(info->fb_info.modename, igafb_name);
+ info->fb_info.node = -1;
+ info->fb_info.fbops = &igafb_ops;
+ info->fb_info.disp = &info->disp;
+ strcpy(info->fb_info.fontname, fontname);
+ info->fb_info.changevar = NULL;
+ info->fb_info.switch_con = &igafb_switch;
+ info->fb_info.updatevar = &igafb_update_var;
+ info->fb_info.blank = &igafb_blank;
+ info->fb_info.flags=FBINFO_FLAG_DEFAULT;
+
+ {
+ int j, k;
+ 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];
+ }
+ }
+
+ igafb_set_disp(-1, info);
+
+ if (register_framebuffer(&info->fb_info) < 0)
+ return 0;
+
+ printk("fb%d: %s frame buffer device at 0x%08lx [%dMB VRAM]\n",
+ GET_FB_IDX(info->fb_info.node), igafb_name,
+ info->frame_buffer_phys, info->total_vram >> 20);
+
+ iga_blank_border(info);
+ return 1;
+}
+
+
+__initfunc(void igafb_init(void))
+{
+ struct pci_dev *pdev;
+ struct fb_info_iga *info;
+ unsigned long addr;
+ extern int con_is_present(void);
+
+ /* Do not attach when we have a serial console. */
+ if (!con_is_present())
+ return;
+
+ pdev = pci_find_device(PCI_VENDOR_ID_INTERG,
+ PCI_DEVICE_ID_INTERG_1682, 0);
+ if(pdev == NULL)
+ return;
+
+ info = kmalloc(sizeof(struct fb_info_iga), GFP_ATOMIC);
+ if (!info) {
+ printk("igafb_init: can't alloc fb_info_iga\n");
+ return;
+ }
+ memset(info, 0, sizeof(struct fb_info_iga));
+
+ info->frame_buffer = pdev->base_address[0];
+ if (!info->frame_buffer)
+ return;
+
+ pcibios_read_config_dword(0, pdev->devfn,
+ PCI_BASE_ADDRESS_0,
+ (unsigned int*)&addr);
+ if (!addr)
+ return;
+ info->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
+
+#ifdef __sparc__
+
+ info->io_base_phys = info->frame_buffer_phys;
+
+ /* Obtain virtual address and correct physical by PCIC shift */
+ info->io_base = pcic_alloc_io(&info->io_base_phys);
+ if (!info->io_base) {
+ return;
+ }
+
+ /*
+ * Figure mmap addresses from PCI config space.
+ * We need two regions: for video memory and for I/O ports.
+ * Later one can add region for video coprocessor registers.
+ * However, mmap routine loops until size != 0, so we put
+ * one additional region with size == 0.
+ */
+
+ info->mmap_map = kmalloc(4 * sizeof(*info->mmap_map), GFP_ATOMIC);
+ if (!info->mmap_map) {
+ printk("igafb_init: can't alloc mmap_map\n");
+ kfree(info);
+ return;
+ }
+
+ memset(info->mmap_map, 0, 4 * sizeof(*info->mmap_map));
+
+ /*
+ * 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;
+ }
+ }
+
+#endif
+ if (!iga_init(info)) {
+ if (info->mmap_map)
+ kfree(info->mmap_map);
+ kfree(info);
+ }
+
+#ifdef __sparc__
+ /*
+ * Add /dev/fb mmap values.
+ */
+
+ /* First region is for video memory */
+ info->mmap_map[0].voff = 0x0;
+ info->mmap_map[0].poff = info->frame_buffer_phys & PAGE_MASK;
+ info->mmap_map[0].size = info->total_vram & PAGE_MASK;
+ info->mmap_map[0].prot_mask = SRMMU_CACHE;
+ info->mmap_map[0].prot_flag = SRMMU_WRITE;
+
+ /* Second region is for I/O ports */
+ info->mmap_map[1].voff = info->frame_buffer_phys & PAGE_MASK;
+ info->mmap_map[1].poff = info->io_base_phys & PAGE_MASK;
+ info->mmap_map[1].size = PAGE_SIZE * 2; /* X wants 2 pages */
+ info->mmap_map[1].prot_mask = SRMMU_CACHE;
+ info->mmap_map[1].prot_flag = SRMMU_WRITE;
+#endif /* __sparc__ */
+}
+
+__initfunc(void igafb_setup(char *options, int *ints))
+{
+ char *this_opt;
+
+ 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;
+ }
+ }
+}
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
new file mode 100644
index 000000000..d50c403a6
--- /dev/null
+++ b/drivers/video/imsttfb.c
@@ -0,0 +1,1818 @@
+/*
+ * drivers/video/imsttfb.c -- frame buffer device for IMS TwinTurbo
+ *
+ * This file is derived from the powermac console "imstt" driver:
+ * Copyright (C) 1997 Sigurdur Asgeirsson
+ * With additional hacking by Jeffrey Kuskin (jsk@mojave.stanford.edu)
+ * Modified by Danilo Beuche 1998
+ * Some register values added by Damien Doligez, INRIA Rocquencourt
+ *
+ * This file was written by Ryan Nielsen (ran@krazynet.com)
+ * Most of the frame buffer device stuff was copied from atyfb.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/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/console.h>
+#include <linux/selection.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#if defined(CONFIG_PPC)
+#include <linux/nvram.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <video/macmodes.h>
+#endif
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+
+#ifndef __powerpc__
+#define eieio() /* Enforce In-order Execution of I/O */
+#endif
+
+enum {
+ IBM = 0x00,
+ TVP = 0x01
+};
+
+/* TwinTurbo (Cosmo) registers */
+enum {
+ S1SA = 0, /* 0x00 */
+ S2SA = 1, /* 0x04 */
+ SP = 2, /* 0x08 */
+ DSA = 3, /* 0x0C */
+ CNT = 4, /* 0x10 */
+ DP_OCTRL= 5, /* 0x14 */
+ BI = 8, /* 0x20 */
+ MBC = 9, /* 0x24 */
+ BLTCTL = 10, /* 0x28 */
+
+ /* Scan Timing Generator Registers */
+ HES = 12, /* 0x30 */
+ HEB = 13, /* 0x34 */
+ HSB = 14, /* 0x38 */
+ HT = 15, /* 0x3C */
+ VES = 16, /* 0x40 */
+ VEB = 17, /* 0x44 */
+ VSB = 18, /* 0x48 */
+ VT = 19, /* 0x4C */
+ HCIV = 20, /* 0x50 */
+ VCIV = 21, /* 0x54 */
+ TCDR = 22, /* 0x58 */
+ VIL = 23, /* 0x5C */
+ STGCTL = 24, /* 0x60 */
+
+ /* Screen Refresh Generator Registers */
+ SSR = 25, /* 0x64 */
+ HRIR = 26, /* 0x68 */
+ SPR = 27, /* 0x6C */
+ CMR = 28, /* 0x70 */
+ SRGCTL = 29, /* 0x74 */
+
+ /* RAM Refresh Generator Registers */
+ RRCIV = 30, /* 0x78 */
+ RRSC = 31, /* 0x7C */
+ RRCR = 34, /* 0x88 */
+
+ /* System Registers */
+ GIOE = 32, /* 0x80 */
+ GIO = 33, /* 0x84 */
+ SCR = 35, /* 0x8C */
+ SSTATUS = 36, /* 0x90 */
+ PRC = 37, /* 0x94 */
+
+#if 0
+ /* PCI Registers */
+ DVID = 0x00000000L,
+ SC = 0x00000004L,
+ CCR = 0x00000008L,
+ OG = 0x0000000CL,
+ BARM = 0x00000010L,
+ BARER = 0x00000030L,
+#endif
+};
+
+/* IBM ramdac direct registers */
+enum {
+ PADDRW = 0x00,
+ PDATA = 0x04,
+ PPMASK = 0x08,
+ PADDRR = 0x0c,
+ PIDXLO = 0x10,
+ PIDXHI = 0x14,
+ PIDXDATA= 0x18,
+ PIDXCTL = 0x1c
+};
+
+/* IBM ramdac indirect registers */
+enum {
+ CLKCTL = 0x02, /* (0x01) Miscellaneous Clock Control */
+ SYNCCTL = 0x03, /* (0x00) Sync Control */
+ HSYNCPOS = 0x04, /* (0x00) Horizontal Sync Position */
+ PWRMNGMT = 0x05, /* (0x00) Power Management */
+ DACOP = 0x06, /* (0x02) DAC Operation */
+ PALETCTL = 0x07, /* (0x00) Palette Control */
+ SYSCLKCTL = 0x08, /* (0x01) System Clock Control */
+ PIXFMT = 0x0a, /* () Pixel Format [bpp >> 3 + 2] */
+ BPP8 = 0x0b, /* () 8 Bits/Pixel Control */
+ BPP16 = 0x0c, /* () 16 Bits/Pixel Control [bit 1=1 for 565] */
+ BPP24 = 0x0d, /* () 24 Bits/Pixel Control */
+ BPP32 = 0x0e, /* () 32 Bits/Pixel Control */
+ PIXCTL1 = 0x10, /* (0x05) Pixel PLL Control 1 */
+ PIXCTL2 = 0x11, /* (0x00) Pixel PLL Control 2 */
+ SYSCLKN = 0x15, /* () System Clock N (System PLL Reference Divider) */
+ SYSCLKM = 0x16, /* () System Clock M (System PLL VCO Divider) */
+ SYSCLKP = 0x17, /* () System Clock P */
+ SYSCLKC = 0x18, /* () System Clock C */
+ /*
+ * Dot clock rate is 20MHz * (m + 1) / ((n + 1) * (p ? 2 * p : 1)
+ * c is charge pump bias which depends on the VCO frequency
+ */
+ PIXM0 = 0x20, /* () Pixel M 0 */
+ PIXN0 = 0x21, /* () Pixel N 0 */
+ PIXP0 = 0x22, /* () Pixel P 0 */
+ PIXC0 = 0x23, /* () Pixel C 0 */
+ CURSCTL = 0x30, /* (0x00) Cursor Control */
+ CURSXLO = 0x31, /* () Cursor X position, low 8 bits */
+ CURSXHI = 0x32, /* () Cursor X position, high 8 bits */
+ CURSYLO = 0x33, /* () Cursor Y position, low 8 bits */
+ CURSYHI = 0x34, /* () Cursor Y position, high 8 bits */
+ CURSHOTX = 0x35, /* () Cursor Hot Spot X */
+ CURSHOTY = 0x36, /* () Cursor Hot Spot Y */
+ CURSACCTL = 0x37, /* () Advanced Cursor Control Enable */
+ CURSACATTR = 0x38, /* () Advanced Cursor Attribute */
+ CURS1R = 0x40, /* () Cursor 1 Red */
+ CURS1G = 0x41, /* () Cursor 1 Green */
+ CURS1B = 0x42, /* () Cursor 1 Blue */
+ CURS2R = 0x43, /* () Cursor 2 Red */
+ CURS2G = 0x44, /* () Cursor 2 Green */
+ CURS2B = 0x45, /* () Cursor 2 Blue */
+ CURS3R = 0x46, /* () Cursor 3 Red */
+ CURS3G = 0x47, /* () Cursor 3 Green */
+ CURS3B = 0x48, /* () Cursor 3 Blue */
+ BORDR = 0x60, /* () Border Color Red */
+ BORDG = 0x61, /* () Border Color Green */
+ BORDB = 0x62, /* () Border Color Blue */
+ MISCTL1 = 0x70, /* (0x00) Miscellaneous Control 1 */
+ MISCTL2 = 0x71, /* (0x00) Miscellaneous Control 2 */
+ MISCTL3 = 0x72, /* (0x00) Miscellaneous Control 3 */
+ KEYCTL = 0x78 /* (0x00) Key Control/DB Operation */
+};
+
+/* TI TVP 3030 RAMDAC Direct Registers */
+enum {
+ TVPADDRW = 0x00, /* 0 Palette/Cursor RAM Write Adress/Index */
+ TVPPDATA = 0x04, /* 1 Palette Data RAM Data */
+ TVPPMASK = 0x08, /* 2 Pixel Read-Mask */
+ TVPPADRR = 0x0c, /* 3 Palette/Cursor RAM Read Adress */
+ TVPCADRW = 0x10, /* 4 Cursor/Overscan Color Write Address */
+ TVPCDATA = 0x14, /* 5 Cursor/Overscan Color Data */
+ /* 6 reserved */
+ TVPCADRR = 0x1c, /* 7 Cursor/Overscan Color Read Address */
+ /* 8 reserved */
+ TVPDCCTL = 0x24, /* 9 Direct Cursor Control */
+ TVPIDATA = 0x28, /* 10 Index Data */
+ TVPCRDAT = 0x2c, /* 11 Cursor RAM Data */
+ TVPCXPOL = 0x30, /* 12 Cursor-Position X LSB */
+ TVPCXPOH = 0x34, /* 13 Cursor-Position X MSB */
+ TVPCYPOL = 0x38, /* 14 Cursor-Position Y LSB */
+ TVPCYPOH = 0x3c, /* 15 Cursor-Position Y MSB */
+};
+
+/* TI TVP 3030 RAMDAC Indirect Registers */
+enum {
+ TVPIRREV = 0x01, /* Silicon Revision [RO] */
+ TVPIRICC = 0x06, /* Indirect Cursor Control (0x00) */
+ TVPIRBRC = 0x07, /* Byte Router Control (0xe4) */
+ TVPIRLAC = 0x0f, /* Latch Control (0x06) */
+ TVPIRTCC = 0x18, /* True Color Control (0x80) */
+ TVPIRMXC = 0x19, /* Multiplex Control (0x98) */
+ TVPIRCLS = 0x1a, /* Clock Selection (0x07) */
+ TVPIRPPG = 0x1c, /* Palette Page (0x00) */
+ TVPIRGEC = 0x1d, /* General Control (0x00) */
+ TVPIRMIC = 0x1e, /* Miscellaneous Control (0x00) */
+ TVPIRPLA = 0x2c, /* PLL Address */
+ TVPIRPPD = 0x2d, /* Pixel Clock PLL Data */
+ TVPIRMPD = 0x2e, /* Memory Clock PLL Data */
+ TVPIRLPD = 0x2f, /* Loop Clock PLL Data */
+ TVPIRCKL = 0x30, /* Color-Key Overlay Low */
+ TVPIRCKH = 0x31, /* Color-Key Overlay High */
+ TVPIRCRL = 0x32, /* Color-Key Red Low */
+ TVPIRCRH = 0x33, /* Color-Key Red High */
+ TVPIRCGL = 0x34, /* Color-Key Green Low */
+ TVPIRCGH = 0x35, /* Color-Key Green High */
+ TVPIRCBL = 0x36, /* Color-Key Blue Low */
+ TVPIRCBH = 0x37, /* Color-Key Blue High */
+ TVPIRCKC = 0x38, /* Color-Key Control (0x00) */
+ TVPIRMLC = 0x39, /* MCLK/Loop Clock Control (0x18) */
+ TVPIRSEN = 0x3a, /* Sense Test (0x00) */
+ TVPIRTMD = 0x3b, /* Test Mode Data */
+ TVPIRRML = 0x3c, /* CRC Remainder LSB [RO] */
+ TVPIRRMM = 0x3d, /* CRC Remainder MSB [RO] */
+ TVPIRRMS = 0x3e, /* CRC Bit Select [WO] */
+ TVPIRDID = 0x3f, /* Device ID [RO] (0x30) */
+ TVPIRRES = 0xff /* Software Reset [WO] */
+};
+
+struct initvalues {
+ __u8 addr, value;
+};
+
+static struct initvalues ibm_initregs[] __initdata = {
+ { CLKCTL, 0x21 },
+ { SYNCCTL, 0x00 },
+ { HSYNCPOS, 0x00 },
+ { PWRMNGMT, 0x00 },
+ { DACOP, 0x02 },
+ { PALETCTL, 0x00 },
+ { SYSCLKCTL, 0x01 },
+
+ /*
+ * Note that colors in X are correct only if all video data is
+ * passed through the palette in the DAC. That is, "indirect
+ * color" must be configured. This is the case for the IBM DAC
+ * used in the 2MB and 4MB cards, at least.
+ */
+ { BPP8, 0x00 },
+ { BPP16, 0x00 },
+ { BPP24, 0x00 },
+ { BPP32, 0x00 },
+
+ { PIXCTL1, 0x05 },
+ { PIXCTL2, 0x00 },
+ { SYSCLKN, 0x08 },
+ { SYSCLKM, 0x4f },
+ { SYSCLKP, 0x00 },
+ { SYSCLKC, 0x00 },
+ { CURSCTL, 0x02 },
+ { CURSACCTL, 0x01 },
+ { CURSACATTR, 0xa8 },
+ { CURS1R, 0xff },
+ { CURS1G, 0xff },
+ { CURS1B, 0xff },
+ { CURS2R, 0xff },
+ { CURS2G, 0xff },
+ { CURS2B, 0xff },
+ { CURS3R, 0xff },
+ { CURS3G, 0xff },
+ { CURS3B, 0xff },
+ { BORDR, 0xff },
+ { BORDG, 0xff },
+ { BORDB, 0xff },
+ { MISCTL1, 0x01 },
+ { MISCTL2, 0x45 },
+ { MISCTL3, 0x00 },
+ { KEYCTL, 0x00 }
+};
+
+static struct initvalues tvp_initregs[] __initdata = {
+ { 0x6, 0x00 },
+ { 0x7, 0xe4 },
+ { 0xf, 0x06 },
+ { 0x18, 0x80 },
+ { 0x19, 0x4d },
+ { 0x1a, 0x05 },
+ { 0x1c, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1e, 0x08 },
+ { 0x30, 0xff },
+ { 0x31, 0xff },
+ { 0x32, 0xff },
+ { 0x33, 0xff },
+ { 0x34, 0xff },
+ { 0x35, 0xff },
+ { 0x36, 0xff },
+ { 0x37, 0xff },
+ { 0x38, 0x00 },
+ { TVPIRPLA, 0x00 },
+ { TVPIRPPD, 0xc0 },
+ { TVPIRPPD, 0xd5 },
+ { TVPIRPPD, 0xea },
+ { TVPIRPLA, 0x00 },
+ { TVPIRMPD, 0xb9 },
+ { TVPIRMPD, 0x3a },
+ { TVPIRMPD, 0xb1 },
+ { TVPIRPLA, 0x00 },
+ { TVPIRLPD, 0xc1 },
+ { TVPIRLPD, 0x3d },
+ { TVPIRLPD, 0xf3 },
+};
+
+struct imstt_regvals {
+ __u32 pitch;
+ __u16 hes, heb, hsb, ht, ves, veb, vsb, vt, vil;
+ __u8 pclk_m, pclk_n, pclk_p;
+ /* Values of the tvp which change depending on colormode x resolution */
+ __u8 mlc[3]; /* Memory Loop Config 0x39 */
+ __u8 lckl_p[3]; /* P value of LCKL PLL */
+};
+
+struct imstt_cursor {
+ struct timer_list timer;
+ int enable;
+ int on;
+ int vbl_cnt;
+ int blink_rate;
+ __u16 x, y, width, height;
+};
+
+struct fb_info_imstt {
+ struct fb_info info;
+ struct fb_fix_screeninfo fix;
+ struct display disp;
+ struct display_switch dispsw;
+ union {
+#ifdef FBCON_HAS_CFB16
+ __u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+ __u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ __u32 cfb32[16];
+#endif
+ } fbcon_cmap;
+ struct {
+ __u8 red, green, blue;
+ } palette[256];
+ struct imstt_regvals init;
+ struct imstt_cursor cursor;
+ volatile __u8 *frame_buffer_phys, *frame_buffer;
+ volatile __u32 *dc_regs_phys, *dc_regs;
+ volatile __u8 *cmap_regs_phys, *cmap_regs;
+ __u32 total_vram;
+ __u32 ramdac;
+};
+
+#define USE_NV_MODES 1
+#define INIT_BPP 8
+#define INIT_XRES 640
+#define INIT_YRES 480
+#define CURSOR_BLINK_RATE 20
+#define CURSOR_DRAW_DELAY 2
+
+static int currcon = 0;
+static char fontname[40] __initdata = { 0 };
+static char curblink __initdata = 1;
+static char noaccel __initdata = 0;
+#if defined(CONFIG_PPC)
+static signed char init_vmode __initdata = -1, init_cmode __initdata = -1;
+#endif
+
+static struct imstt_regvals tvp_reg_init_2 = {
+ 512,
+ 0x0002, 0x0006, 0x0026, 0x0028, 0x0003, 0x0016, 0x0196, 0x0197, 0x0196,
+ 0xec, 0x2a, 0xf3,
+ { 0x3c, 0x3b, 0x39 }, { 0xf3, 0xf3, 0xf3 }
+};
+
+static struct imstt_regvals tvp_reg_init_6 = {
+ 640,
+ 0x0004, 0x0009, 0x0031, 0x0036, 0x0003, 0x002a, 0x020a, 0x020d, 0x020a,
+ 0xef, 0x2e, 0xb2,
+ { 0x39, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
+};
+
+static struct imstt_regvals tvp_reg_init_12 = {
+ 800,
+ 0x0005, 0x000e, 0x0040, 0x0042, 0x0003, 0x018, 0x270, 0x271, 0x270,
+ 0xf6, 0x2e, 0xf2,
+ { 0x3a, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
+};
+
+static struct imstt_regvals tvp_reg_init_13 = {
+ 832,
+ 0x0004, 0x0011, 0x0045, 0x0048, 0x0003, 0x002a, 0x029a, 0x029b, 0x0000,
+ 0xfe, 0x3e, 0xf1,
+ { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
+};
+
+static struct imstt_regvals tvp_reg_init_17 = {
+ 1024,
+ 0x0006, 0x0210, 0x0250, 0x0053, 0x1003, 0x0021, 0x0321, 0x0324, 0x0000,
+ 0xfc, 0x3a, 0xf1,
+ { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
+};
+
+static struct imstt_regvals tvp_reg_init_18 = {
+ 1152,
+ 0x0009, 0x0011, 0x059, 0x5b, 0x0003, 0x0031, 0x0397, 0x039a, 0x0000,
+ 0xfd, 0x3a, 0xf1,
+ { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
+};
+
+static struct imstt_regvals tvp_reg_init_19 = {
+ 1280,
+ 0x0009, 0x0016, 0x0066, 0x0069, 0x0003, 0x0027, 0x03e7, 0x03e8, 0x03e7,
+ 0xf7, 0x36, 0xf0,
+ { 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
+};
+
+static struct imstt_regvals tvp_reg_init_20 = {
+ 1280,
+ 0x0009, 0x0018, 0x0068, 0x006a, 0x0003, 0x0029, 0x0429, 0x042a, 0x0000,
+ 0xf0, 0x2d, 0xf0,
+ { 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
+};
+
+static __u32
+getclkMHz (struct fb_info_imstt *p)
+{
+ __u32 clk_m, clk_n, clk_p;
+
+ clk_m = p->init.pclk_m;
+ clk_n = p->init.pclk_n;
+ clk_p = p->init.pclk_p;
+
+ return 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1));
+}
+
+static void
+setclkMHz (struct fb_info_imstt *p, __u32 MHz)
+{
+ __u32 clk_m, clk_n, clk_p, x, stage, spilled;
+
+ clk_m = clk_n = clk_p = 0;
+ stage = spilled = 0;
+ for (;;) {
+ switch (stage) {
+ case 0:
+ clk_m++;
+ break;
+ case 1:
+ clk_n++;
+ break;
+ }
+ x = 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1));
+ if (x == MHz)
+ break;
+ if (x > MHz) {
+ spilled = 1;
+ stage = 1;
+ } else if (spilled && x < MHz) {
+ stage = 0;
+ }
+ }
+
+ p->init.pclk_m = clk_m;
+ p->init.pclk_n = clk_n;
+ p->init.pclk_p = clk_p;
+}
+
+static struct imstt_regvals *
+compute_imstt_regvals_ibm (struct fb_info_imstt *p, int xres, int yres)
+{
+ struct imstt_regvals *init = &p->init;
+ __u32 MHz, hes, heb, veb, htp, vtp;
+
+ switch (xres) {
+ case 640:
+ hes = 0x0008; heb = 0x0012; veb = 0x002a; htp = 10; vtp = 2;
+ MHz = 30 /* .25 */ ;
+ break;
+ case 832:
+ hes = 0x0005; heb = 0x0020; veb = 0x0028; htp = 8; vtp = 3;
+ MHz = 57 /* .27_ */ ;
+ break;
+ case 1024:
+ hes = 0x000a; heb = 0x001c; veb = 0x0020; htp = 8; vtp = 3;
+ MHz = 80;
+ break;
+ case 1152:
+ hes = 0x0012; heb = 0x0022; veb = 0x0031; htp = 4; vtp = 3;
+ MHz = 101 /* .6_ */ ;
+ break;
+ case 1280:
+ hes = 0x0012; heb = 0x002f; veb = 0x0029; htp = 4; vtp = 1;
+ MHz = yres == 960 ? 126 : 135;
+ break;
+ case 1600:
+ hes = 0x0018; heb = 0x0040; veb = 0x002a; htp = 4; vtp = 3;
+ MHz = 200;
+ break;
+ default:
+ return 0;
+ }
+
+ setclkMHz(p, MHz);
+
+ init->hes = hes;
+ init->heb = heb;
+ init->hsb = init->heb + (xres >> 3);
+ init->ht = init->hsb + htp;
+ init->ves = 0x0003;
+ init->veb = veb;
+ init->vsb = init->veb + yres;
+ init->vt = init->vsb + vtp;
+ init->vil = init->vsb;
+
+ init->pitch = xres;
+
+ return init;
+}
+
+static struct imstt_regvals *
+compute_imstt_regvals_tvp (struct fb_info_imstt *p, int xres, int yres)
+{
+ struct imstt_regvals *init;
+
+ switch (xres) {
+ case 512:
+ init = &tvp_reg_init_2;
+ break;
+ case 640:
+ init = &tvp_reg_init_6;
+ break;
+ case 800:
+ init = &tvp_reg_init_12;
+ break;
+ case 832:
+ init = &tvp_reg_init_13;
+ break;
+ case 1024:
+ init = &tvp_reg_init_17;
+ break;
+ case 1152:
+ init = &tvp_reg_init_18;
+ break;
+ case 1280:
+ init = yres == 960 ? &tvp_reg_init_19 : &tvp_reg_init_20;
+ break;
+ default:
+ return 0;
+ }
+ p->init = *init;
+
+ return init;
+}
+
+static struct imstt_regvals *
+compute_imstt_regvals (struct fb_info_imstt *p, u_int xres, u_int yres)
+{
+ if (p->ramdac == IBM)
+ return compute_imstt_regvals_ibm(p, xres, yres);
+ else
+ return compute_imstt_regvals_tvp(p, xres, yres);
+}
+
+static void
+set_imstt_regvals_ibm (struct fb_info_imstt *p, u_int bpp)
+{
+ struct imstt_regvals *init = &p->init;
+ __u8 pformat = (bpp >> 3) + 2;
+
+ p->cmap_regs[PIDXHI] = 0; eieio();
+ p->cmap_regs[PIDXLO] = PIXM0; eieio();
+ p->cmap_regs[PIDXDATA] = init->pclk_m; eieio();
+ p->cmap_regs[PIDXLO] = PIXN0; eieio();
+ p->cmap_regs[PIDXDATA] = init->pclk_n; eieio();
+ p->cmap_regs[PIDXLO] = PIXP0; eieio();
+ p->cmap_regs[PIDXDATA] = init->pclk_p; eieio();
+ p->cmap_regs[PIDXLO] = PIXC0; eieio();
+ p->cmap_regs[PIDXDATA] = 0x02; eieio();
+
+ p->cmap_regs[PIDXLO] = PIXFMT; eieio();
+ p->cmap_regs[PIDXDATA] = pformat; eieio();
+}
+
+static void
+set_imstt_regvals_tvp (struct fb_info_imstt *p, u_int bpp)
+{
+ struct imstt_regvals *init = &p->init;
+ __u8 tcc, mxc, lckl_n, mic;
+ __u8 mlc, lckl_p;
+
+ switch (bpp) {
+ case 8:
+ tcc = 0x80;
+ mxc = 0x4d;
+ lckl_n = 0xc1;
+ mlc = init->mlc[0];
+ lckl_p = init->lckl_p[0];
+ break;
+ case 16:
+ tcc = 0x44;
+ mxc = 0x55;
+ lckl_n = 0xe1;
+ mlc = init->mlc[1];
+ lckl_p = init->lckl_p[1];
+ break;
+ case 24:
+ /* ?!? */
+ case 32:
+ tcc = 0x46;
+ mxc = 0x5d;
+ lckl_n = 0xf1;
+ mlc = init->mlc[2];
+ lckl_p = init->lckl_p[2];
+ break;
+ }
+ mic = 0x08;
+
+ p->cmap_regs[TVPADDRW] = TVPIRPLA; eieio();
+ p->cmap_regs[TVPIDATA] = 0x00; eieio();
+ p->cmap_regs[TVPADDRW] = TVPIRPPD; eieio();
+ p->cmap_regs[TVPIDATA] = init->pclk_m; eieio();
+ p->cmap_regs[TVPADDRW] = TVPIRPPD; eieio();
+ p->cmap_regs[TVPIDATA] = init->pclk_n; eieio();
+ p->cmap_regs[TVPADDRW] = TVPIRPPD; eieio();
+ p->cmap_regs[TVPIDATA] = init->pclk_p; eieio();
+
+ p->cmap_regs[TVPADDRW] = TVPIRTCC; eieio();
+ p->cmap_regs[TVPIDATA] = tcc; eieio();
+ p->cmap_regs[TVPADDRW] = TVPIRMXC; eieio();
+ p->cmap_regs[TVPIDATA] = mxc; eieio();
+ p->cmap_regs[TVPADDRW] = TVPIRMIC; eieio();
+ p->cmap_regs[TVPIDATA] = mic; eieio();
+
+ p->cmap_regs[TVPADDRW] = TVPIRPLA; eieio();
+ p->cmap_regs[TVPIDATA] = 0x00; eieio();
+ p->cmap_regs[TVPADDRW] = TVPIRLPD; eieio();
+ p->cmap_regs[TVPIDATA] = lckl_n; eieio();
+
+ p->cmap_regs[TVPADDRW] = TVPIRPLA; eieio();
+ p->cmap_regs[TVPIDATA] = 0x15; eieio();
+ p->cmap_regs[TVPADDRW] = TVPIRMLC; eieio();
+ p->cmap_regs[TVPIDATA] = mlc; eieio();
+
+ p->cmap_regs[TVPADDRW] = TVPIRPLA; eieio();
+ p->cmap_regs[TVPIDATA] = 0x2a; eieio();
+ p->cmap_regs[TVPADDRW] = TVPIRLPD; eieio();
+ p->cmap_regs[TVPIDATA] = lckl_p; eieio();
+}
+
+static void
+set_imstt_regvals (struct fb_info_imstt *p, u_int bpp)
+{
+ struct imstt_regvals *init = &p->init;
+ __u32 ctl, pitch, byteswap, scr, line_pitch = init->pitch * (bpp >> 3);
+
+ if (p->ramdac == IBM)
+ set_imstt_regvals_ibm(p, bpp);
+ else
+ set_imstt_regvals_tvp(p, bpp);
+
+ /*
+ * From what I (jsk) can gather poking around with MacsBug,
+ * bits 8 and 9 in the SCR register control endianness
+ * correction (byte swapping). These bits must be set according
+ * to the color depth as follows:
+ * Color depth Bit 9 Bit 8
+ * ========== ===== =====
+ * 8bpp 0 0
+ * 16bpp 0 1
+ * 24bpp 1 0
+ * 32bpp 1 1
+ */
+ switch (bpp) {
+ case 8:
+ ctl = 0x17b1;
+ pitch = init->pitch >> 2;
+ byteswap = 0x000;
+ break;
+ case 16:
+ ctl = 0x17b3;
+ pitch = init->pitch >> 1;
+ byteswap = 0x100;
+ break;
+ case 24:
+ ctl = 0x17b9;
+ pitch = init->pitch - (p->init.pitch >> 2);
+ byteswap = 0x200;
+ break;
+ case 32:
+ ctl = 0x17b5;
+ pitch = init->pitch;
+ byteswap = 0x300;
+ break;
+ }
+ if (p->ramdac == TVP)
+ ctl -= 0x30;
+
+ out_le32(&p->dc_regs[HES], init->hes);
+ out_le32(&p->dc_regs[HEB], init->heb);
+ out_le32(&p->dc_regs[HSB], init->hsb);
+ out_le32(&p->dc_regs[HT], init->ht);
+ out_le32(&p->dc_regs[VES], init->ves);
+ out_le32(&p->dc_regs[VEB], init->veb);
+ out_le32(&p->dc_regs[VSB], init->vsb);
+ out_le32(&p->dc_regs[VT], init->vt);
+ out_le32(&p->dc_regs[VIL], init->vil);
+ out_le32(&p->dc_regs[HCIV], 1);
+ out_le32(&p->dc_regs[VCIV], 1);
+ out_le32(&p->dc_regs[TCDR], 4);
+ out_le32(&p->dc_regs[RRCIV], 1);
+ out_le32(&p->dc_regs[RRSC], 0x980);
+ out_le32(&p->dc_regs[RRCR], 0x11);
+
+ if (p->ramdac == IBM) {
+ out_le32(&p->dc_regs[HRIR], 0x0100);
+ out_le32(&p->dc_regs[CMR], 0x00ff);
+ out_le32(&p->dc_regs[SRGCTL], 0x0073);
+ } else {
+ out_le32(&p->dc_regs[HRIR], 0x0200);
+ out_le32(&p->dc_regs[CMR], 0x01ff);
+ out_le32(&p->dc_regs[SRGCTL], 0x0003);
+ }
+
+ switch (p->total_vram) {
+ case 0x00200000:
+ scr = 0x059d | byteswap;
+ break;
+ case 0x00400000:
+ case 0x00800000:
+ pitch /= 2;
+ scr = 0x150dd | byteswap;
+ break;
+ }
+
+ out_le32(&p->dc_regs[SCR], scr);
+ out_le32(&p->dc_regs[SPR], pitch);
+ out_le32(&p->dc_regs[SP], (line_pitch << 16) | line_pitch);
+ out_le32(&p->dc_regs[DP_OCTRL], line_pitch);
+
+ out_le32(&p->dc_regs[STGCTL], ctl);
+}
+
+static void
+set_16 (struct fb_info_imstt *p, __u8 x)
+{
+ if (p->ramdac == IBM) {
+ p->cmap_regs[PIDXHI] = 0; eieio();
+ p->cmap_regs[PIDXLO] = BPP16; eieio();
+ p->cmap_regs[PIDXDATA] = x; eieio();
+ } else {
+ /* ?!? */
+ }
+}
+
+#define set_555(_p) set_16(_p, 0x01)
+#define set_565(_p) set_16(_p, 0x03)
+
+static void
+imstt_set_cursor (struct fb_info_imstt *p, int on)
+{
+ struct imstt_cursor *c = &p->cursor;
+
+ p->cmap_regs[PIDXHI] = 0;
+ if (!on) {
+ p->cmap_regs[PIDXLO] = CURSCTL; eieio();
+ p->cmap_regs[PIDXDATA] = 0x00; eieio();
+ } else {
+ p->cmap_regs[PIDXLO] = CURSXHI; eieio();
+ p->cmap_regs[PIDXDATA] = c->x >> 8; eieio();
+ p->cmap_regs[PIDXLO] = CURSXLO; eieio();
+ p->cmap_regs[PIDXDATA] = c->x & 0xff; eieio();
+ p->cmap_regs[PIDXLO] = CURSYHI; eieio();
+ p->cmap_regs[PIDXDATA] = c->y >> 8; eieio();
+ p->cmap_regs[PIDXLO] = CURSYLO; eieio();
+ p->cmap_regs[PIDXDATA] = c->y & 0xff; eieio();
+ p->cmap_regs[PIDXLO] = CURSCTL; eieio();
+ p->cmap_regs[PIDXDATA] = 0x02; eieio();
+ }
+}
+
+static void
+imsttfb_cursor (struct display *disp, int mode, int x, int y)
+{
+ struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
+ struct imstt_cursor *c = &p->cursor;
+
+ x *= fontwidth(disp);
+ y *= fontheight(disp);
+
+ if (c->x == x && c->y == y && (mode == CM_ERASE) == !c->enable)
+ return;
+
+ c->enable = 0;
+ if (c->on)
+ imstt_set_cursor(p, 0);
+ c->x = x - disp->var.xoffset;
+ c->y = y - disp->var.yoffset;
+
+ switch (mode) {
+ case CM_ERASE:
+ c->on = 0;
+ break;
+ case CM_DRAW:
+ case CM_MOVE:
+ if (c->on)
+ imstt_set_cursor(p, c->on);
+ else
+ c->vbl_cnt = CURSOR_DRAW_DELAY;
+ c->enable = 1;
+ break;
+ }
+}
+
+static int
+imsttfb_set_font (struct display *disp, int width, int height)
+{
+ struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
+ struct imstt_cursor *c = &p->cursor;
+ u_int x, y;
+
+ if (width > 32 || height > 32)
+ return -EINVAL;
+
+ c->height = height;
+ c->width = width;
+
+ p->cmap_regs[PIDXHI] = 1; eieio();
+ for (x = 0; x < 0x100; x++) {
+ p->cmap_regs[PIDXLO] = x; eieio();
+ p->cmap_regs[PIDXDATA] = 0x00; eieio();
+ }
+ p->cmap_regs[PIDXHI] = 1; eieio();
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width >> 2; x++) {
+ p->cmap_regs[PIDXLO] = x + y * 8; eieio();
+ p->cmap_regs[PIDXDATA] = 0xff; eieio();
+ }
+
+ return 1;
+}
+
+static void
+imstt_cursor_timer_handler (unsigned long dev_addr)
+{
+ struct fb_info_imstt *p = (struct fb_info_imstt *)dev_addr;
+ struct imstt_cursor *c = &p->cursor;
+
+ if (!c->enable)
+ goto out;
+
+ if (c->vbl_cnt && --c->vbl_cnt == 0) {
+ c->on ^= 1;
+ imstt_set_cursor(p, c->on);
+ c->vbl_cnt = c->blink_rate;
+ }
+
+out:
+ c->timer.expires = jiffies + (HZ / 50);
+ add_timer(&c->timer);
+}
+
+__initfunc(static void
+imstt_cursor_init (struct fb_info_imstt *p))
+{
+ struct imstt_cursor *c = &p->cursor;
+
+ imsttfb_set_font(&p->disp, fontwidth(&p->disp), fontheight(&p->disp));
+
+ c->enable = 1;
+ c->on = 1;
+ c->x = c->y = 0;
+ c->blink_rate = 0;
+ c->vbl_cnt = CURSOR_DRAW_DELAY;
+
+ if (curblink) {
+ c->blink_rate = CURSOR_BLINK_RATE;
+ init_timer(&c->timer);
+ c->timer.expires = jiffies + (HZ / 50);
+ c->timer.data = (unsigned long)p;
+ c->timer.function = imstt_cursor_timer_handler;
+ add_timer(&c->timer);
+ }
+}
+
+static void
+imsttfb_rectcopy (struct display *disp, int sy, int sx, int dy, int dx, int height, int width)
+{
+ struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
+ __u32 Bpp = disp->var.bits_per_pixel >> 3,
+ line_pitch = disp->line_length,
+ fb_offset_old, fb_offset_new;
+
+ fb_offset_old = sy * line_pitch + sx * Bpp;
+ fb_offset_new = dy * line_pitch + dx * Bpp;
+
+ while (in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+ out_le32(&p->dc_regs[CNT], ((height - 1) << 16) | (width * Bpp - 1));
+ out_le32(&p->dc_regs[S1SA], fb_offset_old);
+ /* out_le32(&p->dc_regs[S2SA], fb_offset_new); */
+ out_le32(&p->dc_regs[DSA], fb_offset_new);
+ out_le32(&p->dc_regs[BLTCTL], 0xc0000005);
+ while (in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+ while (in_le32(&p->dc_regs[SSTATUS]) & 0x40);
+}
+
+static void
+imsttfbcon_bmove (struct display *disp, int sy, int sx, int dy, int dx, int height, int width)
+{
+ /* XXX .. */
+ if (sy < dy || (sy == dy && sx < dx)) {
+ switch (disp->var.bits_per_pixel) {
+ case 8: fbcon_cfb8_bmove(disp, sy, sx, dy, dx, height, width); break;
+ case 16: fbcon_cfb16_bmove(disp, sy, sx, dy, dx, height, width); break;
+ case 24: fbcon_cfb24_bmove(disp, sy, sx, dy, dx, height, width); break;
+ case 32: fbcon_cfb32_bmove(disp, sy, sx, dy, dx, height, width); break;
+ }
+ return;
+ }
+
+ sy *= fontheight(disp);
+ sx *= fontwidth(disp);
+ dy *= fontheight(disp);
+ dx *= fontwidth(disp);
+ height *= fontheight(disp);
+ width *= fontwidth(disp);
+
+ imsttfb_rectcopy(disp, sy, sx, dy, dx, height, width);
+}
+
+#ifdef FBCON_HAS_CFB8
+static struct display_switch fbcon_imstt8 = {
+ fbcon_cfb8_setup, imsttfbcon_bmove, fbcon_cfb8_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
+#ifdef FBCON_HAS_CFB16
+static struct display_switch fbcon_imstt16 = {
+ fbcon_cfb16_setup, imsttfbcon_bmove, fbcon_cfb16_clear, fbcon_cfb16_putc,
+ fbcon_cfb16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins,
+ FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+#ifdef FBCON_HAS_CFB24
+static struct display_switch fbcon_imstt24 = {
+ fbcon_cfb24_setup, imsttfbcon_bmove, fbcon_cfb24_clear, fbcon_cfb24_putc,
+ fbcon_cfb24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_cfb24_clear_margins,
+ FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+#ifdef FBCON_HAS_CFB32
+static struct display_switch fbcon_imstt32 = {
+ fbcon_cfb32_setup, imsttfbcon_bmove, fbcon_cfb32_clear, fbcon_cfb32_putc,
+ fbcon_cfb32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_cfb32_clear_margins,
+ FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+
+#ifdef CONFIG_FB_COMPAT_XPMAC
+#include <asm/vc_ioctl.h>
+
+extern struct vc_mode display_info;
+extern struct fb_info *console_fb_info;
+
+static void
+set_display_info (struct display *disp)
+{
+ display_info.width = disp->var.xres;
+ display_info.height = disp->var.yres;
+ display_info.depth = disp->var.bits_per_pixel;
+ display_info.pitch = disp->line_length;
+
+ switch (disp->var.xres) {
+ case 512:
+ display_info.mode = 2;
+ break;
+ case 640:
+ display_info.mode = 6;
+ break;
+ case 800:
+ display_info.mode = 12;
+ break;
+ case 832:
+ display_info.mode = 13;
+ break;
+ case 1024:
+ display_info.mode = 17;
+ break;
+ case 1152:
+ display_info.mode = 18;
+ break;
+ case 1280:
+ display_info.mode = disp->var.yres == 960 ? 19 : 20;
+ break;
+ default:
+ display_info.mode = 0;
+ }
+}
+#endif
+
+static int
+imsttfb_getcolreg (u_int regno, u_int *red, u_int *green,
+ u_int *blue, u_int *transp, struct fb_info *info)
+{
+ struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+
+ if (regno > 255)
+ return 1;
+ *red = (p->palette[regno].red << 8) | p->palette[regno].red;
+ *green = (p->palette[regno].green << 8) | p->palette[regno].green;
+ *blue = (p->palette[regno].blue << 8) | p->palette[regno].blue;
+ *transp = 0;
+
+ return 0;
+}
+
+static int
+imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
+{
+ struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+ u_int bpp = fb_display[currcon].var.bits_per_pixel;
+ u_int i;
+
+ if (regno > 255)
+ return 1;
+
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+
+ p->palette[regno].red = red;
+ p->palette[regno].green = green;
+ p->palette[regno].blue = blue;
+
+ /* PADDRW/PDATA are the same as TVPPADDRW/TVPPDATA */
+ if (bpp == 16 && p->ramdac == TVP && fb_display[currcon].var.green.length == 5) {
+ p->cmap_regs[PADDRW] = regno << 3; eieio();
+ } else {
+ p->cmap_regs[PADDRW] = regno; eieio();
+ }
+ p->cmap_regs[PDATA] = red; eieio();
+ p->cmap_regs[PDATA] = green; eieio();
+ p->cmap_regs[PDATA] = blue; eieio();
+
+ if (regno < 16)
+ switch (bpp) {
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ p->fbcon_cmap.cfb16[regno] = (regno << (fb_display[currcon].var.green.length == 5 ? 10 : 11)) | (regno << 5) | regno;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ p->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) | regno;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ i = (regno << 8) | regno;
+ p->fbcon_cmap.cfb32[regno] = (i << 16) | i;
+ break;
+#endif
+ }
+
+ return 0;
+}
+
+static void
+do_install_cmap (int con, struct fb_info *info)
+{
+ if (fb_display[con].cmap.len)
+ fb_set_cmap(&fb_display[con].cmap, 1, imsttfb_setcolreg, info);
+ else {
+ u_int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+ fb_set_cmap(fb_default_cmap(size), 1, imsttfb_setcolreg, info);
+ }
+}
+
+static int
+imsttfb_open (struct fb_info *info, int user)
+{
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int
+imsttfb_release (struct fb_info *info, int user)
+{
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static int
+imsttfb_get_fix (struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+ struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+ struct fb_var_screeninfo *var = &fb_display[con].var;
+
+ *fix = p->fix;
+ fix->visual = var->bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
+ : FB_VISUAL_DIRECTCOLOR;
+ fix->line_length = var->xres * (var->bits_per_pixel >> 3);
+
+ return 0;
+}
+
+static int
+imsttfb_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+ *var = fb_display[con].var;
+
+ return 0;
+}
+
+static void
+set_disp (struct display *disp, struct fb_info_imstt *p)
+{
+ u_int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
+
+ p->dispsw = fbcon_dummy;
+ disp->dispsw = &p->dispsw;
+ disp->dispsw_data = 0;
+ switch (disp->var.bits_per_pixel) {
+ case 8:
+ disp->var.red.offset = 0;
+ disp->var.red.length = 8;
+ disp->var.green.offset = 0;
+ disp->var.green.length = 8;
+ disp->var.blue.offset = 0;
+ disp->var.blue.length = 8;
+ disp->var.transp.offset = 0;
+ disp->var.transp.length = 0;
+#ifdef FBCON_HAS_CFB8
+ p->dispsw = accel ? fbcon_imstt8 : fbcon_cfb8;
+#endif
+ break;
+ case 16: /* RGB 555 */
+ if (disp->var.green.length != 6)
+ disp->var.red.offset = 10;
+ disp->var.red.length = 5;
+ disp->var.green.offset = 5;
+ if (disp->var.green.length != 6)
+ disp->var.green.length = 5;
+ disp->var.blue.offset = 0;
+ disp->var.blue.length = 5;
+ disp->var.transp.offset = 0;
+ disp->var.transp.length = 0;
+#ifdef FBCON_HAS_CFB16
+ p->dispsw = accel ? fbcon_imstt16 : fbcon_cfb16;
+ disp->dispsw_data = p->fbcon_cmap.cfb16;
+#endif
+ break;
+ case 24: /* RGB 888 */
+ disp->var.red.offset = 16;
+ disp->var.red.length = 8;
+ disp->var.green.offset = 8;
+ disp->var.green.length = 8;
+ disp->var.blue.offset = 0;
+ disp->var.blue.length = 8;
+ disp->var.transp.offset = 0;
+ disp->var.transp.length = 0;
+#ifdef FBCON_HAS_CFB24
+ p->dispsw = accel ? fbcon_imstt24 : fbcon_cfb24;
+ disp->dispsw_data = p->fbcon_cmap.cfb24;
+#endif
+ break;
+ case 32: /* RGBA 8888 */
+ disp->var.red.offset = 16;
+ disp->var.red.length = 8;
+ disp->var.green.offset = 8;
+ disp->var.green.length = 8;
+ disp->var.blue.offset = 0;
+ disp->var.blue.length = 8;
+ disp->var.transp.offset = 24;
+ disp->var.transp.length = 8;
+#ifdef FBCON_HAS_CFB32
+ p->dispsw = accel ? fbcon_imstt32 : fbcon_cfb32;
+ disp->dispsw_data = p->fbcon_cmap.cfb32;
+#endif
+ break;
+ }
+
+ if (p->ramdac == IBM) {
+ p->dispsw.cursor = imsttfb_cursor;
+ p->dispsw.set_font = imsttfb_set_font;
+ }
+
+ disp->visual = disp->var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
+ : FB_VISUAL_DIRECTCOLOR;
+ disp->screen_base = (__u8 *)p->frame_buffer;
+ disp->visual = p->fix.visual;
+ disp->type = p->fix.type;
+ disp->type_aux = p->fix.type_aux;
+ disp->line_length = disp->var.xres * (disp->var.bits_per_pixel >> 3);
+ disp->can_soft_blank = 1;
+ disp->inverse = 0;
+ disp->ypanstep = 1;
+ disp->ywrapstep = 0;
+ if (accel) {
+ disp->scrollmode = SCROLL_YNOMOVE;
+ if (disp->var.yres == disp->var.yres_virtual) {
+ __u32 vram = (p->total_vram - (PAGE_SIZE << 2));
+ disp->var.yres_virtual = ((vram << 3) / disp->var.bits_per_pixel) / disp->var.xres_virtual;
+ if (disp->var.yres_virtual < disp->var.yres)
+ disp->var.yres_virtual = disp->var.yres;
+ }
+ } else {
+ disp->scrollmode = SCROLL_YREDRAW;
+ disp->var.yoffset = disp->var.xoffset = 0;
+ out_le32(&p->dc_regs[SSR], 0);
+ }
+
+ disp->var.activate = 0;
+ disp->var.red.msb_right = 0;
+ disp->var.green.msb_right = 0;
+ disp->var.blue.msb_right = 0;
+ disp->var.transp.msb_right = 0;
+ disp->var.height = -1;
+ disp->var.width = -1;
+ disp->var.vmode = FB_VMODE_NONINTERLACED;
+ disp->var.left_margin = disp->var.right_margin = 16;
+ disp->var.upper_margin = disp->var.lower_margin = 16;
+ disp->var.hsync_len = disp->var.vsync_len = 8;
+
+#ifdef CONFIG_FB_COMPAT_XPMAC
+ set_display_info(disp);
+#endif
+}
+
+static int
+imsttfb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+ struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+ struct display *disp;
+ u_int oldbpp, oldxres, oldyres, oldgreenlen;
+
+ disp = &fb_display[con];
+
+ if ((var->bits_per_pixel != 8 && var->bits_per_pixel != 16
+ && var->bits_per_pixel != 24 && var->bits_per_pixel != 32)
+ || var->xres_virtual < var->xres || var->yres_virtual < var->yres
+ || var->nonstd
+ || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+ return -EINVAL;
+
+ if ((var->xres * var->yres) * (var->bits_per_pixel >> 3) > p->total_vram
+ || (var->xres_virtual * var->yres_virtual) * (var->bits_per_pixel >> 3) > p->total_vram)
+ return -EINVAL;
+
+ if (!((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW))
+ return 0;
+
+ if (!compute_imstt_regvals(p, var->xres, var->yres))
+ return -EINVAL;
+
+ oldbpp = disp->var.bits_per_pixel;
+ oldxres = disp->var.xres;
+ oldyres = disp->var.yres;
+ oldgreenlen = disp->var.green.length;
+
+ disp->var.bits_per_pixel = var->bits_per_pixel;
+ disp->var.xres = var->xres;
+ disp->var.yres = var->yres;
+ disp->var.xres_virtual = var->xres_virtual;
+ disp->var.yres_virtual = var->yres_virtual;
+ disp->var.green.length = var->green.length;
+ disp->var.accel_flags = var->accel_flags;
+
+ set_disp(disp, p);
+
+ if (info->changevar)
+ (*info->changevar)(con);
+
+ if (con == currcon) {
+ if (oldgreenlen != disp->var.green.length) {
+ if (disp->var.green.length == 6)
+ set_565(p);
+ else
+ set_555(p);
+ }
+ if (oldxres != disp->var.xres || oldyres != disp->var.yres || oldbpp != disp->var.bits_per_pixel)
+ set_imstt_regvals(p, disp->var.bits_per_pixel);
+
+ }
+ disp->var.pixclock = 1000000 / getclkMHz(p);
+
+ if (oldbpp != disp->var.bits_per_pixel) {
+ int err = fb_alloc_cmap(&disp->cmap, 0, 0);
+ if (err)
+ return err;
+ do_install_cmap(con, info);
+ }
+
+ return 0;
+}
+
+static int
+imsttfb_pan_display (struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+ struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+ struct display *disp = &fb_display[con];
+ __u32 off;
+
+ if (var->xoffset + disp->var.xres > disp->var.xres_virtual
+ || var->yoffset + disp->var.yres > disp->var.yres_virtual)
+ return -EINVAL;
+
+ disp->var.xoffset = var->xoffset;
+ disp->var.yoffset = var->yoffset;
+ if (con == currcon) {
+ off = var->yoffset * (disp->line_length >> 3)
+ + ((var->xoffset * (disp->var.bits_per_pixel >> 3)) >> 3);
+ out_le32(&p->dc_regs[SSR], off);
+ }
+
+ return 0;
+}
+
+static int
+imsttfb_get_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
+{
+ if (con == currcon) /* current console? */
+ return fb_get_cmap(cmap, kspc, imsttfb_getcolreg, info);
+ else if (fb_display[con].cmap.len) /* non default colormap? */
+ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+ else {
+ u_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
+imsttfb_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? */
+ 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? */
+ return fb_set_cmap(cmap, kspc, imsttfb_setcolreg, info);
+ else
+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+
+ return 0;
+}
+
+#define FBIMSTT_SETREG 0x545401
+#define FBIMSTT_GETREG 0x545402
+#define FBIMSTT_SETCMAPREG 0x545403
+#define FBIMSTT_GETCMAPREG 0x545404
+#define FBIMSTT_SETIDXREG 0x545405
+#define FBIMSTT_GETIDXREG 0x545406
+
+static int
+imsttfb_ioctl (struct inode *inode, struct file *file, u_int cmd,
+ u_long arg, int con, struct fb_info *info)
+{
+ struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+ __u8 init[2];
+ __u32 reg[2];
+
+ switch (cmd) {
+ case FBIMSTT_SETREG:
+ if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x40000 - sizeof(reg[0])) / sizeof(reg[0]))
+ return -EFAULT;
+ out_le32(&p->dc_regs[reg[0]], reg[1]);
+ return 0;
+ case FBIMSTT_GETREG:
+ if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x40000 - sizeof(reg[0])) / sizeof(reg[0]))
+ return -EFAULT;
+ reg[1] = in_le32(&p->dc_regs[reg[0]]);
+ if (copy_to_user((void *)(arg + 4), &reg[1], 4))
+ return -EFAULT;
+ return 0;
+ case FBIMSTT_SETCMAPREG:
+ if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x17c0000 - sizeof(reg[0])) / sizeof(reg[0]))
+ return -EFAULT;
+ out_le32(&((u_int *)p->cmap_regs)[reg[0]], reg[1]);
+ return 0;
+ case FBIMSTT_GETCMAPREG:
+ if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x17c0000 - sizeof(reg[0])) / sizeof(reg[0]))
+ return -EFAULT;
+ reg[1] = in_le32(&((u_int *)p->cmap_regs)[reg[0]]);
+ if (copy_to_user((void *)(arg + 4), &reg[1], 4))
+ return -EFAULT;
+ return 0;
+ case FBIMSTT_SETIDXREG:
+ if (copy_from_user(init, (void *)arg, 2))
+ return -EFAULT;
+ p->cmap_regs[PIDXHI] = 0; eieio();
+ p->cmap_regs[PIDXLO] = init[0]; eieio();
+ p->cmap_regs[PIDXDATA] = init[1]; eieio();
+ return 0;
+ case FBIMSTT_GETIDXREG:
+ if (copy_from_user(init, (void *)arg, 1))
+ return -EFAULT;
+ p->cmap_regs[PIDXHI] = 0; eieio();
+ p->cmap_regs[PIDXLO] = init[0]; eieio();
+ init[1] = p->cmap_regs[PIDXDATA];
+ if (copy_to_user((void *)(arg + 1), &init[1], 1))
+ return -EFAULT;
+ return 0;
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static struct fb_ops imsttfb_ops = {
+ imsttfb_open,
+ imsttfb_release,
+ imsttfb_get_fix,
+ imsttfb_get_var,
+ imsttfb_set_var,
+ imsttfb_get_cmap,
+ imsttfb_set_cmap,
+ imsttfb_pan_display,
+ imsttfb_ioctl
+};
+
+static int
+imsttfbcon_switch (int con, struct fb_info *info)
+{
+ struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+ struct display *old = &fb_display[currcon], *new = &fb_display[con];
+ __u32 off;
+
+ if (old->cmap.len)
+ fb_get_cmap(&old->cmap, 1, imsttfb_getcolreg, info);
+
+ if (p->ramdac == IBM)
+ imsttfb_cursor(old, CM_ERASE, p->cursor.x, p->cursor.y);
+
+ currcon = con;
+
+ if (old->var.xres != new->var.xres
+ || old->var.yres != new->var.yres
+ || old->var.bits_per_pixel != new->var.bits_per_pixel
+ || old->var.green.length != new->var.green.length) {
+ set_disp(new, p);
+ if (!compute_imstt_regvals(p, new->var.xres, new->var.yres))
+ return -1;
+ if (new->var.bits_per_pixel == 16) {
+ if (new->var.green.length == 6)
+ set_565(p);
+ else
+ set_555(p);
+ }
+ set_imstt_regvals(p, new->var.bits_per_pixel);
+ }
+ if (old->var.yoffset != new->var.yoffset || old->var.xoffset != new->var.xoffset) {
+ off = new->var.yoffset * (new->line_length >> 3)
+ + ((new->var.xoffset * (new->var.bits_per_pixel >> 3)) >> 3);
+ out_le32(&p->dc_regs[SSR], off);
+ }
+
+ do_install_cmap(con, info);
+
+ return 0;
+}
+
+static inline void
+imsttfb_rectfill (struct display *disp, u_int sy, u_int sx, u_int height, u_int width, __u32 bgx)
+{
+ memset(disp->screen_base + sy + sx, bgx, height * width * (disp->var.bits_per_pixel >> 3));
+}
+
+static int
+imsttfbcon_updatevar (int con, struct fb_info *info)
+{
+ struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+ struct display *disp = &fb_display[con];
+ struct vc_data *conp = disp->conp;
+ __u32 off, yres, yoffset, sy, height;
+
+ if (con != currcon)
+ goto out;
+
+ yres = disp->var.yres;
+ yoffset = disp->var.yoffset;
+ sy = (conp->vc_rows + disp->yscroll) * fontheight(disp);
+ height = yres - conp->vc_rows * fontheight(disp);
+
+ if (height && (yoffset + yres > sy)) {
+ __u32 bgx = attr_bgcol_ec(disp, conp);
+
+ if (sy + height > disp->var.yres_virtual)
+ printk("updatevar: %u + %u > %u\n", sy, height, disp->var.yres_virtual);
+ imsttfb_rectfill(disp, sy, disp->var.xoffset, height, disp->var.xres, bgx);
+ }
+
+ if (p->ramdac == IBM && (yoffset + yres <= sy))
+ imsttfb_cursor(disp, CM_ERASE, p->cursor.x, p->cursor.y);
+
+ off = disp->var.yoffset * (disp->line_length >> 3)
+ + ((disp->var.xoffset * (disp->var.bits_per_pixel >> 3)) >> 3);
+ out_le32(&p->dc_regs[SSR], off);
+
+out:
+ return 0;
+}
+
+static void
+imsttfbcon_blank (int blank, struct fb_info *info)
+{
+ struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+ __u32 ctrl;
+
+ ctrl = in_le32(&p->dc_regs[STGCTL]);
+ if (blank > 0) {
+ switch (blank - 1) {
+ case VESA_NO_BLANKING:
+ case VESA_POWERDOWN:
+ ctrl &= ~0x00000380;
+ if (p->ramdac == IBM) {
+ p->cmap_regs[PIDXHI] = 0; eieio();
+ p->cmap_regs[PIDXLO] = MISCTL2; eieio();
+ p->cmap_regs[PIDXDATA] = 0x55; eieio();
+ p->cmap_regs[PIDXLO] = MISCTL1; eieio();
+ p->cmap_regs[PIDXDATA] = 0x11; eieio();
+ p->cmap_regs[PIDXLO] = SYNCCTL; eieio();
+ p->cmap_regs[PIDXDATA] = 0x0f; eieio();
+ p->cmap_regs[PIDXLO] = PWRMNGMT;eieio();
+ p->cmap_regs[PIDXDATA] = 0x1f; eieio();
+ p->cmap_regs[PIDXLO] = CLKCTL; eieio();
+ p->cmap_regs[PIDXDATA] = 0xc0;
+ }
+ break;
+ case VESA_VSYNC_SUSPEND:
+ ctrl &= ~0x00000020;
+ break;
+ case VESA_HSYNC_SUSPEND:
+ ctrl &= ~0x00000010;
+ break;
+ }
+ } else {
+ if (p->ramdac == IBM) {
+ ctrl |= 0x000017b0;
+ p->cmap_regs[PIDXHI] = 0; eieio();
+ p->cmap_regs[PIDXLO] = CLKCTL; eieio();
+ p->cmap_regs[PIDXDATA] = 0x01; eieio();
+ p->cmap_regs[PIDXLO] = PWRMNGMT;eieio();
+ p->cmap_regs[PIDXDATA] = 0x00; eieio();
+ p->cmap_regs[PIDXLO] = SYNCCTL; eieio();
+ p->cmap_regs[PIDXDATA] = 0x00; eieio();
+ p->cmap_regs[PIDXLO] = MISCTL1; eieio();
+ p->cmap_regs[PIDXDATA] = 0x01; eieio();
+ p->cmap_regs[PIDXLO] = MISCTL2; eieio();
+ p->cmap_regs[PIDXDATA] = 0x45; eieio();
+ } else
+ ctrl |= 0x00001780;
+ }
+ out_le32(&p->dc_regs[STGCTL], ctrl);
+}
+
+__initfunc(static void
+init_imstt(struct fb_info_imstt *p))
+{
+ __u32 i, tmp;
+ __u32 *ip, *end;
+
+ tmp = in_le32(&p->dc_regs[PRC]);
+ if (p->ramdac == IBM)
+ p->total_vram = (tmp & 0x0004) ? 0x00400000 : 0x00200000;
+ else
+ p->total_vram = 0x00800000;
+
+ ip = (__u32 *)p->frame_buffer;
+ end = (__u32 *)(p->frame_buffer + p->total_vram);
+ while (ip < end)
+ *ip++ = 0;
+
+ /* initialize the card */
+ tmp = in_le32(&p->dc_regs[STGCTL]);
+ out_le32(&p->dc_regs[STGCTL], tmp & ~0x1);
+ out_le32(&p->dc_regs[SSR], 0);
+
+ /* set default values for DAC registers */
+ if (p->ramdac == IBM) {
+ p->cmap_regs[PPMASK] = 0xff; eieio();
+ p->cmap_regs[PIDXHI] = 0; eieio();
+ for (i = 0; i < sizeof(ibm_initregs) / sizeof(*ibm_initregs); i++) {
+ p->cmap_regs[PIDXLO] = ibm_initregs[i].addr; eieio();
+ p->cmap_regs[PIDXDATA] = ibm_initregs[i].value; eieio();
+ }
+ } else {
+ for (i = 0; i < sizeof(tvp_initregs) / sizeof(*tvp_initregs); i++) {
+ p->cmap_regs[TVPADDRW] = tvp_initregs[i].addr; eieio();
+ p->cmap_regs[TVPIDATA] = tvp_initregs[i].value; eieio();
+ }
+ }
+
+#if USE_NV_MODES && defined(CONFIG_PPC)
+ {
+ int vmode = init_vmode, cmode = init_cmode;
+
+ if (vmode == -1) {
+ vmode = nvram_read_byte(NV_VMODE);
+ if (vmode <= 0 || vmode > VMODE_MAX)
+ vmode = VMODE_640_480_67;
+ }
+ if (cmode == -1) {
+ cmode = nvram_read_byte(NV_CMODE);
+ if (cmode < CMODE_8 || cmode > CMODE_32)
+ cmode = CMODE_8;
+ }
+ if (mac_vmode_to_var(vmode, cmode, &p->disp.var)) {
+ p->disp.var.xres = p->disp.var.xres_virtual = INIT_XRES;
+ p->disp.var.yres = p->disp.var.yres_virtual = INIT_YRES;
+ p->disp.var.bits_per_pixel = INIT_BPP;
+ }
+ }
+#else
+ p->disp.var.xres = p->disp.var.xres_virtual = INIT_XRES;
+ p->disp.var.yres = p->disp.var.yres_virtual = INIT_YRES;
+ p->disp.var.bits_per_pixel = INIT_BPP;
+#endif
+
+ if ((p->disp.var.xres * p->disp.var.yres) * (p->disp.var.bits_per_pixel >> 3) > p->total_vram
+ || !(compute_imstt_regvals(p, p->disp.var.xres, p->disp.var.yres))) {
+ printk("imsttfb: %ux%ux%u not supported\n", p->disp.var.xres, p->disp.var.yres, p->disp.var.bits_per_pixel);
+ kfree(p);
+ return;
+ }
+
+ sprintf(p->fix.id, "IMS TT (%s)", p->ramdac == IBM ? "IBM" : "TVP");
+ p->fix.smem_start = (__u8 *)p->frame_buffer_phys;
+ p->fix.smem_len = p->total_vram;
+ p->fix.mmio_start = (__u8 *)p->dc_regs_phys;
+ p->fix.mmio_len = 0x40000;
+ p->fix.accel = FB_ACCEL_IMS_TWINTURBO;
+ p->fix.type = FB_TYPE_PACKED_PIXELS;
+ p->fix.visual = p->disp.var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
+ : FB_VISUAL_DIRECTCOLOR;
+ p->fix.line_length = p->disp.var.xres * (p->disp.var.bits_per_pixel >> 3);
+ p->fix.xpanstep = 8;
+ p->fix.ypanstep = 1;
+ p->fix.ywrapstep = 0;
+
+ p->disp.var.accel_flags = noaccel ? 0 : FB_ACCELF_TEXT;
+ set_disp(&p->disp, p);
+
+ if (p->ramdac == IBM)
+ imstt_cursor_init(p);
+ if (p->disp.var.green.length == 6)
+ set_565(p);
+ else
+ set_555(p);
+ set_imstt_regvals(p, p->disp.var.bits_per_pixel);
+
+ p->disp.var.pixclock = 1000000 / getclkMHz(p);
+
+ strcpy(p->info.modename, p->fix.id);
+ strcpy(p->info.fontname, fontname);
+ p->info.node = -1;
+ p->info.fbops = &imsttfb_ops;
+ p->info.disp = &p->disp;
+ p->info.changevar = 0;
+ p->info.switch_con = &imsttfbcon_switch;
+ p->info.updatevar = &imsttfbcon_updatevar;
+ p->info.blank = &imsttfbcon_blank;
+ p->info.flags = FBINFO_FLAG_DEFAULT;
+
+ for (i = 0; i < 16; i++) {
+ u_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;
+ }
+
+ tmp = (in_le32(&p->dc_regs[SSTATUS]) & 0x0f00) >> 8;
+ printk("fb%d: %s frame buffer; %uMB vram; chip version %u\n",
+ GET_FB_IDX(p->info.node), p->fix.id, p->total_vram >> 20, tmp);
+
+#ifdef CONFIG_FB_COMPAT_XPMAC
+ strncpy(display_info.name, "IMS,tt128mb", sizeof(display_info.name));
+ display_info.fb_address = (__u32)p->frame_buffer_phys;
+ display_info.cmap_adr_address = (__u32)&p->cmap_regs_phys[PADDRW];
+ display_info.cmap_data_address = (__u32)&p->cmap_regs_phys[PDATA];
+ display_info.disp_reg_address = (__u32)p->dc_regs_phys;
+ set_display_info(&p->disp);
+ if (!console_fb_info)
+ console_fb_info = &p->info;
+#endif /* CONFIG_FB_COMPAT_XPMAC */
+}
+
+#if defined(CONFIG_FB_OF)
+__initfunc(void
+imsttfb_of_init(struct device_node *dp))
+{
+ struct fb_info_imstt *p;
+ int i;
+ __u32 addr, size = 0;
+ __u8 bus, devfn;
+ __u16 cmd;
+
+ for (i = 0; i < dp->n_addrs; i++) {
+ if (dp->addrs[i].size >= 0x02000000) {
+ addr = dp->addrs[i].address;
+ size = dp->addrs[i].size;
+ }
+ }
+ if (!size)
+ return;
+
+ p = kmalloc(sizeof(struct fb_info_imstt), GFP_ATOMIC);
+ if (!p)
+ return;
+
+ memset(p, 0, sizeof(struct fb_info_imstt));
+ p->frame_buffer_phys = (__u8 *)addr;
+ p->frame_buffer = (__u8 *)ioremap(addr, size);
+ p->dc_regs_phys = (__u32 *)(p->frame_buffer_phys + 0x00800000);
+ p->dc_regs = (__u32 *)(p->frame_buffer + 0x00800000);
+ p->cmap_regs_phys = (__u8 *)(p->frame_buffer_phys + 0x00840000);
+ p->cmap_regs = (__u8 *)(p->frame_buffer + 0x00840000);
+
+ if (dp->name[11] == '8')
+ p->ramdac = TVP;
+ else
+ p->ramdac = IBM;
+
+ if (!pci_device_loc(dp, &bus, &devfn)) {
+ if (!pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd)) {
+ cmd |= PCI_COMMAND_MEMORY;
+ pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
+ }
+ }
+
+ init_imstt(p);
+}
+#endif
+
+__initfunc(void
+imsttfb_init(void))
+{
+#if !defined(CONFIG_FB_OF)
+ /* ... */
+#endif
+}
+
+__initfunc(void
+imsttfb_setup(char *options, int *ints))
+{
+ char *this_opt;
+
+ 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;
+ } else if (!strncmp(this_opt, "noblink", 7)) {
+ curblink = 0;
+ } else if (!strncmp(this_opt, "noaccel", 7)) {
+ noaccel = 1;
+ }
+#if defined(CONFIG_PPC)
+ else if (!strncmp(this_opt, "vmode:", 6)) {
+ int vmode = simple_strtoul(this_opt+6, NULL, 0);
+ if (vmode > 0 && vmode <= VMODE_MAX)
+ init_vmode = vmode;
+ } else if (!strncmp(this_opt, "cmode:", 6)) {
+ int cmode = simple_strtoul(this_opt+6, NULL, 0);
+ switch (cmode) {
+ case CMODE_8:
+ case 8:
+ init_cmode = CMODE_8;
+ break;
+ case CMODE_16:
+ case 15:
+ case 16:
+ init_cmode = CMODE_16;
+ break;
+ case CMODE_32:
+ case 24:
+ case 32:
+ init_cmode = CMODE_32;
+ break;
+ }
+ }
+#endif
+ }
+}
diff --git a/drivers/video/leofb.c b/drivers/video/leofb.c
new file mode 100644
index 000000000..6bfd09fd8
--- /dev/null
+++ b/drivers/video/leofb.c
@@ -0,0 +1,582 @@
+/* $Id: leofb.c,v 1.4 1998/09/04 15:43:45 jj Exp $
+ * leofb.c: Leo (ZX) 24/8bit frame buffer driver
+ *
+ * Copyright (C) 1996,1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
+ */
+
+#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 <video/sbusfb.h>
+#include <asm/io.h>
+
+#define LEO_OFF_LC_SS0_KRN 0x00200000
+#define LEO_OFF_LC_SS0_USR 0x00201000
+#define LEO_OFF_LC_SS1_KRN 0x01200000
+#define LEO_OFF_LC_SS1_USR 0x01201000
+#define LEO_OFF_LD_SS0 0x00400000
+#define LEO_OFF_LD_SS1 0x01400000
+#define LEO_OFF_LD_GBL 0x00401000
+#define LEO_OFF_LX_KRN 0x00600000
+#define LEO_OFF_LX_CURSOR 0x00601000
+#define LEO_OFF_SS0 0x00800000
+#define LEO_OFF_SS1 0x01800000
+#define LEO_OFF_UNK 0x00602000
+#define LEO_OFF_UNK2 0x00000000
+
+#define LEO_CUR_ENABLE 0x00000080
+#define LEO_CUR_UPDATE 0x00000030
+#define LEO_CUR_PROGRESS 0x00000006
+#define LEO_CUR_UPDATECMAP 0x00000003
+
+#define LEO_CUR_TYPE_MASK 0x00000000
+#define LEO_CUR_TYPE_IMAGE 0x00000020
+#define LEO_CUR_TYPE_CMAP 0x00000050
+
+struct leo_cursor {
+ u8 xxx0[16];
+ volatile u32 cur_type;
+ volatile u32 cur_misc;
+ volatile u32 cur_cursxy;
+ volatile u32 cur_data;
+};
+
+#define LEO_KRN_TYPE_CLUT0 0x00001000
+#define LEO_KRN_TYPE_CLUT1 0x00001001
+#define LEO_KRN_TYPE_CLUT2 0x00001002
+#define LEO_KRN_TYPE_WID 0x00001003
+#define LEO_KRN_TYPE_UNK 0x00001006
+#define LEO_KRN_TYPE_VIDEO 0x00002003
+#define LEO_KRN_TYPE_CLUTDATA 0x00004000
+#define LEO_KRN_CSR_ENABLE 0x00000008
+#define LEO_KRN_CSR_PROGRESS 0x00000004
+#define LEO_KRN_CSR_UNK 0x00000002
+#define LEO_KRN_CSR_UNK2 0x00000001
+
+struct leo_lx_krn {
+ volatile u32 krn_type;
+ volatile u32 krn_csr;
+ volatile u32 krn_value;
+};
+
+struct leo_lc_ss0_krn {
+ volatile u32 misc;
+ u8 xxx0[0x800-4];
+ volatile u32 rev;
+};
+
+struct leo_lc_ss0_usr {
+ volatile u32 csr;
+ volatile u32 attrs;
+ volatile u32 fontc;
+ volatile u32 fontc2;
+ volatile u32 extent;
+ volatile u32 src;
+ u32 xxx1[1];
+ volatile u32 copy;
+ volatile u32 fill;
+};
+
+struct leo_lc_ss1_krn {
+ u8 unknown;
+};
+
+struct leo_lc_ss1_usr {
+ u8 unknown;
+};
+
+struct leo_ld_ss0 {
+ u8 xxx0[0xe00];
+ u32 xxx1[2];
+ volatile u32 unk;
+ u32 xxx2[1];
+ volatile u32 unk2;
+ volatile u32 unk3;
+ u32 xxx3[2];
+ volatile u32 fg;
+ volatile u32 bg;
+ u8 xxx4[0x05c];
+ volatile u32 planemask;
+ volatile u32 rop;
+};
+
+#define LEO_SS1_MISC_ENABLE 0x00000001
+#define LEO_SS1_MISC_STEREO 0x00000002
+struct leo_ld_ss1 {
+ u8 xxx0[0xef4];
+ volatile u32 ss1_misc;
+};
+
+struct leo_ld_gbl {
+ u8 unknown;
+};
+
+static struct sbus_mmap_map leo_mmap_map[] = {
+ { LEO_SS0_MAP, LEO_OFF_SS0, 0x800000 },
+ { LEO_LC_SS0_USR_MAP, LEO_OFF_LC_SS0_USR, PAGE_SIZE },
+ { LEO_LD_SS0_MAP, LEO_OFF_LD_SS0, PAGE_SIZE },
+ { LEO_LX_CURSOR_MAP, LEO_OFF_LX_CURSOR, PAGE_SIZE },
+ { LEO_SS1_MAP, LEO_OFF_SS1, 0x800000 },
+ { LEO_LC_SS1_USR_MAP, LEO_OFF_LC_SS1_USR, PAGE_SIZE },
+ { LEO_LD_SS1_MAP, LEO_OFF_LD_SS1, PAGE_SIZE },
+ { LEO_UNK_MAP, LEO_OFF_UNK, PAGE_SIZE },
+ { LEO_LX_KRN_MAP, LEO_OFF_LX_KRN, PAGE_SIZE },
+ { LEO_LC_SS0_KRN_MAP, LEO_OFF_LC_SS0_KRN, PAGE_SIZE },
+ { LEO_LC_SS1_KRN_MAP, LEO_OFF_LC_SS1_KRN, PAGE_SIZE },
+ { LEO_LD_GBL_MAP, LEO_OFF_LD_GBL, PAGE_SIZE },
+ { LEO_UNK2_MAP, LEO_OFF_UNK2, 0x100000 },
+ { 0, 0, 0 }
+};
+
+static void leo_setup(struct display *p)
+{
+ p->next_line = 8192;
+ p->next_plane = 0;
+}
+
+static void leo_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 leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
+ register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0;
+ int x, y, w, h;
+ int i;
+
+ do {
+ i = us->csr;
+ } while (i & 0x20000000);
+ ss->unk = 0xffff;
+ ss->unk2 = 0;
+ ss->unk3 = fb->s.leo.extent;
+ ss->fg = (attr_bgcol_ec(p,conp)<<24) | 0x030703;
+ ss->planemask = 0xff000000;
+ ss->rop = 0xd0840;
+ if (fontheightlog(p)) {
+ y = sy << fontheightlog(p); h = height << fontheightlog(p);
+ } else {
+ y = sy * fontheight(p); h = height * fontheight(p);
+ }
+ if (fontwidthlog(p)) {
+ x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
+ } else {
+ x = sx * fontwidth(p); w = width * fontwidth(p);
+ }
+ us->extent = (w - 1) | ((h - 1) << 11);
+ i = us->attrs;
+ us->fill = (x + fb->x_margin) | ((y + fb->y_margin) << 11) |
+ ((i & 3) << 29) | ((i & 8) ? 0x80000000 : 0);
+}
+
+static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
+ int count, unsigned short *boxes)
+{
+ int i;
+ register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
+ register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0;
+
+ do {
+ i = us->csr;
+ } while (i & 0x20000000);
+ ss->unk = 0xffff;
+ ss->unk2 = 0;
+ ss->unk3 = fb->s.leo.extent;
+ ss->fg = (attr_bgcol(p,s)<<24) | 0x030703;
+ ss->planemask = 0xff000000;
+ ss->rop = 0xd0840;
+ while (count-- > 0) {
+ us->extent = (boxes[2] - boxes[0] - 1) |
+ ((boxes[3] - boxes[1] - 1) << 11);
+ i = us->attrs;
+ us->fill = boxes[0] | (boxes[1] << 11) |
+ ((i & 3) << 29) | ((i & 8) ? 0x80000000 : 0);
+ }
+}
+
+static void leo_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 leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
+ register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0;
+ int i, x, y;
+ u8 *fd;
+ u32 *u;
+
+ if (fontheightlog(p)) {
+ y = yy << (fontheightlog(p) + 11);
+ i = (c & p->charmask) << fontheightlog(p);
+ } else {
+ y = (yy * fontheight(p)) << 11;
+ i = (c & p->charmask) * fontheight(p);
+ }
+ if (fontwidth(p) <= 8)
+ fd = p->fontdata + i;
+ else
+ fd = p->fontdata + (i << 1);
+ if (fontwidthlog(p))
+ x = xx << fontwidthlog(p);
+ else
+ x = xx * fontwidth(p);
+ do {
+ i = us->csr;
+ } while (i & 0x20000000);
+ ss->fg = attr_fgcol(p,c) << 24;
+ ss->bg = attr_bgcol(p,c) << 24;
+ ss->rop = 0x310040;
+ ss->planemask = 0xff000000;
+ us->fontc2 = 0xFFFFFFFE;
+ us->attrs = 4;
+ us->fontc = 0xFFFFFFFF<<(32-fontwidth(p));
+ u = ((u32 *)p->screen_base) + y + x;
+ if (fontwidth(p) <= 8) {
+ for (i = 0; i < fontheight(p); i++, u += 2048)
+ *u = *fd++ << 24;
+ } else {
+ for (i = 0; i < fontheight(p); i++, u += 2048) {
+ *u = *(u16 *)fd << 16;
+ fd += 2;
+ }
+ }
+}
+
+static void leo_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 leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
+ register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0;
+ int i, x, y;
+ u8 *fd1, *fd2, *fd3, *fd4;
+ u32 *u;
+
+ do {
+ i = us->csr;
+ } while (i & 0x20000000);
+ ss->fg = attr_fgcol(p,*s) << 24;
+ ss->bg = attr_bgcol(p,*s) << 24;
+ ss->rop = 0x310040;
+ ss->planemask = 0xff000000;
+ us->fontc2 = 0xFFFFFFFE;
+ us->attrs = 4;
+ us->fontc = 0xFFFFFFFF<<(32-fontwidth(p));
+ if (fontwidthlog(p))
+ x = (xx << fontwidthlog(p));
+ else
+ x = xx * fontwidth(p);
+ if (fontheightlog(p))
+ y = yy << (fontheightlog(p) + 11);
+ else
+ y = (yy * fontheight(p)) << 11;
+ u = ((u32 *)p->screen_base) + y + x;
+ if (fontwidth(p) <= 8) {
+ us->fontc = 0xFFFFFFFF<<(32-4*fontwidth(p));
+ x = 4*fontwidth(p) - fontheight(p)*2048;
+ while (count >= 4) {
+ count -= 4;
+ if (fontheightlog(p)) {
+ fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+ fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+ fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+ fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+ } else {
+ fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+ fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+ fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+ fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+ }
+ if (fontwidth(p) == 8) {
+ for (i = 0; i < fontheight(p); i++, u += 2048)
+ *u = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
+ << 8)) << 8)) << 8);
+ u += x;
+ } else {
+ for (i = 0; i < fontheight(p); i++, u += 2048)
+ *u = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
+ << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
+ u += x;
+ }
+ }
+ } else {
+ us->fontc = 0xFFFFFFFF<<(32-2*fontwidth(p));
+ x = 2*fontwidth(p) - fontheight(p)*2048;
+ while (count >= 2) {
+ count -= 2;
+ if (fontheightlog(p)) {
+ fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
+ fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
+ } else {
+ fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
+ fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
+ }
+ for (i = 0; i < fontheight(p); i++, u += 2048) {
+ *u = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
+ fd1 += 2; fd2 += 2;
+ }
+ u += x;
+ }
+ }
+ us->fontc = 0xFFFFFFFF<<(32-fontwidth(p));
+ x = fontwidth(p) - fontheight(p)*2048;
+ while (count) {
+ count--;
+ if (fontheightlog(p))
+ i = ((*s++ & p->charmask) << fontheightlog(p));
+ else
+ i = ((*s++ & p->charmask) * fontheight(p));
+ if (fontwidth(p) <= 8) {
+ fd1 = p->fontdata + i;
+ for (i = 0; i < fontheight(p); i++, u += 2048)
+ *u = *fd1++ << 24;
+ } else {
+ fd1 = p->fontdata + (i << 1);
+ for (i = 0; i < fontheight(p); i++, u += 2048) {
+ *u = *(u16 *)fd1 << 16;
+ fd1 += 2;
+ }
+ }
+ u += x;
+ }
+}
+
+static void leo_revc(struct display *p, int xx, int yy)
+{
+ /* Not used if hw cursor */
+}
+
+static int leo_wait (struct leo_lx_krn *lx_krn)
+{
+ int i;
+
+ for (i = 0; (lx_krn->krn_csr & LEO_KRN_CSR_PROGRESS) && i < 300000; i++)
+ udelay (1); /* Busy wait at most 0.3 sec */
+ if (i == 300000) return -EFAULT; /* Timed out - should we print some message? */
+ return 0;
+}
+
+static void leo_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
+{
+ struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
+ int i;
+
+ lx_krn->krn_type = LEO_KRN_TYPE_CLUT0;
+ i = leo_wait (lx_krn);
+ if (i) return;
+ lx_krn->krn_type = LEO_KRN_TYPE_CLUTDATA;
+ for (i = 0; i < 256; i++)
+ lx_krn->krn_value = fb->color_map CM(i,0) |
+ (fb->color_map CM(i,1) << 8) |
+ (fb->color_map CM(i,2) << 16); /* Throw colors there :)) */
+ lx_krn->krn_type = LEO_KRN_TYPE_CLUT0;
+ lx_krn->krn_csr |= (LEO_KRN_CSR_UNK|LEO_KRN_CSR_UNK2);
+}
+
+static void leo_restore_palette (struct fb_info_sbusfb *fb)
+{
+ fb->s.leo.ld_ss1->ss1_misc &= ~(LEO_SS1_MISC_ENABLE);
+}
+
+static struct display_switch leo_dispsw __initdata = {
+ leo_setup, fbcon_redraw_bmove, leo_clear, leo_putc, leo_putcs, leo_revc,
+ NULL, NULL, NULL, FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
+};
+
+static void leo_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
+{
+ struct leo_cursor *l = fb->s.leo.cursor;
+ int i;
+
+ for (i = 0; (l->cur_misc & LEO_CUR_PROGRESS) && i < 300000; i++)
+ udelay (1); /* Busy wait at most 0.3 sec */
+ if (i == 300000) return; /* Timed out - should we print some message? */
+ l->cur_type = LEO_CUR_TYPE_CMAP;
+ l->cur_data = (red[0] | (green[0]<<8) | (blue[0]<<16));
+ l->cur_data = (red[1] | (green[1]<<8) | (blue[1]<<16));
+ l->cur_misc = LEO_CUR_UPDATECMAP;
+}
+
+/* Set cursor shape */
+static void leo_setcurshape (struct fb_info_sbusfb *fb)
+{
+ int i, j, k;
+ u32 m, n, mask;
+ struct leo_cursor *l = fb->s.leo.cursor;
+
+ l->cur_misc &= ~LEO_CUR_ENABLE;
+ for (k = 0; k < 2; k ++) {
+ l->cur_type = (k * LEO_CUR_TYPE_IMAGE); /* LEO_CUR_TYPE_MASK is 0 */
+ for (i = 0; i < 32; i++) {
+ mask = 0;
+ m = fb->cursor.bits[k][i];
+ /* mask = m with reversed bit order */
+ for (j = 0, n = 1; j < 32; j++, n <<= 1)
+ if (m & n)
+ mask |= (0x80000000 >> j);
+ l->cur_data = mask;
+ }
+ }
+ l->cur_misc |= LEO_CUR_ENABLE;
+}
+
+/* Load cursor information */
+static void leo_setcursor (struct fb_info_sbusfb *fb)
+{
+ struct cg_cursor *c = &fb->cursor;
+ struct leo_cursor *l = fb->s.leo.cursor;
+
+ l->cur_misc &= ~LEO_CUR_ENABLE;
+ l->cur_cursxy = ((c->cpos.fbx - c->chot.fbx) & 0x7ff)
+ |(((c->cpos.fby - c->chot.fby) & 0x7ff) << 11);
+ l->cur_misc |= LEO_CUR_UPDATE;
+ if (c->enable)
+ l->cur_misc |= LEO_CUR_ENABLE;
+}
+
+static void leo_blank (struct fb_info_sbusfb *fb)
+{
+ fb->s.leo.lx_krn->krn_type = LEO_KRN_TYPE_VIDEO;
+ fb->s.leo.lx_krn->krn_csr &= ~LEO_KRN_CSR_ENABLE;
+}
+
+static void leo_unblank (struct fb_info_sbusfb *fb)
+{
+ fb->s.leo.lx_krn->krn_type = LEO_KRN_TYPE_VIDEO;
+ if (!(fb->s.leo.lx_krn->krn_csr & LEO_KRN_CSR_ENABLE))
+ fb->s.leo.lx_krn->krn_csr |= LEO_KRN_CSR_ENABLE;
+}
+
+__initfunc(static int
+leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl))
+{
+ struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
+ struct fb_wid_item *wi;
+ int i, j;
+
+ lx_krn->krn_type = LEO_KRN_TYPE_WID;
+ i = leo_wait (lx_krn);
+ if (i) return i;
+ for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) {
+ switch (wi->wi_type) {
+ case FB_WID_DBL_8: j = (wi->wi_index & 0xf) + 0x40; break;
+ case FB_WID_DBL_24: j = wi->wi_index & 0x3f; break;
+ default: return -EINVAL;
+ }
+ lx_krn->krn_type = 0x5800 + j;
+ lx_krn->krn_value = wi->wi_values[0];
+ }
+ return 0;
+}
+
+static void leo_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
+{
+ p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
+}
+
+static char idstring[40] __initdata = { 0 };
+
+__initfunc(char *leofb_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;
+ struct fb_wid_item wi;
+ struct fb_wid_list wl;
+ int i;
+
+ strcpy(fb->info.modename, "Leo");
+
+ strcpy(fix->id, "Leo");
+ fix->visual = 0xff; /* We only know how to do acceleration and know nothing
+ about the actual memory layout */
+ fix->line_length = 8192;
+ fix->accel = FB_ACCEL_SUN_LEO;
+
+ var->accel_flags = FB_ACCELF_TEXT;
+
+ disp->scrollmode = SCROLL_YREDRAW;
+ if (!disp->screen_base)
+ disp->screen_base = (char *)sparc_alloc_io(phys + LEO_OFF_SS0, 0,
+ 0x800000, "leo_ram", fb->iospace, 0);
+ disp->screen_base += 8192 * fb->y_margin + 4 * fb->x_margin;
+ fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *)
+ sparc_alloc_io(phys + LEO_OFF_LC_SS0_USR, 0,
+ PAGE_SIZE, "leo_lc_ss0_usr", fb->iospace, 0);
+ fb->s.leo.ld_ss0 = (struct leo_ld_ss0 *)
+ sparc_alloc_io(phys + LEO_OFF_LD_SS0, 0,
+ PAGE_SIZE, "leo_ld_ss0", fb->iospace, 0);
+ fb->s.leo.ld_ss1 = (struct leo_ld_ss1 *)
+ sparc_alloc_io(phys + LEO_OFF_LD_SS1, 0,
+ PAGE_SIZE, "leo_ld_ss1", fb->iospace, 0);
+ fb->s.leo.lx_krn = (struct leo_lx_krn *)
+ sparc_alloc_io(phys + LEO_OFF_LX_KRN, 0,
+ PAGE_SIZE, "leo_lx_krn", fb->iospace, 0);
+ fb->s.leo.cursor = (struct leo_cursor *)
+ sparc_alloc_io(phys + LEO_OFF_LX_CURSOR, 0,
+ sizeof(struct leo_cursor), "leo_lx_cursor", fb->iospace, 0);
+ fb->dispsw = leo_dispsw;
+
+ fb->s.leo.extent = (type->fb_width-1) | ((type->fb_height-1) << 16);
+
+ fb->s.leo.ld_ss0->unk = 0xffff;
+ fb->s.leo.ld_ss0->unk2 = 0;
+ fb->s.leo.ld_ss0->unk3 = fb->s.leo.extent;
+ wl.wl_count = 1;
+ wl.wl_list = &wi;
+ wi.wi_type = FB_WID_DBL_8;
+ wi.wi_index = 0;
+ wi.wi_values [0] = 0x2c0;
+ leo_wid_put (fb, &wl);
+ wi.wi_index = 1;
+ wi.wi_values [0] = 0x30;
+ leo_wid_put (fb, &wl);
+ wi.wi_index = 2;
+ wi.wi_values [0] = 0x20;
+ leo_wid_put (fb, &wl);
+
+ fb->s.leo.ld_ss1->ss1_misc |= LEO_SS1_MISC_ENABLE;
+
+ fb->s.leo.ld_ss0->fg = 0x30703;
+ fb->s.leo.ld_ss0->planemask = 0xff000000;
+ fb->s.leo.ld_ss0->rop = 0xd0840;
+ fb->s.leo.lc_ss0_usr->extent = (type->fb_width-1) | ((type->fb_height-1) << 11);
+ i = fb->s.leo.lc_ss0_usr->attrs;
+ fb->s.leo.lc_ss0_usr->fill = (0) | ((0) << 11) | ((i & 3) << 29) | ((i & 8) ? 0x80000000 : 0);
+ do {
+ i = fb->s.leo.lc_ss0_usr->csr;
+ } while (i & 0x20000000);
+
+ fb->margins = leo_margins;
+ fb->loadcmap = leo_loadcmap;
+ fb->setcursor = leo_setcursor;
+ fb->setcursormap = leo_setcursormap;
+ fb->setcurshape = leo_setcurshape;
+ fb->restore_palette = leo_restore_palette;
+ fb->fill = leo_fill;
+ fb->blank = leo_blank;
+ fb->unblank = leo_unblank;
+
+ fb->physbase = phys;
+ fb->mmap_map = leo_mmap_map;
+
+#ifdef __sparc_v9__
+ sprintf(idstring, "leo at %016lx", phys);
+#else
+ sprintf(idstring, "leo at %x.%08lx", fb->iospace, phys);
+#endif
+
+ return idstring;
+}
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index 67d6e87b1..2d0ad2924 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -22,12 +22,11 @@
#include <asm/macintosh.h>
#include <linux/fb.h>
-
/* conditionalize these ?? */
-#include "fbcon-mfb.h"
-#include "fbcon-cfb2.h"
-#include "fbcon-cfb4.h"
-#include "fbcon-cfb8.h"
+#include <video/fbcon-mfb.h>
+#include <video/fbcon-cfb2.h>
+#include <video/fbcon-cfb4.h>
+#include <video/fbcon-cfb8.h>
#define arraysize(x) (sizeof(x)/sizeof(*(x)))
@@ -237,7 +236,7 @@ static void macfb_set_disp(int con)
break;
#endif
default:
- display->dispsw = NULL;
+ display->dispsw = &fbcon_dummy;
break;
}
}
@@ -261,7 +260,7 @@ static int macfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
if (console_loglevel < 7)
return -EINVAL;
if (con == currcon) /* current console? */
- return fb_get_cmap(cmap, &fb_display[con].var, kspc, 0 /*offb_getcolreg*/, info);
+ return fb_get_cmap(cmap, kspc, 0 /*offb_getcolreg*/, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
@@ -285,7 +284,7 @@ static int macfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return err;
}
if (con == currcon) /* current console? */
- return fb_set_cmap(cmap, &fb_display[con].var, kspc, 1 /*offb_setcolreg*/, info);
+ return fb_set_cmap(cmap, kspc, 1 /*offb_setcolreg*/, info);
else
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
#endif
@@ -415,6 +414,7 @@ __initfunc(void macfb_init(void))
fb_info.switch_con=&macfb_switch;
fb_info.updatevar=&fb_update_var;
fb_info.blank=&macfb_blank;
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
do_fb_set_var(&macfb_defined,1);
macfb_get_var(&disp.var, -1, &fb_info);
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
index 57cf4877a..0fbe917d3 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/macmodes.c
@@ -12,7 +12,7 @@
#include <linux/fb.h>
#include <linux/string.h>
-#include "macmodes.h"
+#include <video/macmodes.h>
struct mac_mode {
int number;
@@ -348,7 +348,7 @@ int mac_vmode_to_var(int vmode, int cmode, struct fb_var_screeninfo *var)
int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
int *cmode)
{
- int i = 0;
+ unsigned int i;
if (var->bits_per_pixel <= 8)
*cmode = CMODE_8;
@@ -367,7 +367,7 @@ int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
continue;
if (var->pixclock > mode->pixclock)
continue;
- if (var->vmode != mode->vmode)
+ if ((var->vmode & FB_VMODE_MASK) != mode->vmode)
continue;
*vmode = mode->number;
return 0;
diff --git a/drivers/video/macmodes.h b/drivers/video/macmodes.h
deleted file mode 100644
index e0e90c738..000000000
--- a/drivers/video/macmodes.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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/matroxfb.c b/drivers/video/matroxfb.c
new file mode 100644
index 000000000..e9f3f44a3
--- /dev/null
+++ b/drivers/video/matroxfb.c
@@ -0,0 +1,5381 @@
+/*
+ *
+ * Hardware accelerated Matrox Millennium I, II, Mystique and G200
+ *
+ * (c) 1998 Petr Vandrovec <vandrove@vc.cvut.cz>
+ *
+ * Version: 1.5 1998/11/19
+ *
+ * MTRR stuff: 1998 Tom Rini <tmrini@ntplx.net>
+ *
+ * Contributors: "menion?" <menion@mindless.com>
+ * Betatesting, fixes, ideas
+ *
+ * "Kurt Garloff" <garloff@kg1.ping.de>
+ * Betatesting, fixes, ideas, videomodes, videomodes timmings
+ *
+ * "Tom Rini" <tmrini@ntplx.net>
+ * MTRR stuff, betatesting, fixes, ideas
+ *
+ * "Bibek Sahu" <scorpio@dodds.net>
+ * Access device through readb|w|l and write b|w|l
+ * Extensive debugging stuff
+ *
+ * "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
+ * Betatesting
+ *
+ * "Kelly French" <targon@hazmat.com>
+ * Betatesting, bug reporting
+ *
+ * "Pablo Bianucci" <pbian@pccp.com.ar>
+ * Fixes, ideas, betatesting
+ *
+ * "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
+ * Fixes, enhandcements, ideas, betatesting
+ *
+ * "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
+ * PPC betatesting, PPC support, backward compatibility
+ *
+ * "Paul Womar" <Paul@pwomar.demon.co.uk>
+ * "Owen Waller" <O.Waller@ee.qub.ac.uk>
+ * PPC betatesting
+ *
+ * "H. Peter Arvin" <hpa@transmeta.com>
+ * Ideas
+ *
+ * (following author is not in any relation with this code, but his code
+ * is included in this driver)
+ *
+ * Based on framebuffer driver for VBE 2.0 compliant graphic boards
+ * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
+ *
+ * (following author is not in any relation with this code, but his ideas
+ * were used when writting this driver)
+ *
+ * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
+ *
+ */
+
+/* general, but fairly heavy, debugging */
+#undef MATROXFB_DEBUG
+
+/* heavy debugging: */
+/* -- logs putc[s], so everytime a char is displayed, it's logged */
+#undef MATROXFB_DEBUG_HEAVY
+
+/* This one _could_ cause infinite loops */
+/* It _does_ cause lots and lots of messages during idle loops */
+#undef MATROXFB_DEBUG_LOOP
+
+/* Debug register calls, too? */
+#undef MATROXFB_DEBUG_REG
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/spinlock.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb4.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+
+#if defined(CONFIG_FB_COMPAT_XPMAC)
+#include <asm/vc_ioctl.h>
+#endif
+#if defined(CONFIG_PPC)
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <video/macmodes.h>
+#endif
+
+#ifdef MATROXFB_DEBUG
+
+#define DEBUG
+#define DBG(x) printk("matroxfb: %s\n", (x));
+
+#ifdef MATROXFB_DEBUG_HEAVY
+#define DBG_HEAVY(x) DBG(x)
+#else /* MATROXFB_DEBUG_HEAVY */
+#define DBG_HEAVY(x) /* DBG_HEAVY */
+#endif /* MATROXFB_DEBUG_HEAVY */
+
+#ifdef MATROXFB_DEBUG_LOOP
+#define DBG_LOOP(x) DBG(x)
+#else /* MATROXFB_DEBUG_LOOP */
+#define DBG_LOOP(x) /* DBG_LOOP */
+#endif /* MATROXFB_DEBUG_LOOP */
+
+#ifdef MATROXFB_DEBUG_REG
+#define DBG_REG(x) DBG(x)
+#else /* MATROXFB_DEBUG_REG */
+#define DBG_REG(x) /* DBG_REG */
+#endif /* MATROXFB_DEBUG_REG */
+
+#else /* MATROXFB_DEBUG */
+
+#define DBG(x) /* DBG */
+#define DBG_HEAVY(x) /* DBG_HEAVY */
+#define DBG_REG(x) /* DBG_REG */
+#define DBG_LOOP(x) /* DBG_LOOP */
+
+#endif /* MATROXFB_DEBUG */
+
+#ifndef __i386__
+#ifndef ioremap_nocache
+#define ioremap_nocache(X,Y) ioremap(X,Y)
+#endif
+#endif
+
+#if defined(__alpha__) || defined(__m68k__)
+#define READx_WORKS
+#define MEMCPYTOIO_WORKS
+#else
+#define READx_FAILS
+/* recheck __ppc__, maybe that __ppc__ needs MEMCPYTOIO_WRITEL */
+/* I benchmarked PII/350MHz with G200... MEMCPY, MEMCPYTOIO and WRITEL are on same speed ( <2% diff) */
+/* so that means that G200 speed (or AGP speed?) is our limit... I do not have benchmark to test, how */
+/* much of PCI bandwidth is used during transfers... */
+#if defined(__i386__) || defined(__ppc__)
+#define MEMCPYTOIO_MEMCPY
+#else
+#define MEMCPYTOIO_WRITEL
+#endif
+#endif
+
+#ifdef __sparc__
+#error "Sorry, I have no idea how to do this on sparc... There is mapioaddr... With bus_type parameter..."
+#endif
+
+#ifdef __m68k__
+#define MAP_BUSTOVIRT
+#else
+#define MAP_IOREMAP
+#endif
+
+#ifdef DEBUG
+#define dprintk(X...) printk(X)
+#else
+#define dprintk(X...)
+#endif
+
+#ifndef PCI_SS_VENDOR_ID_SIEMENS_NIXDORF
+#define PCI_SS_VENDOR_ID_SIEMENS_NIXDORF 0x110A
+#endif
+#ifndef PCI_SS_VENDOR_ID_MATROX
+#define PCI_SS_VENDOR_ID_MATROX PCI_VENDOR_ID_MATROX
+#endif
+#ifndef PCI_DEVICE_ID_MATROX_G200_AGP
+#define PCI_DEVICE_ID_MATROX_G200_AGP 0x0521
+#endif
+#ifndef PCI_DEVICE_ID_MATROX_G100
+#define PCI_DEVICE_ID_MATROX_G100 0x1000
+#endif
+#ifndef PCI_DEVICE_ID_MATROX_G100_AGP
+#define PCI_DEVICE_ID_MATROX_G100_AGP 0x1001
+#endif
+
+#ifndef PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP
+#define PCI_SS_ID_MATROX_GENERIC 0xFF00
+#define PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP 0xFF01
+#define PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP 0xFF02
+#define PCI_SS_ID_MATROX_MILLENIUM_G200_AGP 0xFF03
+#define PCI_SS_ID_MATROX_MARVEL_G200_AGP 0xFF04
+#define PCI_SS_ID_MATROX_MGA_G100_PCI 0xFF05
+#define PCI_SS_ID_MATROX_MGA_G100_AGP 0x1001
+#define PCI_SS_ID_SIEMENS_MGA_G100_AGP 0x001E /* 30 */
+#define PCI_SS_ID_SIEMENS_MGA_G200_AGP 0x0032 /* 50 */
+#endif
+
+#define MX_VISUAL_TRUECOLOR FB_VISUAL_DIRECTCOLOR
+#define MX_VISUAL_DIRECTCOLOR FB_VISUAL_TRUECOLOR
+#define MX_VISUAL_PSEUDOCOLOR FB_VISUAL_PSEUDOCOLOR
+
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+
+/* G100, G200 and Mystique have (almost) same DAC */
+#undef NEED_DAC1064
+#if defined(CONFIG_FB_MATROX_MYSTIQUE) || defined(CONFIG_FB_MATROX_G100)
+#define NEED_DAC1064 1
+#endif
+
+typedef struct {
+ u_int8_t* vaddr;
+} vaddr_t;
+
+#ifdef READx_WORKS
+static inline unsigned int mga_readb(vaddr_t va, unsigned int offs) {
+ return readb(va.vaddr + offs);
+}
+
+static inline u_int32_t mga_readl(vaddr_t va, unsigned int offs) {
+ return readl(va.vaddr + offs);
+}
+
+static inline void mga_writeb(vaddr_t va, unsigned int offs, u_int8_t value) {
+ writeb(value, va.vaddr + offs);
+}
+
+static inline void mga_writew(vaddr_t va, unsigned int offs, u_int16_t value) {
+ writew(value, va.vaddr + offs);
+}
+
+static inline void mga_writel(vaddr_t va, unsigned int offs, u_int32_t value) {
+ writel(value, va.vaddr + offs);
+}
+#else
+static inline unsigned int mga_readb(vaddr_t va, unsigned int offs) {
+ return *(volatile u_int8_t*)(va.vaddr + offs);
+}
+
+static inline u_int32_t mga_readl(vaddr_t va, unsigned int offs) {
+ return *(volatile u_int32_t*)(va.vaddr + offs);
+}
+
+static inline void mga_writeb(vaddr_t va, unsigned int offs, u_int8_t value) {
+ *(volatile u_int8_t*)(va.vaddr + offs) = value;
+}
+
+static inline void mga_writew(vaddr_t va, unsigned int offs, u_int16_t value) {
+ *(volatile u_int16_t*)(va.vaddr + offs) = value;
+}
+
+static inline void mga_writel(vaddr_t va, unsigned int offs, u_int32_t value) {
+ *(volatile u_int32_t*)(va.vaddr + offs) = value;
+}
+#endif
+
+static inline void mga_memcpy_toio(vaddr_t va, unsigned int offs, const void* src, int len) {
+#ifdef MEMCPYTOIO_WORKS
+ memcpy_toio(va.vaddr + offs, src, len);
+#elif defined(MEMCPYTOIO_WRITEL)
+#define srcd ((const u_int32_t*)src)
+ if (offs & 3) {
+ while (len >= 4) {
+ mga_writel(va, offs, get_unaligned(srcd++));
+ offs += 4;
+ len -= 4;
+ }
+ } else {
+ while (len >= 4) {
+ mga_writel(va, offs, *srcd++);
+ offs += 4;
+ len -= 4;
+ }
+ }
+#undef srcd
+ if (len) {
+ u_int32_t tmp;
+
+ memcpy(&tmp, src, len);
+ mga_writel(va, offs, tmp);
+ }
+#elif defined(MEMCPYTOIO_MEMCPY)
+ memcpy(va.vaddr + offs, src, len);
+#else
+#error "Sorry, do not know how to write block of data to device"
+#endif
+}
+
+static inline void vaddr_add(vaddr_t* va, unsigned long offs) {
+ va->vaddr += offs;
+}
+
+static inline void* vaddr_va(vaddr_t va) {
+ return va.vaddr;
+}
+
+#define MGA_IOREMAP_NORMAL 0
+#define MGA_IOREMAP_NOCACHE 1
+
+#define MGA_IOREMAP_FB MGA_IOREMAP_NOCACHE
+#define MGA_IOREMAP_MMIO MGA_IOREMAP_NOCACHE
+static inline int mga_ioremap(unsigned long phys, unsigned long size, int flags, vaddr_t* virt) {
+#ifdef MAP_IOREMAP
+ if (flags & MGA_IOREMAP_NOCACHE)
+ virt->vaddr = ioremap_nocache(phys, size);
+ else
+ virt->vaddr = ioremap(phys, size);
+#else
+#ifdef MAP_BUSTOVIRT
+ virt->vaddr = bus_to_virt(phys);
+#else
+#error "Your architecture does not have neither ioremap nor bus_to_virt... Giving up"
+#endif
+#endif
+ return (virt->vaddr == 0); /* 0, !0... 0, error_code in future */
+}
+
+static inline void mga_iounmap(vaddr_t va) {
+#ifdef MAP_IOREMAP
+ iounmap(va.vaddr);
+#endif
+}
+
+struct matroxfb_par
+{
+ struct fb_var_screeninfo var;
+
+ unsigned int final_bppShift;
+ int visual; /* unfortunately, fix */
+ int video_type;
+ unsigned int cmap_len;
+ void (*putc)(u_int32_t, u_int32_t, struct display*, int, int, int);
+ void (*putcs)(u_int32_t, u_int32_t, struct display*, const unsigned short*, int, int, int);
+};
+
+struct my_timming {
+ unsigned int pixclock;
+ unsigned int HDisplay;
+ unsigned int HSyncStart;
+ unsigned int HSyncEnd;
+ unsigned int HTotal;
+ unsigned int VDisplay;
+ unsigned int VSyncStart;
+ unsigned int VSyncEnd;
+ unsigned int VTotal;
+ unsigned int sync;
+ int dblscan;
+ int interlaced;
+};
+
+struct matrox_fb_info;
+
+#define MATROX_2MB_WITH_4MB_ADDON
+
+struct matrox_pll_features {
+ unsigned int vco_freq_min;
+ unsigned int ref_freq;
+ unsigned int feed_div_min;
+ unsigned int feed_div_max;
+ unsigned int in_div_min;
+ unsigned int in_div_max;
+ unsigned int post_shift_max;
+};
+
+struct matrox_DAC1064_features {
+ u_int8_t xvrefctrl;
+ unsigned int cursorimage;
+};
+
+struct matrox_accel_features {
+ int has_cacheflush;
+};
+
+/* current hardware status */
+struct matrox_hw_state {
+ u_int32_t MXoptionReg;
+ unsigned char DACclk[6];
+ unsigned char DACreg[64];
+ unsigned char MiscOutReg;
+ unsigned char DACpal[768];
+ unsigned char CRTC[25];
+ unsigned char CRTCEXT[6];
+ unsigned char SEQ[5];
+ /* unused for MGA mode, but who knows... */
+ unsigned char GCTL[9];
+ /* unused for MGA mode, but who knows... */
+ unsigned char ATTR[21];
+};
+
+struct matrox_accel_data {
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+ unsigned char ramdac_rev;
+#endif
+ u_int32_t m_dwg_rect;
+ u_int32_t m_opmode;
+};
+
+#ifdef CONFIG_FB_MATROX_MULTIHEAD
+#define ACCESS_FBINFO(x) (minfo->x)
+#define ACCESS_FBINFO2(info, x) (((struct matrox_fb_info*)info)->x)
+
+#define MINFO minfo
+
+#define WPMINFO struct matrox_fb_info* minfo,
+#define CPMINFO const struct matrox_fb_info* minfo,
+#define PMINFO minfo,
+
+static inline struct matrox_fb_info* mxinfo(struct display* p) {
+ return (struct matrox_fb_info*)p->fb_info;
+}
+
+#define PMXINFO(p) mxinfo(p),
+#define MINFO_FROM_DISP(x) struct matrox_fb_info* minfo = mxinfo(x)
+
+#else
+
+struct matrox_fb_info global_mxinfo;
+struct display global_disp;
+
+#define ACCESS_FBINFO(x) (global_mxinfo.x)
+#define ACCESS_FBINFO2(info, x) (global_mxinfo.x)
+
+#define MINFO (&global_mxinfo)
+
+#define WPMINFO
+#define CPMINFO
+#define PMINFO
+
+#if 0
+static inline struct matrox_fb_info* mxinfo(struct display* p) {
+ return &global_mxinfo;
+}
+#endif
+
+#define PMXINFO(p)
+#define MINFO_FROM_DISP(x)
+
+#endif
+
+struct matrox_switch {
+ int (*preinit)(WPMINFO struct matrox_hw_state*);
+ void (*reset)(WPMINFO struct matrox_hw_state*);
+ int (*init)(CPMINFO struct matrox_hw_state*, struct my_timming*);
+ void (*restore)(WPMINFO struct matrox_hw_state*, struct matrox_hw_state*, struct display*);
+};
+
+struct matrox_fb_info {
+ /* fb_info must be first */
+ struct fb_info fbcon;
+
+ struct matrox_fb_info* next_fb;
+
+ struct matroxfb_par curr;
+ struct matrox_hw_state hw1;
+ struct matrox_hw_state hw2;
+ struct matrox_hw_state* newhw;
+ struct matrox_hw_state* currenthw;
+
+ struct matrox_accel_data accel;
+
+#ifdef MATROX_2MB_WITH_4MB_ADDON
+ unsigned int _mga_ydstorg;
+ unsigned int _curr_ydstorg;
+#endif
+
+ struct pci_dev* pcidev;
+
+ struct {
+ unsigned long base; /* physical */
+ vaddr_t vbase; /* CPU view */
+ unsigned int len;
+ unsigned int len_usable;
+ } video;
+
+ struct {
+ unsigned long base; /* physical */
+ vaddr_t vbase; /* CPU view */
+ unsigned int len;
+ } mmio;
+
+ unsigned int max_pixel_clock;
+
+ struct matrox_switch* hw_switch;
+ int currcon;
+ struct display* currcon_display;
+
+ struct {
+ struct matrox_pll_features pll;
+ struct matrox_DAC1064_features DAC1064;
+ struct matrox_accel_features accel;
+ } features;
+ struct {
+ spinlock_t DAC;
+ } lock;
+
+ int interleave;
+ int millenium;
+ int milleniumII;
+ struct {
+ int cfb4;
+ const int* vxres;
+ int cross4MB;
+ } capable;
+ struct {
+ unsigned int size;
+ unsigned int mgabase;
+ vaddr_t vbase;
+ } fastfont;
+#ifdef CONFIG_MTRR
+ struct {
+ int vram;
+ int vram_valid;
+ } mtrr;
+#endif
+ struct {
+ int precise_width;
+ int mga_24bpp_fix;
+ int novga;
+ int nobios;
+ int nopciretry;
+ int inverse;
+ int hwcursor;
+ int blink;
+
+ int accelerator;
+ int video64bits;
+ } devflags;
+ struct display_switch dispsw;
+ struct {
+ int x;
+ int y;
+ unsigned int w;
+ unsigned int u;
+ unsigned int d;
+ unsigned int type;
+ int state;
+ struct timer_list timer;
+ } cursor;
+#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
+ union {
+#ifdef FBCON_HAS_CFB16
+ u_int16_t cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+ u_int32_t cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u_int32_t cfb32[16];
+#endif
+ } cmap;
+#endif
+ struct { unsigned red, green, blue, transp; } palette[256];
+#if defined(CONFIG_FB_COMPAT_XPMAC)
+ char matrox_name[32];
+#endif
+};
+
+#if defined(CONFIG_PPC)
+unsigned char nvram_read_byte(int);
+static int default_vmode = VMODE_NVRAM;
+static int default_cmode = CMODE_NVRAM;
+#endif
+#if defined(CONFIG_FB_OF)
+void matrox_of_init(struct device_node *dp);
+#endif
+
+#ifdef MATROX_2MB_WITH_4MB_ADDON
+#define mga_ydstorg(x) ACCESS_FBINFO2(x, _mga_ydstorg)
+#define curr_ydstorg(x) ACCESS_FBINFO2(x, _curr_ydstorg)
+#else
+#define mga_ydstorg(x) (0)
+#define curr_ydstorg(x) (0)
+#endif
+
+#define PCI_OPTION_REG 0x40
+#define PCI_MGA_INDEX 0x44
+#define PCI_MGA_DATA 0x48
+
+#define M_DWGCTL 0x1C00
+#define M_MACCESS 0x1C04
+#define M_CTLWTST 0x1C08
+
+#define M_PLNWT 0x1C1C
+
+#define M_BCOL 0x1C20
+#define M_FCOL 0x1C24
+
+#define M_SGN 0x1C58
+#define M_LEN 0x1C5C
+#define M_AR0 0x1C60
+#define M_AR1 0x1C64
+#define M_AR2 0x1C68
+#define M_AR3 0x1C6C
+#define M_AR4 0x1C70
+#define M_AR5 0x1C74
+#define M_AR6 0x1C78
+
+#define M_CXBNDRY 0x1C80
+#define M_FXBNDRY 0x1C84
+#define M_YDSTLEN 0x1C88
+#define M_PITCH 0x1C8C
+#define M_YDST 0x1C90
+#define M_YDSTORG 0x1C94
+#define M_YTOP 0x1C98
+#define M_YBOT 0x1C9C
+
+/* mystique only */
+#define M_CACHEFLUSH 0x1FFF
+
+#define M_EXEC 0x0100
+
+#define M_DWG_TRAP 0x04
+#define M_DWG_BITBLT 0x08
+#define M_DWG_ILOAD 0x09
+
+#define M_DWG_LINEAR 0x0080
+#define M_DWG_SOLID 0x0800
+#define M_DWG_ARZERO 0x1000
+#define M_DWG_SGNZERO 0x2000
+#define M_DWG_SHIFTZERO 0x4000
+
+#define M_DWG_REPLACE 0x000C0000
+#define M_DWG_REPLACE2 (M_DWG_REPLACE | 0x40)
+#define M_DWG_XOR 0x00060010
+
+#define M_DWG_BFCOL 0x04000000
+#define M_DWG_BMONOWF 0x08000000
+
+#define M_DWG_TRANSC 0x40000000
+
+#define M_FIFOSTATUS 0x1E10
+#define M_STATUS 0x1E14
+
+#define M_IEN 0x1E1C
+
+#define M_VCOUNT 0x1E20
+
+#define M_RESET 0x1E40
+
+#define M_OPMODE 0x1E54
+#define M_OPMODE_DMA_GEN_WRITE 0x00
+#define M_OPMODE_DMA_BLIT 0x04
+#define M_OPMODE_DMA_VECTOR_WRITE 0x08
+#define M_OPMODE_DMA_LE 0x0000 /* little endian - no transformation */
+#define M_OPMODE_DMA_BE_8BPP 0x0000
+#define M_OPMODE_DMA_BE_16BPP 0x0100
+#define M_OPMODE_DMA_BE_32BPP 0x0200
+#define M_OPMODE_DIR_LE 0x000000 /* little endian - no transformation */
+#define M_OPMODE_DIR_BE_8BPP 0x000000
+#define M_OPMODE_DIR_BE_16BPP 0x010000
+#define M_OPMODE_DIR_BE_32BPP 0x020000
+
+#define M_ATTR_INDEX 0x1FC0
+#define M_ATTR_DATA 0x1FC1
+
+#define M_MISC_REG 0x1FC2
+#define M_3C2_RD 0x1FC2
+
+#define M_SEQ_INDEX 0x1FC4
+#define M_SEQ_DATA 0x1FC5
+
+#define M_MISC_REG_READ 0x1FCC
+
+#define M_GRAPHICS_INDEX 0x1FCE
+#define M_GRAPHICS_DATA 0x1FCF
+
+#define M_CRTC_INDEX 0x1FD4
+
+#define M_ATTR_RESET 0x1FDA
+#define M_3DA_WR 0x1FDA
+
+#define M_EXTVGA_INDEX 0x1FDE
+#define M_EXTVGA_DATA 0x1FDF
+
+#define M_RAMDAC_BASE 0x3C00
+
+/* fortunately, same on TVP3026 and MGA1064 */
+#define M_DAC_REG (M_RAMDAC_BASE+0)
+#define M_DAC_VAL (M_RAMDAC_BASE+1)
+#define M_PALETTE_MASK (M_RAMDAC_BASE+2)
+
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+#define TVP3026_INDEX 0x00
+#define TVP3026_PALWRADD 0x00
+#define TVP3026_PALDATA 0x01
+#define TVP3026_PIXRDMSK 0x02
+#define TVP3026_PALRDADD 0x03
+#define TVP3026_CURCOLWRADD 0x04
+#define TVP3026_CLOVERSCAN 0x00
+#define TVP3026_CLCOLOR0 0x01
+#define TVP3026_CLCOLOR1 0x02
+#define TVP3026_CLCOLOR2 0x03
+#define TVP3026_CURCOLDATA 0x05
+#define TVP3026_CURCOLRDADD 0x07
+#define TVP3026_CURCTRL 0x09
+#define TVP3026_X_DATAREG 0x0A
+#define TVP3026_CURRAMDATA 0x0B
+#define TVP3026_CURPOSXL 0x0C
+#define TVP3026_CURPOSXH 0x0D
+#define TVP3026_CURPOSYL 0x0E
+#define TVP3026_CURPOSYH 0x0F
+
+#define TVP3026_XSILICONREV 0x01
+#define TVP3026_XCURCTRL 0x06
+#define TVP3026_XCURCTRL_DIS 0x00 /* transparent, transparent, transparent, transparent */
+#define TVP3026_XCURCTRL_3COLOR 0x01 /* transparent, 0, 1, 2 */
+#define TVP3026_XCURCTRL_XGA 0x02 /* 0, 1, transparent, complement */
+#define TVP3026_XCURCTRL_XWIN 0x03 /* transparent, transparent, 0, 1 */
+#define TVP3026_XCURCTRL_BLANK2048 0x00
+#define TVP3026_XCURCTRL_BLANK4096 0x10
+#define TVP3026_XCURCTRL_INTERLACED 0x20
+#define TVP3026_XCURCTRL_ODD 0x00 /* ext.signal ODD/\EVEN */
+#define TVP3026_XCURCTRL_EVEN 0x40 /* ext.signal EVEN/\ODD */
+#define TVP3026_XCURCTRL_INDIRECT 0x00
+#define TVP3026_XCURCTRL_DIRECT 0x80
+#define TVP3026_XLATCHCTRL 0x0F
+#define TVP3026_XLATCHCTRL_1_1 0x06
+#define TVP3026_XLATCHCTRL_2_1 0x07
+#define TVP3026_XLATCHCTRL_4_1 0x06
+#define TVP3026_XLATCHCTRL_8_1 0x06
+#define TVP3026_XLATCHCTRL_16_1 0x06
+#define TVP3026A_XLATCHCTRL_4_3 0x06 /* ??? do not understand... but it works... !!! */
+#define TVP3026A_XLATCHCTRL_8_3 0x07
+#define TVP3026B_XLATCHCTRL_4_3 0x08
+#define TVP3026B_XLATCHCTRL_8_3 0x06 /* ??? do not understand... but it works... !!! */
+#define TVP3026_XTRUECOLORCTRL 0x18
+#define TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_ACCEL 0x00
+#define TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_TVP 0x20
+#define TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR 0x80
+#define TVP3026_XTRUECOLORCTRL_TRUECOLOR 0x40 /* paletized */
+#define TVP3026_XTRUECOLORCTRL_DIRECTCOLOR 0x00
+#define TVP3026_XTRUECOLORCTRL_24_ALTERNATE 0x08 /* 5:4/5:2 instead of 4:3/8:3 */
+#define TVP3026_XTRUECOLORCTRL_RGB_888 0x16 /* 4:3/8:3 (or 5:4/5:2) */
+#define TVP3026_XTRUECOLORCTRL_BGR_888 0x17
+#define TVP3026_XTRUECOLORCTRL_ORGB_8888 0x06
+#define TVP3026_XTRUECOLORCTRL_BGRO_8888 0x07
+#define TVP3026_XTRUECOLORCTRL_RGB_565 0x05
+#define TVP3026_XTRUECOLORCTRL_ORGB_1555 0x04
+#define TVP3026_XTRUECOLORCTRL_RGB_664 0x03
+#define TVP3026_XTRUECOLORCTRL_RGBO_4444 0x01
+#define TVP3026_XMUXCTRL 0x19
+#define TVP3026_XMUXCTRL_MEMORY_8BIT 0x01 /* - */
+#define TVP3026_XMUXCTRL_MEMORY_16BIT 0x02 /* - */
+#define TVP3026_XMUXCTRL_MEMORY_32BIT 0x03 /* 2MB RAM, 512K * 4 */
+#define TVP3026_XMUXCTRL_MEMORY_64BIT 0x04 /* >2MB RAM, 512K * 8 & more */
+#define TVP3026_XMUXCTRL_PIXEL_4BIT 0x40 /* L0,H0,L1,H1... */
+#define TVP3026_XMUXCTRL_PIXEL_4BIT_SWAPPED 0x60 /* H0,L0,H1,L1... */
+#define TVP3026_XMUXCTRL_PIXEL_8BIT 0x48
+#define TVP3026_XMUXCTRL_PIXEL_16BIT 0x50
+#define TVP3026_XMUXCTRL_PIXEL_32BIT 0x58
+#define TVP3026_XMUXCTRL_VGA 0x98 /* VGA MEMORY, 8BIT PIXEL */
+#define TVP3026_XCLKCTRL 0x1A
+#define TVP3026_XCLKCTRL_DIV1 0x00
+#define TVP3026_XCLKCTRL_DIV2 0x10
+#define TVP3026_XCLKCTRL_DIV4 0x20
+#define TVP3026_XCLKCTRL_DIV8 0x30
+#define TVP3026_XCLKCTRL_DIV16 0x40
+#define TVP3026_XCLKCTRL_DIV32 0x50
+#define TVP3026_XCLKCTRL_DIV64 0x60
+#define TVP3026_XCLKCTRL_CLKSTOPPED 0x70
+#define TVP3026_XCLKCTRL_SRC_CLK0 0x00
+#define TVP3026_XCLKCTRL_SRC_CLK1 0x01
+#define TVP3026_XCLKCTRL_SRC_CLK2 0x02 /* CLK2 is TTL source*/
+#define TVP3026_XCLKCTRL_SRC_NCLK2 0x03 /* not CLK2 is TTL source */
+#define TVP3026_XCLKCTRL_SRC_ECLK2 0x04 /* CLK2 and not CLK2 is ECL source */
+#define TVP3026_XCLKCTRL_SRC_PLL 0x05
+#define TVP3026_XCLKCTRL_SRC_DIS 0x06 /* disable & poweroff internal clock */
+#define TVP3026_XCLKCTRL_SRC_CLK0VGA 0x07
+#define TVP3026_XPALETTEPAGE 0x1C
+#define TVP3026_XGENCTRL 0x1D
+#define TVP3026_XGENCTRL_HSYNC_POS 0x00
+#define TVP3026_XGENCTRL_HSYNC_NEG 0x01
+#define TVP3026_XGENCTRL_VSYNC_POS 0x00
+#define TVP3026_XGENCTRL_VSYNC_NEG 0x02
+#define TVP3026_XGENCTRL_LITTLE_ENDIAN 0x00
+#define TVP3026_XGENCTRL_BIG_ENDIAN 0x08
+#define TVP3026_XGENCTRL_BLACK_0IRE 0x00
+#define TVP3026_XGENCTRL_BLACK_75IRE 0x10
+#define TVP3026_XGENCTRL_NO_SYNC_ON_GREEN 0x00
+#define TVP3026_XGENCTRL_SYNC_ON_GREEN 0x20
+#define TVP3026_XGENCTRL_OVERSCAN_DIS 0x00
+#define TVP3026_XGENCTRL_OVERSCAN_EN 0x40
+#define TVP3026_XMISCCTRL 0x1E
+#define TVP3026_XMISCCTRL_DAC_PUP 0x00
+#define TVP3026_XMISCCTRL_DAC_PDOWN 0x01
+#define TVP3026_XMISCCTRL_DAC_EXT 0x00 /* or 8, bit 3 is ignored */
+#define TVP3026_XMISCCTRL_DAC_6BIT 0x04
+#define TVP3026_XMISCCTRL_DAC_8BIT 0x0C
+#define TVP3026_XMISCCTRL_PSEL_DIS 0x00
+#define TVP3026_XMISCCTRL_PSEL_EN 0x10
+#define TVP3026_XMISCCTRL_PSEL_LOW 0x00 /* PSEL high selects directcolor */
+#define TVP3026_XMISCCTRL_PSEL_HIGH 0x20 /* PSEL high selects truecolor or pseudocolor */
+#define TVP3026_XGENIOCTRL 0x2A
+#define TVP3026_XGENIODATA 0x2B
+#define TVP3026_XPLLADDR 0x2C
+#define TVP3026_XPLLADDR_X(LOOP,MCLK,PIX) (((LOOP)<<4) | ((MCLK)<<2) | (PIX))
+#define TVP3026_XPLLDATA_N 0x00
+#define TVP3026_XPLLDATA_M 0x01
+#define TVP3026_XPLLDATA_P 0x02
+#define TVP3026_XPLLDATA_STAT 0x03
+#define TVP3026_XPIXPLLDATA 0x2D
+#define TVP3026_XMEMPLLDATA 0x2E
+#define TVP3026_XLOOPPLLDATA 0x2F
+#define TVP3026_XCOLKEYOVRMIN 0x30
+#define TVP3026_XCOLKEYOVRMAX 0x31
+#define TVP3026_XCOLKEYREDMIN 0x32
+#define TVP3026_XCOLKEYREDMAX 0x33
+#define TVP3026_XCOLKEYGREENMIN 0x34
+#define TVP3026_XCOLKEYGREENMAX 0x35
+#define TVP3026_XCOLKEYBLUEMIN 0x36
+#define TVP3026_XCOLKEYBLUEMAX 0x37
+#define TVP3026_XCOLKEYCTRL 0x38
+#define TVP3026_XCOLKEYCTRL_OVR_EN 0x01
+#define TVP3026_XCOLKEYCTRL_RED_EN 0x02
+#define TVP3026_XCOLKEYCTRL_GREEN_EN 0x04
+#define TVP3026_XCOLKEYCTRL_BLUE_EN 0x08
+#define TVP3026_XCOLKEYCTRL_NEGATE 0x10
+#define TVP3026_XCOLKEYCTRL_ZOOM1 0x00
+#define TVP3026_XCOLKEYCTRL_ZOOM2 0x20
+#define TVP3026_XCOLKEYCTRL_ZOOM4 0x40
+#define TVP3026_XCOLKEYCTRL_ZOOM8 0x60
+#define TVP3026_XCOLKEYCTRL_ZOOM16 0x80
+#define TVP3026_XCOLKEYCTRL_ZOOM32 0xA0
+#define TVP3026_XMEMPLLCTRL 0x39
+#define TVP3026_XMEMPLLCTRL_DIV(X) (((X)-1)>>1) /* 2,4,6,8,10,12,14,16, division applied to LOOP PLL after divide by 2^P */
+#define TVP3026_XMEMPLLCTRL_STROBEMKC4 0x08
+#define TVP3026_XMEMPLLCTRL_MCLK_DOTCLOCK 0x00 /* MKC4 */
+#define TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL 0x10 /* MKC4 */
+#define TVP3026_XMEMPLLCTRL_RCLK_PIXPLL 0x00
+#define TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL 0x20
+#define TVP3026_XMEMPLLCTRL_RCLK_DOTDIVN 0x40 /* dot clock divided by loop pclk N prescaler */
+#define TVP3026_XSENSETEST 0x3A
+#define TVP3026_XTESTMODEDATA 0x3B
+#define TVP3026_XCRCREML 0x3C
+#define TVP3026_XCRCREMH 0x3D
+#define TVP3026_XCRCBITSEL 0x3E
+#define TVP3026_XID 0x3F
+
+#endif
+
+#ifdef NEED_DAC1064
+
+#define DAC1064_OPT_SCLK_PCI 0x00
+#define DAC1064_OPT_SCLK_PLL 0x01
+#define DAC1064_OPT_SCLK_EXT 0x02
+#define DAC1064_OPT_SCLK_MASK 0x03
+#define DAC1064_OPT_GDIV1 0x04 /* maybe it is GDIV2 on G100 ?! */
+#define DAC1064_OPT_GDIV3 0x00
+#define DAC1064_OPT_MDIV1 0x08
+#define DAC1064_OPT_MDIV2 0x00
+#define DAC1064_OPT_RESERVED 0x10
+
+#define M1064_INDEX 0x00
+#define M1064_PALWRADD 0x00
+#define M1064_PALDATA 0x01
+#define M1064_PIXRDMSK 0x02
+#define M1064_PALRDADD 0x03
+#define M1064_X_DATAREG 0x0A
+#define M1064_CURPOSXL 0x0C /* can be accessed as DWORD */
+#define M1064_CURPOSXH 0x0D
+#define M1064_CURPOSYL 0x0E
+#define M1064_CURPOSYH 0x0F
+
+#define M1064_XCURADDL 0x04
+#define M1064_XCURADDH 0x05
+#define M1064_XCURCTRL 0x06
+#define M1064_XCURCTRL_DIS 0x00 /* transparent, transparent, transparent, transparent */
+#define M1064_XCURCTRL_3COLOR 0x01 /* transparent, 0, 1, 2 */
+#define M1064_XCURCTRL_XGA 0x02 /* 0, 1, transparent, complement */
+#define M1064_XCURCTRL_XWIN 0x03 /* transparent, transparent, 0, 1 */
+#define M1064_XCURCOL0RED 0x08
+#define M1064_XCURCOL0GREEN 0x09
+#define M1064_XCURCOL0BLUE 0x0A
+#define M1064_XCURCOL1RED 0x0C
+#define M1064_XCURCOL1GREEN 0x0D
+#define M1064_XCURCOL1BLUE 0x0E
+#define M1064_XCURCOL2RED 0x10
+#define M1064_XCURCOL2GREEN 0x11
+#define M1064_XCURCOL2BLUE 0x12
+#define DAC1064_XVREFCTRL 0x18
+#define DAC1064_XVREFCTRL_INTERNAL 0x3F
+#define DAC1064_XVREFCTRL_EXTERNAL 0x00
+#define DAC1064_XVREFCTRL_G100_DEFAULT 0x03
+#define M1064_XMULCTRL 0x19
+#define M1064_XMULCTRL_DEPTH_8BPP 0x00 /* 8 bpp paletized */
+#define M1064_XMULCTRL_DEPTH_15BPP_1BPP 0x01 /* 15 bpp paletized + 1 bpp overlay */
+#define M1064_XMULCTRL_DEPTH_16BPP 0x02 /* 16 bpp paletized */
+#define M1064_XMULCTRL_DEPTH_24BPP 0x03 /* 24 bpp paletized */
+#define M1064_XMULCTRL_DEPTH_24BPP_8BPP 0x04 /* 24 bpp direct + 8 bpp overlay paletized */
+#define M1064_XMULCTRL_2G8V16 0x05 /* 15 bpp video direct, half xres, 8bpp paletized */
+#define M1064_XMULCTRL_G16V16 0x06 /* 15 bpp video, 15bpp graphics, one of them paletized */
+#define M1064_XMULCTRL_DEPTH_32BPP 0x07 /* 24 bpp paletized + 8 bpp unused */
+#define M1064_XMULCTRL_GRAPHICS_PALETIZED 0x00
+#define M1064_XMULCTRL_VIDEO_PALETIZED 0x08
+#define M1064_XPIXCLKCTRL 0x1A
+#define M1064_XPIXCLKCTRL_SRC_PCI 0x00
+#define M1064_XPIXCLKCTRL_SRC_PLL 0x01
+#define M1064_XPIXCLKCTRL_SRC_EXT 0x02
+#define M1064_XPIXCLKCTRL_SRC_MASK 0x03
+#define M1064_XPIXCLKCTRL_EN 0x00
+#define M1064_XPIXCLKCTRL_DIS 0x04
+#define M1064_XPIXCLKCTRL_PLL_DOWN 0x00
+#define M1064_XPIXCLKCTRL_PLL_UP 0x08
+#define M1064_XGENCTRL 0x1D
+#define M1064_XGENCTRL_VS_0 0x00
+#define M1064_XGENCTRL_VS_1 0x01
+#define M1064_XGENCTRL_ALPHA_DIS 0x00
+#define M1064_XGENCTRL_ALPHA_EN 0x02
+#define M1064_XGENCTRL_BLACK_0IRE 0x00
+#define M1064_XGENCTRL_BLACK_75IRE 0x10
+#define M1064_XGENCTRL_SYNC_ON_GREEN 0x00
+#define M1064_XGENCTRL_NO_SYNC_ON_GREEN 0x20
+#define M1064_XGENCTRL_SYNC_ON_GREEN_MASK 0x20
+#define M1064_XMISCCTRL 0x1E
+#define M1064_XMISCCTRL_DAC_DIS 0x00
+#define M1064_XMISCCTRL_DAC_EN 0x01
+#define M1064_XMISCCTRL_MFC_VGA 0x00
+#define M1064_XMISCCTRL_MFC_MAFC 0x02
+#define M1064_XMISCCTRL_MFC_DIS 0x06
+#define M1064_XMISCCTRL_DAC_6BIT 0x00
+#define M1064_XMISCCTRL_DAC_8BIT 0x08
+#define M1064_XMISCCTRL_LUT_DIS 0x00
+#define M1064_XMISCCTRL_LUT_EN 0x10
+#define M1064_XGENIOCTRL 0x2A
+#define M1064_XGENIODATA 0x2B
+#define DAC1064_XSYSPLLM 0x2C
+#define DAC1064_XSYSPLLN 0x2D
+#define DAC1064_XSYSPLLP 0x2E
+#define DAC1064_XSYSPLLSTAT 0x2F
+#define M1064_XZOOMCTRL 0x38
+#define M1064_XZOOMCTRL_1 0x00
+#define M1064_XZOOMCTRL_2 0x01
+#define M1064_XZOOMCTRL_4 0x03
+#define M1064_XSENSETEST 0x3A
+#define M1064_XSENSETEST_BCOMP 0x01
+#define M1064_XSENSETEST_GCOMP 0x02
+#define M1064_XSENSETEST_RCOMP 0x04
+#define M1064_XSENSETEST_PDOWN 0x00
+#define M1064_XSENSETEST_PUP 0x80
+#define M1064_XCRCREML 0x3C
+#define M1064_XCRCREMH 0x3D
+#define M1064_XCRCBITSEL 0x3E
+#define M1064_XCOLKEYMASKL 0x40
+#define M1064_XCOLKEYMASKH 0x41
+#define M1064_XCOLKEYL 0x42
+#define M1064_XCOLKEYH 0x43
+#define M1064_XPIXPLLAM 0x44
+#define M1064_XPIXPLLAN 0x45
+#define M1064_XPIXPLLAP 0x46
+#define M1064_XPIXPLLBM 0x48
+#define M1064_XPIXPLLBN 0x49
+#define M1064_XPIXPLLBP 0x4A
+#define M1064_XPIXPLLCM 0x4C
+#define M1064_XPIXPLLCN 0x4D
+#define M1064_XPIXPLLCP 0x4E
+#define M1064_XPIXPLLSTAT 0x4F
+
+#endif
+
+#ifdef __LITTLE_ENDIAN
+#define MX_OPTION_BSWAP 0x00000000
+
+#define M_OPMODE_4BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
+#define M_OPMODE_8BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
+#define M_OPMODE_16BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
+#define M_OPMODE_24BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
+#define M_OPMODE_32BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
+#else
+#ifdef __BIG_ENDIAN
+#define MX_OPTION_BSWAP 0x80000000
+
+#define M_OPMODE_4BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT) /* TODO */
+#define M_OPMODE_8BPP (M_OPMODE_DMA_BE_8BPP | M_OPMODE_DIR_BE_8BPP | M_OPMODE_DMA_BLIT)
+#define M_OPMODE_16BPP (M_OPMODE_DMA_BE_16BPP | M_OPMODE_DIR_BE_16BPP | M_OPMODE_DMA_BLIT)
+#define M_OPMODE_24BPP (M_OPMODE_DMA_BE_8BPP | M_OPMODE_DIR_BE_8BPP | M_OPMODE_DMA_BLIT) /* TODO, ?32 */
+#define M_OPMODE_32BPP (M_OPMODE_DMA_BE_32BPP | M_OPMODE_DIR_BE_32BPP | M_OPMODE_DMA_BLIT)
+#else
+#error "Byte ordering have to be defined. Cannot continue."
+#endif
+#endif
+
+#define mga_inb(addr) mga_readb(ACCESS_FBINFO(mmio.vbase), (addr))
+#define mga_inl(addr) mga_readl(ACCESS_FBINFO(mmio.vbase), (addr))
+#define mga_outb(addr,val) mga_writeb(ACCESS_FBINFO(mmio.vbase), (addr), (val))
+#define mga_outw(addr,val) mga_writew(ACCESS_FBINFO(mmio.vbase), (addr), (val))
+#define mga_outl(addr,val) mga_writel(ACCESS_FBINFO(mmio.vbase), (addr), (val))
+#define mga_readr(port,idx) (mga_outb((port),(idx)), mga_inb((port)+1))
+#ifdef __LITTLE_ENDIAN
+#define mga_setr(addr,port,val) mga_outw(addr, ((val)<<8) | (port))
+#else
+#define mga_setr(addr,port,val) do { mga_outb(addr, port); mga_outb((addr)+1, val); } while (0)
+#endif
+
+#ifdef __LITTLE_ENDIAN
+#define mga_fifo(n) do {} while (mga_inb(M_FIFOSTATUS) < (n))
+#else
+#define mga_fifo(n) do {} while ((mga_inl(M_FIFOSTATUS) & 0xFF) < (n))
+#endif
+
+#define WaitTillIdle() do {} while (mga_inl(M_STATUS) & 0x10000)
+
+/* code speedup */
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+#define isInterleave(x) (x->interleave)
+#define isMillenium(x) (x->millenium)
+#define isMilleniumII(x) (x->milleniumII)
+#else
+#define isInterleave(x) (0)
+#define isMillenium(x) (0)
+#define isMilleniumII(x) (0)
+#endif
+
+static void matrox_cfbX_init(struct matrox_fb_info* minfo) {
+ u_int32_t maccess;
+ u_int32_t mpitch;
+ u_int32_t mopmode;
+
+ DBG("matrox_cfbX_init")
+
+#ifdef MATROX_2MB_WITH_4MB_ADDON
+ curr_ydstorg(MINFO) = mga_ydstorg(MINFO);
+#endif
+ mpitch = ACCESS_FBINFO(curr.var.xres_virtual);
+
+ switch (ACCESS_FBINFO(curr.var.bits_per_pixel)) {
+ case 4: maccess = 0x00000000; /* accelerate as 8bpp video */
+ mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */
+ mopmode = M_OPMODE_4BPP;
+ break;
+ case 8: maccess = 0x00000000;
+ mopmode = M_OPMODE_8BPP;
+ break;
+ case 16: if (ACCESS_FBINFO(curr.var.green.length) == 5)
+ maccess = 0xC0000001;
+ else
+ maccess = 0x40000001;
+#ifdef MATROX_2MB_WITH_4MB_ADDON
+ curr_ydstorg(MINFO) >>= 1;
+#endif
+ mopmode = M_OPMODE_16BPP;
+ break;
+ case 24: maccess = 0x00000003;
+#ifdef MATROX_2MB_WITH_4MB_ADDON
+ curr_ydstorg(MINFO) /= 3;
+#endif
+ mopmode = M_OPMODE_24BPP;
+ break;
+ case 32: maccess = 0x00000002;
+#ifdef MATROX_2MB_WITH_4MB_ADDON
+ curr_ydstorg(MINFO) >>= 2;
+#endif
+ mopmode = M_OPMODE_32BPP;
+ break;
+ default: maccess = 0x00000000;
+ mopmode = 0x00000000;
+ break; /* turn off acceleration!!! */
+ }
+ mga_fifo(8);
+ mga_outl(M_PITCH, mpitch);
+ mga_outl(M_YDSTORG, curr_ydstorg(MINFO));
+ mga_outl(M_PLNWT, -1);
+ mga_outl(M_OPMODE, mopmode);
+ mga_outl(M_CXBNDRY, 0xFFFF0000);
+ mga_outl(M_YTOP, 0);
+ mga_outl(M_YBOT, 0x007FFFFF);
+ mga_outl(M_MACCESS, maccess);
+ ACCESS_FBINFO(accel.m_dwg_rect) = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO;
+ if (isMilleniumII(MINFO)) ACCESS_FBINFO(accel.m_dwg_rect) |= M_DWG_TRANSC;
+ ACCESS_FBINFO(accel.m_opmode) = mopmode;
+}
+
+static void matrox_cfbX_bmove(struct display* p, int sy, int sx, int dy, int dx, int height, int width) {
+ int pixx = p->var.xres_virtual, start, end;
+ MINFO_FROM_DISP(p);
+
+ DBG("matrox_cfbX_bmove")
+
+ sx *= fontwidth(p);
+ dx *= fontwidth(p);
+ width *= fontwidth(p);
+ height *= fontheight(p);
+ sy *= fontheight(p);
+ dy *= fontheight(p);
+ if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
+ mga_fifo(2);
+ mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
+ M_DWG_BFCOL | M_DWG_REPLACE);
+ mga_outl(M_AR5, pixx);
+ width--;
+ start = sy*pixx+sx+curr_ydstorg(MINFO);
+ end = start+width;
+ } else {
+ mga_fifo(3);
+ mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
+ mga_outl(M_SGN, 5);
+ mga_outl(M_AR5, -pixx);
+ width--;
+ end = (sy+height-1)*pixx+sx+curr_ydstorg(MINFO);
+ start = end+width;
+ dy += height-1;
+ }
+ mga_fifo(4);
+ mga_outl(M_AR0, end);
+ mga_outl(M_AR3, start);
+ mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
+ mga_outl(M_YDSTLEN | M_EXEC, ((dy)<<16) | height);
+ WaitTillIdle();
+}
+
+#ifdef FBCON_HAS_CFB4
+static void matrox_cfb4_bmove(struct display* p, int sy, int sx, int dy, int dx, int height, int width) {
+ int pixx, start, end;
+ MINFO_FROM_DISP(p);
+ /* both (sx or dx or width) and fontwidth() are odd, so their multiply is
+ also odd, that means that we cannot use acceleration */
+
+ DBG("matrox_cfb4_bmove")
+
+ if ((sx | dx | width) & fontwidth(p) & 1) {
+ fbcon_cfb4_bmove(p, sy, sx, dy, dx, height, width);
+ return;
+ }
+ sx *= fontwidth(p);
+ dx *= fontwidth(p);
+ width *= fontwidth(p);
+ height *= fontheight(p);
+ sy *= fontheight(p);
+ dy *= fontheight(p);
+ pixx = p->var.xres_virtual >> 1;
+ sx >>= 1;
+ dx >>= 1;
+ width >>= 1;
+ if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
+ mga_fifo(2);
+ mga_outl(M_AR5, pixx);
+ mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
+ M_DWG_BFCOL | M_DWG_REPLACE);
+ width--;
+ start = sy*pixx+sx+curr_ydstorg(MINFO);
+ end = start+width;
+ } else {
+ mga_fifo(3);
+ mga_outl(M_SGN, 5);
+ mga_outl(M_AR5, -pixx);
+ mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
+ width--;
+ end = (sy+height-1)*pixx+sx+curr_ydstorg(MINFO);
+ start = end+width;
+ dy += height-1;
+ }
+ mga_fifo(5);
+ mga_outl(M_AR0, end);
+ mga_outl(M_AR3, start);
+ mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
+ mga_outl(M_YDST, dy*pixx >> 5);
+ mga_outl(M_LEN | M_EXEC, height);
+ WaitTillIdle();
+}
+#endif
+
+static void matroxfb_accel_clear(CPMINFO u_int32_t color, int sy, int sx, int height,
+ int width) {
+
+ DBG("matroxfb_accel_clear")
+
+ mga_fifo(4);
+ mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE);
+ mga_outl(M_FCOL, color);
+ mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
+ mga_outl(M_YDSTLEN | M_EXEC, (sy << 16) | height);
+ WaitTillIdle();
+}
+
+static void matrox_cfbX_clear(u_int32_t color, struct display* p, int sy, int sx, int height, int width) {
+
+ DBG("matrox_cfbX_clear")
+
+ matroxfb_accel_clear(PMXINFO(p) color, sy * fontheight(p), sx * fontwidth(p),
+ height * fontheight(p), width * fontwidth(p));
+}
+
+#ifdef FBCON_HAS_CFB4
+static void matrox_cfb4_clear(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) {
+ u_int32_t bgx;
+ int whattodo;
+ MINFO_FROM_DISP(p);
+
+ DBG("matrox_cfb4_clear")
+
+ whattodo = 0;
+ bgx = attr_bgcol_ec(p, conp);
+ bgx |= bgx << 4;
+ bgx |= bgx << 8;
+ bgx |= bgx << 16;
+ sy *= fontheight(p);
+ sx *= fontwidth(p);
+ height *= fontheight(p);
+ width *= fontwidth(p);
+ if (sx & 1) {
+ sx ++;
+ if (!width) return;
+ width --;
+ whattodo = 1;
+ }
+ if (width & 1) {
+ whattodo |= 2;
+ }
+ width >>= 1;
+ sx >>= 1;
+ if (width) {
+ mga_fifo(5);
+ mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE2);
+ mga_outl(M_FCOL, bgx);
+ mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
+ mga_outl(M_YDST, sy * p->var.xres_virtual >> 6);
+ mga_outl(M_LEN | M_EXEC, height);
+ WaitTillIdle();
+ }
+ if (whattodo) {
+ u_int32_t step = p->var.xres_virtual >> 1;
+ vaddr_t vbase = ACCESS_FBINFO(video.vbase);
+ if (whattodo & 1) {
+ unsigned int uaddr = sy * step + sx - 1;
+ u_int32_t loop;
+ u_int8_t bgx2 = bgx & 0xF0;
+ for (loop = height; loop > 0; loop --) {
+ mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0x0F) | bgx2);
+ uaddr += step;
+ }
+ }
+ if (whattodo & 2) {
+ unsigned int uaddr = sy * step + sx + width;
+ u_int32_t loop;
+ u_int8_t bgx2 = bgx & 0x0F;
+ for (loop = height; loop > 0; loop --) {
+ mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0xF0) | bgx2);
+ uaddr += step;
+ }
+ }
+ }
+}
+#endif
+
+#ifdef FBCON_HAS_CFB8
+static void matrox_cfb8_clear(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) {
+ u_int32_t bgx;
+
+ DBG("matrox_cfb8_clear")
+
+ bgx = attr_bgcol_ec(p, conp);
+ bgx |= bgx << 8;
+ bgx |= bgx << 16;
+ matrox_cfbX_clear(bgx, p, sy, sx, height, width);
+}
+#endif
+
+#ifdef FBCON_HAS_CFB16
+static void matrox_cfb16_clear(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) {
+ u_int32_t bgx;
+
+ DBG("matrox_cfb16_clear")
+
+ bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+ matrox_cfbX_clear((bgx << 16) | bgx, p, sy, sx, height, width);
+}
+#endif
+
+#if defined(FBCON_HAS_CFB32) || defined(FBCON_HAS_CFB24)
+static void matrox_cfb32_clear(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) {
+ u_int32_t bgx;
+
+ DBG("matrox_cfb32_clear")
+
+ bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+ matrox_cfbX_clear(bgx, p, sy, sx, height, width);
+}
+#endif
+
+static void matrox_cfbX_fastputc(u_int32_t fgx, u_int32_t bgx, struct display* p, int c, int yy, int xx) {
+ unsigned int charcell;
+ unsigned int ar3;
+ MINFO_FROM_DISP(p);
+
+ charcell = fontwidth(p) * fontheight(p);
+ yy *= fontheight(p);
+ xx *= fontwidth(p);
+ mga_fifo(7);
+ mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
+
+ mga_outl(M_FCOL, fgx);
+ mga_outl(M_BCOL, bgx);
+ mga_outl(M_FXBNDRY, ((xx + fontwidth(p) - 1) << 16) | xx);
+ ar3 = ACCESS_FBINFO(fastfont.mgabase) + (c & p->charmask) * charcell;
+ mga_outl(M_AR3, ar3);
+ mga_outl(M_AR0, (ar3 + charcell - 1) & 0x0003FFFF);
+ mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p));
+ WaitTillIdle();
+}
+
+static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, int c, int yy, int xx) {
+ u_int32_t ar0;
+ u_int32_t step;
+ MINFO_FROM_DISP(p);
+
+ DBG_HEAVY("matrox_cfbX_putc");
+
+ yy *= fontheight(p);
+ xx *= fontwidth(p);
+#ifdef __BIG_ENDIAN
+ WaitTillIdle();
+ mga_outl(M_OPMODE, M_OPMODE_8BPP);
+#else
+ mga_fifo(7);
+#endif
+ ar0 = fontwidth(p) - 1;
+ mga_outl(M_FXBNDRY, ((xx+ar0)<<16) | xx);
+ if (fontwidth(p) <= 8)
+ step = 1;
+ else if (fontwidth(p) <= 16)
+ step = 2;
+ else
+ step = 4;
+ if (fontwidth(p) == step << 3) {
+ size_t charcell = fontheight(p)*step;
+ /* TODO: Align charcell to 4B for BE */
+ mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
+ mga_outl(M_FCOL, fgx);
+ mga_outl(M_BCOL, bgx);
+ mga_outl(M_AR3, 0);
+ mga_outl(M_AR0, fontheight(p)*fontwidth(p)-1);
+ mga_outl(M_YDSTLEN | M_EXEC, (yy<<16) | fontheight(p));
+ mga_memcpy_toio(ACCESS_FBINFO(mmio.vbase), 0, p->fontdata+(c&p->charmask)*charcell, charcell);
+ } else {
+ u8* chardata = p->fontdata+(c&p->charmask)*fontheight(p)*step;
+ int i;
+
+ mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_REPLACE);
+ mga_outl(M_FCOL, fgx);
+ mga_outl(M_BCOL, bgx);
+ mga_outl(M_AR5, 0);
+ mga_outl(M_AR3, 0);
+ mga_outl(M_AR0, ar0);
+ mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p));
+
+ switch (step) {
+ case 1:
+ for (i = fontheight(p); i > 0; i--) {
+#ifdef __LITTLE_ENDIAN
+ mga_outl(0, *chardata++);
+#else
+ mga_outl(0, (*chardata++) << 24);
+#endif
+ }
+ break;
+ case 2:
+ for (i = fontheight(p); i > 0; i--) {
+#ifdef __LITTLE_ENDIAN
+ mga_outl(0, *(u_int16_t*)chardata);
+#else
+ mga_outl(0, (*(u_int16_t*)chardata) << 16);
+#endif
+ chardata += 2;
+ }
+ break;
+ case 4:
+ mga_memcpy_toio(ACCESS_FBINFO(mmio.vbase), 0, chardata, fontheight(p) * 4);
+ break;
+ }
+ }
+ WaitTillIdle();
+#ifdef __BIG_ENDIAN
+ mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
+#endif
+}
+
+#ifdef FBCON_HAS_CFB8
+static void matrox_cfb8_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
+ u_int32_t fgx, bgx;
+ MINFO_FROM_DISP(p);
+
+ DBG_HEAVY("matroxfb_cfb8_putc");
+
+ fgx = attr_fgcol(p, c);
+ bgx = attr_bgcol(p, c);
+ fgx |= (fgx << 8);
+ fgx |= (fgx << 16);
+ bgx |= (bgx << 8);
+ bgx |= (bgx << 16);
+ ACCESS_FBINFO(curr.putc)(fgx, bgx, p, c, yy, xx);
+}
+#endif
+
+#ifdef FBCON_HAS_CFB16
+static void matrox_cfb16_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
+ u_int32_t fgx, bgx;
+ MINFO_FROM_DISP(p);
+
+ DBG_HEAVY("matroxfb_cfb16_putc");
+
+ fgx = ((u_int16_t*)p->dispsw_data)[attr_fgcol(p, c)];
+ bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol(p, c)];
+ fgx |= (fgx << 16);
+ bgx |= (bgx << 16);
+ ACCESS_FBINFO(curr.putc)(fgx, bgx, p, c, yy, xx);
+}
+#endif
+
+#if defined(FBCON_HAS_CFB32) || defined(FBCON_HAS_CFB24)
+static void matrox_cfb32_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
+ u_int32_t fgx, bgx;
+ MINFO_FROM_DISP(p);
+
+ DBG_HEAVY("matroxfb_cfb32_putc");
+
+ fgx = ((u_int32_t*)p->dispsw_data)[attr_fgcol(p, c)];
+ bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol(p, c)];
+ ACCESS_FBINFO(curr.putc)(fgx, bgx, p, c, yy, xx);
+}
+#endif
+
+static void matrox_cfbX_fastputcs(u_int32_t fgx, u_int32_t bgx, struct display* p, const unsigned short* s, int count, int yy, int xx) {
+ unsigned int charcell;
+ MINFO_FROM_DISP(p);
+
+ yy *= fontheight(p);
+ xx *= fontwidth(p);
+ charcell = fontwidth(p) * fontheight(p);
+ mga_fifo(3);
+ mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
+ mga_outl(M_FCOL, fgx);
+ mga_outl(M_BCOL, bgx);
+ while (count--) {
+ u_int32_t ar3 = ACCESS_FBINFO(fastfont.mgabase) + (*s++ & p->charmask)*charcell;
+
+ mga_fifo(4);
+ mga_outl(M_FXBNDRY, ((xx + fontwidth(p) - 1) << 16) | xx);
+ mga_outl(M_AR3, ar3);
+ mga_outl(M_AR0, (ar3 + charcell - 1) & 0x0003FFFF);
+ mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p));
+ xx += fontwidth(p);
+ }
+ WaitTillIdle();
+}
+
+static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, const unsigned short* s, int count, int yy, int xx) {
+ u_int32_t step;
+ u_int32_t ydstlen;
+ u_int32_t xlen;
+ u_int32_t ar0;
+ u_int32_t charcell;
+ u_int32_t fxbndry;
+ vaddr_t mmio;
+ int easy;
+ MINFO_FROM_DISP(p);
+
+ DBG_HEAVY("matroxfb_cfbX_putcs");
+
+ yy *= fontheight(p);
+ xx *= fontwidth(p);
+ if (fontwidth(p) <= 8)
+ step = 1;
+ else if (fontwidth(p) <= 16)
+ step = 2;
+ else
+ step = 4;
+ charcell = fontheight(p)*step;
+ xlen = (charcell + 3) & ~3;
+ ydstlen = (yy<<16) | fontheight(p);
+ if (fontwidth(p) == step << 3) {
+ ar0 = fontheight(p)*fontwidth(p) - 1;
+ easy = 1;
+ } else {
+ ar0 = fontwidth(p) - 1;
+ easy = 0;
+ }
+#ifdef __BIG_ENDIAN
+ WaitTillIdle();
+ mga_outl(M_OPMODE, M_OPMODE_8BPP);
+#else
+ mga_fifo(3);
+#endif
+ if (easy)
+ mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
+ else
+ mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_REPLACE);
+ mga_outl(M_FCOL, fgx);
+ mga_outl(M_BCOL, bgx);
+ fxbndry = ((xx + fontwidth(p) - 1) << 16) | xx;
+ mmio = ACCESS_FBINFO(mmio.vbase);
+ while (count--) {
+ u_int8_t* chardata = p->fontdata + (*s++ & p->charmask)*charcell;
+
+ mga_fifo(5);
+ mga_writel(mmio, M_FXBNDRY, fxbndry);
+ mga_writel(mmio, M_AR0, ar0);
+ mga_writel(mmio, M_AR3, 0);
+ if (easy) {
+ mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
+ mga_memcpy_toio(mmio, 0, chardata, xlen);
+ } else {
+ mga_writel(mmio, M_AR5, 0);
+ mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
+ switch (step) {
+ case 1: {
+ u_int8_t* charend = chardata + charcell;
+ for (; chardata != charend; chardata++) {
+#ifdef __LITTLE_ENDIAN
+ mga_writel(mmio, 0, *chardata);
+#else
+ mga_writel(mmio, 0, (*chardata) << 24);
+#endif
+ }
+ }
+ break;
+ case 2: {
+ u_int8_t* charend = chardata + charcell;
+ for (; chardata != charend; chardata += 2) {
+#ifdef __LITTLE_ENDIAN
+ mga_writel(mmio, 0, *(u_int16_t*)chardata);
+#else
+ mga_writel(mmio, 0, (*(u_int16_t*)chardata) << 16);
+#endif
+ }
+ }
+ break;
+ default:
+ mga_memcpy_toio(mmio, 0, chardata, charcell);
+ break;
+ }
+ }
+ fxbndry += fontwidth(p) + (fontwidth(p) << 16);
+ }
+ WaitTillIdle();
+#ifdef __BIG_ENDIAN
+ mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
+#endif
+}
+
+#ifdef FBCON_HAS_CFB8
+static void matrox_cfb8_putcs(struct vc_data* conp, struct display* p, const unsigned short* s, int count, int yy, int xx) {
+ u_int32_t fgx, bgx;
+ MINFO_FROM_DISP(p);
+
+ DBG_HEAVY("matroxfb_cfb8_putcs");
+
+ fgx = attr_fgcol(p, *s);
+ bgx = attr_bgcol(p, *s);
+ fgx |= (fgx << 8);
+ fgx |= (fgx << 16);
+ bgx |= (bgx << 8);
+ bgx |= (bgx << 16);
+ ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
+}
+#endif
+
+#ifdef FBCON_HAS_CFB16
+static void matrox_cfb16_putcs(struct vc_data* conp, struct display* p, const unsigned short* s, int count, int yy, int xx) {
+ u_int32_t fgx, bgx;
+ MINFO_FROM_DISP(p);
+
+ DBG_HEAVY("matroxfb_cfb16_putcs");
+
+ fgx = ((u_int16_t*)p->dispsw_data)[attr_fgcol(p, *s)];
+ bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol(p, *s)];
+ fgx |= (fgx << 16);
+ bgx |= (bgx << 16);
+ ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
+}
+#endif
+
+#if defined(FBCON_HAS_CFB32) || defined(FBCON_HAS_CFB24)
+static void matrox_cfb32_putcs(struct vc_data* conp, struct display* p, const unsigned short* s, int count, int yy, int xx) {
+ u_int32_t fgx, bgx;
+ MINFO_FROM_DISP(p);
+
+ DBG_HEAVY("matroxfb_cfb32_putcs");
+
+ fgx = ((u_int32_t*)p->dispsw_data)[attr_fgcol(p, *s)];
+ bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol(p, *s)];
+ ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
+}
+#endif
+
+#ifdef FBCON_HAS_CFB4
+static void matrox_cfb4_revc(struct display* p, int xx, int yy) {
+ MINFO_FROM_DISP(p);
+
+ DBG_LOOP("matroxfb_cfb4_revc");
+
+ if (fontwidth(p) & 1) {
+ fbcon_cfb4_revc(p, xx, yy);
+ return;
+ }
+ yy *= fontheight(p);
+ xx *= fontwidth(p);
+ xx |= (xx + fontwidth(p)) << 16;
+ xx >>= 1;
+
+ mga_fifo(5);
+ mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR);
+ mga_outl(M_FCOL, 0xFFFFFFFF);
+ mga_outl(M_FXBNDRY, xx);
+ mga_outl(M_YDST, yy * p->var.xres_virtual >> 6);
+ mga_outl(M_LEN | M_EXEC, fontheight(p));
+ WaitTillIdle();
+}
+#endif
+
+#ifdef FBCON_HAS_CFB8
+static void matrox_cfb8_revc(struct display* p, int xx, int yy) {
+ MINFO_FROM_DISP(p);
+
+ DBG_LOOP("matrox_cfb8_revc")
+
+ yy *= fontheight(p);
+ xx *= fontwidth(p);
+
+ mga_fifo(4);
+ mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR);
+ mga_outl(M_FCOL, 0x0F0F0F0F);
+ mga_outl(M_FXBNDRY, ((xx + fontwidth(p)) << 16) | xx);
+ mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p));
+ WaitTillIdle();
+}
+#endif
+
+static void matrox_cfbX_revc(struct display* p, int xx, int yy) {
+ MINFO_FROM_DISP(p);
+
+ DBG_LOOP("matrox_cfbX_revc")
+
+ yy *= fontheight(p);
+ xx *= fontwidth(p);
+
+ mga_fifo(4);
+ mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR);
+ mga_outl(M_FCOL, 0xFFFFFFFF);
+ mga_outl(M_FXBNDRY, ((xx + fontwidth(p)) << 16) | xx);
+ mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p));
+ WaitTillIdle();
+}
+
+static void matrox_cfbX_clear_margins(struct vc_data* conp, struct display* p, int bottom_only) {
+ unsigned int bottom_height, right_width;
+ unsigned int bottom_start, right_start;
+ unsigned int cell_h, cell_w;
+
+ DBG("matrox_cfbX_clear_margins")
+
+ cell_w = fontwidth(p);
+ if (!cell_w) return; /* PARANOID */
+ right_width = p->var.xres % cell_w;
+ right_start = p->var.xres - right_width;
+ if (!bottom_only && right_width) {
+ /* clear whole right margin, not only visible portion */
+ matroxfb_accel_clear( PMXINFO(p)
+ /* color */ 0x00000000,
+ /* y */ 0,
+ /* x */ p->var.xoffset + right_start,
+ /* height */ p->var.yres_virtual,
+ /* width */ right_width);
+ }
+ cell_h = fontheight(p);
+ if (!cell_h) return; /* PARANOID */
+ bottom_height = p->var.yres % cell_h;
+ if (bottom_height) {
+ bottom_start = p->var.yres - bottom_height;
+ matroxfb_accel_clear( PMXINFO(p)
+ /* color */ 0x00000000,
+ /* y */ p->var.yoffset + bottom_start,
+ /* x */ p->var.xoffset,
+ /* height */ bottom_height,
+ /* width */ right_start);
+ }
+}
+
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+static void outTi3026(CPMINFO int reg, int val) {
+
+ DBG_REG("outTi3026")
+
+ mga_outb(M_RAMDAC_BASE+TVP3026_INDEX, reg);
+ mga_outb(M_RAMDAC_BASE+TVP3026_X_DATAREG, val);
+}
+
+static int inTi3026(CPMINFO int reg) {
+
+ DBG_REG("inTi3026")
+
+ mga_outb(M_RAMDAC_BASE+TVP3026_INDEX, reg);
+ return mga_inb(M_RAMDAC_BASE+TVP3026_X_DATAREG);
+}
+
+#define POS3026_XCURCTRL 20
+
+static void matroxfb_ti3026_flashcursor(unsigned long ptr) {
+#define minfo ((struct matrox_fb_info*)ptr)
+ spin_lock(&ACCESS_FBINFO(lock.DAC));
+ outTi3026(PMINFO TVP3026_XCURCTRL, inTi3026(PMINFO TVP3026_XCURCTRL) ^ TVP3026_XCURCTRL_DIS ^ TVP3026_XCURCTRL_XGA);
+ ACCESS_FBINFO(cursor.timer.expires) = jiffies + HZ/2;
+ add_timer(&ACCESS_FBINFO(cursor.timer));
+ spin_unlock(&ACCESS_FBINFO(lock.DAC));
+#undef minfo
+}
+
+static void matroxfb_ti3026_createcursor(WPMINFO struct display* p) {
+ unsigned long flags;
+ u_int32_t xline;
+ unsigned int i;
+ unsigned int w, h;
+ unsigned int cd, cu;
+
+ if (ACCESS_FBINFO(currcon_display) != p)
+ return;
+
+ DBG("matroxfb_ti3026_createcursor");
+
+ w = fontwidth(p);
+ h = fontheight(p);
+
+ if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
+ h *= 2;
+ cd = h;
+ if (cd >= 10)
+ cd -= 1;
+ switch (ACCESS_FBINFO(cursor.type) = (p->conp->vc_cursor_type & CUR_HWMASK)) {
+ case CUR_NONE:
+ cu = cd;
+ break;
+ case CUR_UNDERLINE:
+ cu = cd - 2;
+ break;
+ case CUR_LOWER_THIRD:
+ cu = (h * 2) / 3;
+ break;
+ case CUR_LOWER_HALF:
+ cu = h / 2;
+ break;
+ case CUR_TWO_THIRDS:
+ cu = h / 3;
+ break;
+ case CUR_BLOCK:
+ default:
+ cu = 0;
+ cd = h;
+ break;
+ }
+ ACCESS_FBINFO(cursor.w) = w;
+ ACCESS_FBINFO(cursor.u) = cu;
+ ACCESS_FBINFO(cursor.d) = cd;
+ xline = (~0) << (32 - ACCESS_FBINFO(cursor.w));
+ spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
+ mga_outb(M_RAMDAC_BASE+TVP3026_INDEX, 0);
+ for (i = 0; i < cu; i++) {
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ }
+ for (; i < cd; i++) {
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline >> 24);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline >> 16);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline >> 8);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ }
+ for (; i < 64; i++) {
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ }
+ for (i = 0; i < 512; i++)
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0xFF);
+ spin_unlock_irqrestore(&ACCESS_FBINFO(lock.DAC), flags);
+}
+
+static void matroxfb_ti3026_cursor(struct display* p, int mode, int x, int y) {
+ unsigned long flags;
+ MINFO_FROM_DISP(p);
+
+ DBG("matroxfb_ti3026_cursor")
+
+ if (mode == CM_ERASE) {
+ if (ACCESS_FBINFO(cursor.state) != CM_ERASE) {
+ spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
+ ACCESS_FBINFO(cursor.state) = CM_ERASE;
+ del_timer(&ACCESS_FBINFO(cursor.timer));
+ outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(currenthw->DACreg[POS3026_XCURCTRL]));
+ spin_unlock_irqrestore(&ACCESS_FBINFO(lock.DAC), flags);
+ }
+ return;
+ }
+ if ((p->conp->vc_cursor_type & CUR_HWMASK) != ACCESS_FBINFO(cursor.type))
+ matroxfb_ti3026_createcursor(PMINFO p);
+ x *= fontwidth(p);
+ y *= fontheight(p);
+ y -= p->var.yoffset;
+ if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
+ y *= 2;
+ spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
+ if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y))) {
+ ACCESS_FBINFO(cursor.x) = x;
+ ACCESS_FBINFO(cursor.y) = y;
+ x += 64;
+ y += 64;
+ outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(currenthw->DACreg[POS3026_XCURCTRL]));
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURPOSXL, x);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURPOSXH, x >> 8);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURPOSYL, y);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURPOSYH, y >> 8);
+ }
+ ACCESS_FBINFO(cursor.state) = CM_DRAW;
+ if (ACCESS_FBINFO(devflags.blink))
+ mod_timer(&ACCESS_FBINFO(cursor.timer), jiffies + HZ/2);
+ outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(currenthw->DACreg[POS3026_XCURCTRL]) | TVP3026_XCURCTRL_XGA);
+ spin_unlock_irqrestore(&ACCESS_FBINFO(lock.DAC), flags);
+}
+#undef POS3026_XCURCTRL
+
+static int matroxfb_ti3026_setfont(struct display* p, int width, int height) {
+
+ DBG("matrox_ti3026_setfont");
+
+ if (p && p->conp)
+ matroxfb_ti3026_createcursor(PMXINFO(p) p);
+ return 0;
+}
+#endif
+
+#ifdef NEED_DAC1064
+static void outDAC1064(CPMINFO int reg, int val) {
+
+ DBG_REG("outDAC1064");
+
+ mga_outb(M_RAMDAC_BASE+M1064_INDEX, reg);
+ mga_outb(M_RAMDAC_BASE+M1064_X_DATAREG, val);
+}
+
+static int inDAC1064(CPMINFO int reg) {
+
+ DBG_REG("inDAC1064");
+
+ mga_outb(M_RAMDAC_BASE+M1064_INDEX, reg);
+ return mga_inb(M_RAMDAC_BASE+M1064_X_DATAREG);
+}
+
+static void matroxfb_DAC1064_flashcursor(unsigned long ptr) {
+#define minfo ((struct matrox_fb_info*)ptr)
+ spin_lock(&ACCESS_FBINFO(lock.DAC));
+ outDAC1064(PMINFO M1064_XCURCTRL, inDAC1064(PMINFO M1064_XCURCTRL) ^ M1064_XCURCTRL_DIS ^ M1064_XCURCTRL_XGA);
+ ACCESS_FBINFO(cursor.timer.expires) = jiffies + HZ/2;
+ add_timer(&ACCESS_FBINFO(cursor.timer));
+ spin_unlock(&ACCESS_FBINFO(lock.DAC));
+#undef minfo
+}
+
+static void matroxfb_DAC1064_createcursor(WPMINFO struct display* p) {
+ vaddr_t cursorbase;
+ u_int32_t xline;
+ unsigned int i;
+ unsigned int w, h;
+ unsigned int cu, cd;
+
+ if (ACCESS_FBINFO(currcon_display) != p)
+ return;
+
+ w = fontwidth(p);
+ h = fontheight(p);
+
+ if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
+ h *= 2;
+ cd = h;
+ if (cd >= 10)
+ cd -= 1;
+ switch (ACCESS_FBINFO(cursor.type) = (p->conp->vc_cursor_type & CUR_HWMASK)) {
+ case CUR_NONE:
+ cu = cd;
+ break;
+ case CUR_UNDERLINE:
+ cu = cd - 2;
+ break;
+ case CUR_LOWER_THIRD:
+ cu = (h * 2) / 3;
+ break;
+ case CUR_LOWER_HALF:
+ cu = h / 2;
+ break;
+ case CUR_TWO_THIRDS:
+ cu = h / 3;
+ break;
+ case CUR_BLOCK:
+ default:
+ cu = 0;
+ cd = h;
+ break;
+ }
+ ACCESS_FBINFO(cursor.w) = w;
+ ACCESS_FBINFO(cursor.u) = cu;
+ ACCESS_FBINFO(cursor.d) = cd;
+ xline = (~0) << (32 - ACCESS_FBINFO(cursor.w));
+ cursorbase = ACCESS_FBINFO(video.vbase);
+ h = ACCESS_FBINFO(features.DAC1064.cursorimage);
+#ifdef __BIG_ENDIAN
+ WaitTillIdle();
+ mga_outl(M_OPMODE, M_OPMODE_32BPP);
+#endif
+ for (i = 0; i < cu; i++) {
+ mga_writel(cursorbase, h, 0);
+ mga_writel(cursorbase, h+4, 0);
+ mga_writel(cursorbase, h+8, ~0);
+ mga_writel(cursorbase, h+12, ~0);
+ h += 16;
+ }
+ for (; i < cd; i++) {
+ mga_writel(cursorbase, h, 0);
+ mga_writel(cursorbase, h+4, xline);
+ mga_writel(cursorbase, h+8, ~0);
+ mga_writel(cursorbase, h+12, ~0);
+ h += 16;
+ }
+ for (; i < 64; i++) {
+ mga_writel(cursorbase, h, 0);
+ mga_writel(cursorbase, h+4, 0);
+ mga_writel(cursorbase, h+8, ~0);
+ mga_writel(cursorbase, h+12, ~0);
+ h += 16;
+ }
+#ifdef __BIG_ENDIAN
+ mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
+#endif
+}
+
+static void matroxfb_DAC1064_cursor(struct display* p, int mode, int x, int y) {
+ unsigned long flags;
+ MINFO_FROM_DISP(p);
+
+ if (mode == CM_ERASE) {
+ if (ACCESS_FBINFO(cursor.state) != CM_ERASE) {
+ spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
+ ACCESS_FBINFO(cursor.state) = CM_ERASE;
+ del_timer(&ACCESS_FBINFO(cursor.timer));
+ outDAC1064(PMINFO M1064_XCURCTRL, M1064_XCURCTRL_DIS);
+ spin_unlock_irqrestore(&ACCESS_FBINFO(lock.DAC), flags);
+ }
+ return;
+ }
+ if ((p->conp->vc_cursor_type & CUR_HWMASK) != ACCESS_FBINFO(cursor.type))
+ matroxfb_DAC1064_createcursor(PMINFO p);
+ x *= fontwidth(p);
+ y *= fontheight(p);
+ y -= p->var.yoffset;
+ if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
+ y *= 2;
+ spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
+ if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y))) {
+ ACCESS_FBINFO(cursor.x) = x;
+ ACCESS_FBINFO(cursor.y) = y;
+ x += 64;
+ y += 64;
+ outDAC1064(PMINFO M1064_XCURCTRL, M1064_XCURCTRL_DIS);
+ mga_outb(M_RAMDAC_BASE+M1064_CURPOSXL, x);
+ mga_outb(M_RAMDAC_BASE+M1064_CURPOSXH, x >> 8);
+ mga_outb(M_RAMDAC_BASE+M1064_CURPOSYL, y);
+ mga_outb(M_RAMDAC_BASE+M1064_CURPOSYH, y >> 8);
+ }
+ ACCESS_FBINFO(cursor.state) = CM_DRAW;
+ if (ACCESS_FBINFO(devflags.blink))
+ mod_timer(&ACCESS_FBINFO(cursor.timer), jiffies + HZ/2);
+ outDAC1064(PMINFO M1064_XCURCTRL, M1064_XCURCTRL_XGA);
+ spin_unlock_irqrestore(&ACCESS_FBINFO(lock.DAC), flags);
+}
+
+static int matroxfb_DAC1064_setfont(struct display* p, int width, int height) {
+ if (p && p->conp)
+ matroxfb_DAC1064_createcursor(PMXINFO(p) p);
+ return 0;
+}
+#endif
+
+#ifndef FNTCHARCNT
+#define FNTCHARCNT(fd) (((int *)(fd))[-3])
+#endif
+
+static int matroxfb_fastfont_tryset(WPMINFO struct display* p) {
+ unsigned int fsize;
+ unsigned int width;
+
+ if (!p || !p->fontdata)
+ return 0;
+ width = fontwidth(p);
+ if (width > 32)
+ return 0;
+ fsize = (p->userfont?FNTCHARCNT(p->fontdata):256) * fontheight(p);
+ if (((fsize * width + 31) / 32) * 4 > ACCESS_FBINFO(fastfont.size))
+ return 0;
+ mga_outl(M_OPMODE, M_OPMODE_8BPP);
+ if (width <= 8) {
+ if (width == 8)
+ mga_memcpy_toio(ACCESS_FBINFO(fastfont.vbase), 0, p->fontdata, fsize);
+ else {
+ vaddr_t dst;
+ unsigned int i;
+ u_int8_t* font;
+ u_int32_t mask, valid, reg;
+
+ dst = ACCESS_FBINFO(fastfont.vbase);
+ font = (u_int8_t*)p->fontdata;
+ mask = ~0 << (8 - width);
+ valid = 0;
+ reg = 0;
+ i = 0;
+ while (fsize--) {
+ reg |= (*font++ & mask) << (8 - valid);
+ valid += width;
+ if (valid >= 8) {
+ mga_writeb(dst, i++, reg >> 8);
+ reg = reg << 8;
+ valid -= 8;
+ }
+ }
+ if (valid)
+ mga_writeb(dst, i, reg >> 8);
+ }
+ } else if (width <= 16) {
+ if (width == 16)
+ mga_memcpy_toio(ACCESS_FBINFO(fastfont.vbase), 0, p->fontdata, fsize*2);
+ else {
+ vaddr_t dst;
+ u_int16_t* font;
+ u_int32_t mask, valid, reg;
+ unsigned int i;
+
+ dst = ACCESS_FBINFO(fastfont.vbase);
+ font = (u_int16_t*)p->fontdata;
+ mask = ~0 << (16 - width);
+ valid = 0;
+ reg = 0;
+ i = 0;
+ while (fsize--) {
+ reg |= (ntohs(*font++) & mask) << (16 - valid);
+ valid += width;
+ if (valid >= 16) {
+ mga_writew(dst, i, htons(reg >> 16));
+ i += 2;
+ reg = reg << 16;
+ valid -= 16;
+ }
+ }
+ if (valid)
+ mga_writew(dst, i, htons(reg >> 16));
+ }
+ } else {
+ if (width == 32)
+ mga_memcpy_toio(ACCESS_FBINFO(fastfont.vbase), 0, p->fontdata, fsize*4);
+ else {
+ vaddr_t dst;
+ u_int32_t* font;
+ u_int32_t mask, valid, reg;
+ unsigned int i;
+
+ dst = ACCESS_FBINFO(fastfont.vbase);
+ font = (u_int32_t*)p->fontdata;
+ mask = ~0 << (32 - width);
+ valid = 0;
+ reg = 0;
+ i = 0;
+ while (fsize--) {
+ reg |= (ntohl(*font) & mask) >> valid;
+ valid += width;
+ if (valid >= 32) {
+ mga_writel(dst, i, htonl(reg));
+ i += 4;
+ valid -= 32;
+ if (valid)
+ reg = (ntohl(*font) & mask) << (width - valid);
+ else
+ reg = 0;
+ }
+ font++;
+ }
+ if (valid)
+ mga_writel(dst, i, htonl(reg));
+ }
+ }
+ mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
+ return 1;
+}
+
+#define matrox_cfb16_revc matrox_cfbX_revc
+#define matrox_cfb24_revc matrox_cfbX_revc
+#define matrox_cfb32_revc matrox_cfbX_revc
+
+#define matrox_cfb24_clear matrox_cfb32_clear
+#define matrox_cfb24_putc matrox_cfb32_putc
+#define matrox_cfb24_putcs matrox_cfb32_putcs
+
+#ifdef FBCON_HAS_CFB4
+static struct display_switch matroxfb_cfb4 = {
+ fbcon_cfb4_setup, matrox_cfb4_bmove, matrox_cfb4_clear,
+ fbcon_cfb4_putc, fbcon_cfb4_putcs, matrox_cfb4_revc,
+ NULL, NULL, NULL,
+ /* cursor... */ /* set_font... */
+ FONTWIDTH(8) /* fix, fix, fix it */
+};
+#endif
+
+#ifdef FBCON_HAS_CFB8
+static struct display_switch matroxfb_cfb8 = {
+ fbcon_cfb8_setup, matrox_cfbX_bmove, matrox_cfb8_clear,
+ matrox_cfb8_putc, matrox_cfb8_putcs, matrox_cfb8_revc,
+ NULL, NULL, matrox_cfbX_clear_margins,
+ ~1 /* FONTWIDTHS */
+};
+#endif
+
+#ifdef FBCON_HAS_CFB16
+static struct display_switch matroxfb_cfb16 = {
+ fbcon_cfb16_setup, matrox_cfbX_bmove, matrox_cfb16_clear,
+ matrox_cfb16_putc, matrox_cfb16_putcs, matrox_cfb16_revc,
+ NULL, NULL, matrox_cfbX_clear_margins,
+ ~1 /* FONTWIDTHS */
+};
+#endif
+
+#ifdef FBCON_HAS_CFB24
+static struct display_switch matroxfb_cfb24 = {
+ fbcon_cfb24_setup, matrox_cfbX_bmove, matrox_cfb24_clear,
+ matrox_cfb24_putc, matrox_cfb24_putcs, matrox_cfb24_revc,
+ NULL, NULL, matrox_cfbX_clear_margins,
+ ~1 /* FONTWIDTHS */ /* TODO: and what about non-aligned access on BE? I think that there are no in my code */
+};
+#endif
+
+#ifdef FBCON_HAS_CFB32
+static struct display_switch matroxfb_cfb32 = {
+ fbcon_cfb32_setup, matrox_cfbX_bmove, matrox_cfb32_clear,
+ matrox_cfb32_putc, matrox_cfb32_putcs, matrox_cfb32_revc,
+ NULL, NULL, matrox_cfbX_clear_margins,
+ ~1 /* FONTWIDTHS */
+};
+#endif
+
+static struct pci_dev* pci_find(struct pci_dev* p) {
+
+ DBG("pci_find")
+
+ if (p) return p->next;
+ return pci_devices;
+}
+
+static void initMatrox(WPMINFO struct display* p) {
+ struct display_switch *swtmp;
+
+ DBG("initMatrox")
+
+ p->dispsw_data = NULL;
+ if ((p->var.accel_flags & FB_ACCELF_TEXT) != FB_ACCELF_TEXT) {
+ switch (p->var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB4
+ case 4:
+ swtmp = &fbcon_cfb4;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ swtmp = &fbcon_cfb8;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ p->dispsw_data = &ACCESS_FBINFO(cmap.cfb16);
+ swtmp = &fbcon_cfb16;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ p->dispsw_data = &ACCESS_FBINFO(cmap.cfb24);
+ swtmp = &fbcon_cfb24;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ p->dispsw_data = &ACCESS_FBINFO(cmap.cfb32);
+ swtmp = &fbcon_cfb32;
+ break;
+#endif
+ default:
+ p->dispsw = &fbcon_dummy;
+ return;
+ }
+ dprintk(KERN_INFO "matroxfb: acceleration disabled\n");
+ p->dispsw = swtmp;
+ return;
+ }
+ switch (p->var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB4
+ case 4:
+ swtmp = &matroxfb_cfb4;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ swtmp = &matroxfb_cfb8;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ p->dispsw_data = &ACCESS_FBINFO(cmap.cfb16);
+ swtmp = &matroxfb_cfb16;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ p->dispsw_data = &ACCESS_FBINFO(cmap.cfb24);
+ swtmp = &matroxfb_cfb24;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ p->dispsw_data = &ACCESS_FBINFO(cmap.cfb32);
+ swtmp = &matroxfb_cfb32;
+ break;
+#endif
+ default:
+ p->dispsw = &fbcon_dummy;
+ return;
+ }
+ dprintk(KERN_INFO "matroxfb: now accelerated\n");
+ memcpy(&ACCESS_FBINFO(dispsw), swtmp, sizeof(ACCESS_FBINFO(dispsw)));
+ p->dispsw = &ACCESS_FBINFO(dispsw);
+ if (ACCESS_FBINFO(devflags.hwcursor)) {
+ if (isMillenium(MINFO)) {
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+ ACCESS_FBINFO(dispsw.cursor) = matroxfb_ti3026_cursor;
+ ACCESS_FBINFO(dispsw.set_font) = matroxfb_ti3026_setfont;
+#endif
+ } else {
+#ifdef NEED_DAC1064
+ ACCESS_FBINFO(dispsw.cursor) = matroxfb_DAC1064_cursor;
+ ACCESS_FBINFO(dispsw.set_font) = matroxfb_DAC1064_setfont;
+#endif
+ }
+ }
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * card parameters
+ */
+
+/* --------------------------------------------------------------------- */
+
+static struct fb_var_screeninfo vesafb_defined __initdata = {
+ 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,
+ FB_ACCELF_TEXT, /* accel flags */
+ 0L,0L,0L,0L,0L,
+ 0L,0L,0, /* No sync info */
+ FB_VMODE_NONINTERLACED,
+ {0,0,0,0,0,0}
+};
+
+
+
+/* --------------------------------------------------------------------- */
+
+static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
+ struct matroxfb_par* p = &ACCESS_FBINFO(curr);
+ unsigned int pos;
+ unsigned short p0, p1, p2;
+
+ DBG("matrox_pan_var")
+
+ p->var.xoffset = var->xoffset;
+ p->var.yoffset = var->yoffset;
+ if (var->vmode & FB_VMODE_YWRAP)
+ p->var.vmode |= FB_VMODE_YWRAP;
+ else
+ p->var.vmode &= ~FB_VMODE_YWRAP;
+
+ pos = (p->var.yoffset * p->var.xres_virtual + p->var.xoffset) * p->final_bppShift / 32;
+ if (mga_ydstorg(MINFO)) {
+ if (isInterleave(MINFO))
+ pos += mga_ydstorg(MINFO) >> 3;
+ else
+ pos += mga_ydstorg(MINFO) >> 2;
+ }
+
+ p0 = ACCESS_FBINFO(currenthw)->CRTC[0x0D] = pos & 0xFF;
+ p1 = ACCESS_FBINFO(currenthw)->CRTC[0x0C] = (pos & 0xFF00) >> 8;
+ p2 = ACCESS_FBINFO(currenthw)->CRTCEXT[0] = (ACCESS_FBINFO(currenthw)->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F);
+ mga_setr(M_CRTC_INDEX, 0x0D, p0);
+ mga_setr(M_CRTC_INDEX, 0x0C, p1);
+ mga_setr(M_EXTVGA_INDEX, 0x00, p2);
+}
+
+ /*
+ * Open/Release the frame buffer device
+ */
+
+static int matroxfb_open(struct fb_info *info, int user)
+{
+ DBG_LOOP("matroxfb_open")
+
+ /*
+ * Nothing, only a usage count for the moment
+ */
+ MOD_INC_USE_COUNT;
+ return(0);
+}
+
+static int matroxfb_release(struct fb_info *info, int user)
+{
+ DBG_LOOP("matroxfb_release")
+
+ MOD_DEC_USE_COUNT;
+ return(0);
+}
+
+static int matroxfb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info* info) {
+#define minfo ((struct matrox_fb_info*)info)
+
+ DBG("matroxfb_pan_display")
+
+ if (var->vmode & FB_VMODE_YWRAP) {
+ if (var->yoffset < 0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset)
+ return -EINVAL;
+ } else {
+ if (var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual ||
+ var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)
+ return -EINVAL;
+ }
+ if (con == ACCESS_FBINFO(currcon))
+ matrox_pan_var(PMINFO var);
+ fb_display[con].var.xoffset = var->xoffset;
+ fb_display[con].var.yoffset = var->yoffset;
+ if (var->vmode & FB_VMODE_YWRAP)
+ fb_display[con].var.vmode |= FB_VMODE_YWRAP;
+ else
+ fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
+ return 0;
+#undef minfo
+}
+
+static int matroxfb_updatevar(int con, struct fb_info *info)
+{
+#define minfo ((struct matrox_fb_info*)info)
+ DBG("matroxfb_updatevar");
+
+ matrox_pan_var(PMINFO &fb_display[con].var);
+ return 0;
+#undef minfo
+}
+
+static int matroxfb_get_final_bppShift(CPMINFO int bpp) {
+ int bppshft2;
+
+ DBG("matroxfb_get_final_bppShift")
+
+ bppshft2 = bpp;
+ if (isInterleave(MINFO))
+ bppshft2 >>= 1;
+ if (ACCESS_FBINFO(devflags.video64bits))
+ bppshft2 >>= 1;
+ return bppshft2;
+}
+
+static int matroxfb_test_and_set_rounding(CPMINFO int xres, int bpp) {
+ int over;
+ int rounding;
+
+ DBG("matroxfb_test_and_set_rounding")
+
+ switch (bpp) {
+ case 4: rounding = 128;
+ break;
+ case 8: rounding = 64;
+ break;
+ case 16: rounding = 32;
+ break;
+ case 24: rounding = 64;
+ break;
+ default: rounding = 16;
+ break;
+ }
+ if (isInterleave(MINFO)) {
+ rounding *= 2;
+ }
+ over = xres % rounding;
+ if (over)
+ xres += rounding-over;
+ return xres;
+}
+
+static int matroxfb_pitch_adjust(CPMINFO int xres, int bpp) {
+ const int* width;
+ int xres_new;
+
+ DBG("matroxfb_pitch_adjust")
+
+ width = ACCESS_FBINFO(capable.vxres);
+
+ if (ACCESS_FBINFO(devflags.precise_width)) {
+ while (*width) {
+ if ((*width >= xres) && (matroxfb_test_and_set_rounding(PMINFO *width, bpp) == *width)) {
+ break;
+ }
+ width++;
+ }
+ xres_new = *width;
+ } else {
+ xres_new = matroxfb_test_and_set_rounding(PMINFO xres, bpp);
+ }
+ if (!xres_new) return 0;
+ if (xres != xres_new) {
+ printk(KERN_INFO "matroxfb: cannot set xres to %d, rounded up to %d\n", xres, xres_new);
+ }
+ return xres_new;
+}
+
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+static const unsigned char DACseq[] =
+{ TVP3026_XLATCHCTRL, TVP3026_XTRUECOLORCTRL,
+ TVP3026_XMUXCTRL, TVP3026_XCLKCTRL,
+ TVP3026_XPALETTEPAGE,
+ TVP3026_XGENCTRL,
+ TVP3026_XMISCCTRL,
+ TVP3026_XGENIOCTRL,
+ TVP3026_XGENIODATA,
+ TVP3026_XCOLKEYOVRMIN, TVP3026_XCOLKEYOVRMAX, TVP3026_XCOLKEYREDMIN, TVP3026_XCOLKEYREDMAX,
+ TVP3026_XCOLKEYGREENMIN, TVP3026_XCOLKEYGREENMAX, TVP3026_XCOLKEYBLUEMIN, TVP3026_XCOLKEYBLUEMAX,
+ TVP3026_XCOLKEYCTRL,
+ TVP3026_XMEMPLLCTRL, TVP3026_XSENSETEST, TVP3026_XCURCTRL };
+
+#define POS3026_XLATCHCTRL 0
+#define POS3026_XTRUECOLORCTRL 1
+#define POS3026_XMUXCTRL 2
+#define POS3026_XCLKCTRL 3
+#define POS3026_XGENCTRL 5
+#define POS3026_XMISCCTRL 6
+#define POS3026_XMEMPLLCTRL 18
+#define POS3026_XCURCTRL 20
+
+static const unsigned char MGADACbpp32[] =
+{ TVP3026_XLATCHCTRL_2_1, TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_8888,
+ 0x00, TVP3026_XCLKCTRL_DIV1 | TVP3026_XCLKCTRL_SRC_PLL,
+ 0x00,
+ TVP3026_XGENCTRL_HSYNC_POS | TVP3026_XGENCTRL_VSYNC_POS | TVP3026_XGENCTRL_LITTLE_ENDIAN | TVP3026_XGENCTRL_BLACK_0IRE | TVP3026_XGENCTRL_NO_SYNC_ON_GREEN | TVP3026_XGENCTRL_OVERSCAN_DIS,
+ TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_HIGH,
+ 0x00,
+ 0x1E,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ TVP3026_XCOLKEYCTRL_ZOOM1,
+ 0x00, 0x00, TVP3026_XCURCTRL_DIS };
+#endif /* CONFIG_FB_MATROX_MILLENIUM */
+
+static int PLL_calcclock(CPMINFO unsigned int freq, unsigned int fmax, unsigned int* in, unsigned int* feed, unsigned int* post) {
+ unsigned int bestdiff = ~0;
+ unsigned int bestvco = 0;
+ unsigned int fxtal = ACCESS_FBINFO(features.pll.ref_freq);
+ unsigned int fwant;
+ unsigned int p;
+
+ DBG("PLL_calcclock")
+
+ fwant = freq;
+
+#ifdef DEBUG
+ printk(KERN_ERR "post_shift_max: %d\n", ACCESS_FBINFO(features.pll.post_shift_max));
+ printk(KERN_ERR "ref_freq: %d\n", ACCESS_FBINFO(features.pll.ref_freq));
+ printk(KERN_ERR "freq: %d\n", freq);
+ printk(KERN_ERR "vco_freq_min: %d\n", ACCESS_FBINFO(features.pll.vco_freq_min));
+ printk(KERN_ERR "in_div_min: %d\n", ACCESS_FBINFO(features.pll.in_div_min));
+ printk(KERN_ERR "in_div_max: %d\n", ACCESS_FBINFO(features.pll.in_div_max));
+ printk(KERN_ERR "feed_div_min: %d\n", ACCESS_FBINFO(features.pll.feed_div_min));
+ printk(KERN_ERR "feed_div_max: %d\n", ACCESS_FBINFO(features.pll.feed_div_max));
+ printk(KERN_ERR "fmax: %d\n", fmax);
+#endif
+ for (p = 1; p <= ACCESS_FBINFO(features.pll.post_shift_max); p++) {
+ if (fwant * 2 > fmax)
+ break;
+ fwant *= 2;
+ }
+ if (fwant < ACCESS_FBINFO(features.pll.vco_freq_min)) fwant = ACCESS_FBINFO(features.pll.vco_freq_min);
+ if (fwant > fmax) fwant = fmax;
+ for (; p-- > 0; fwant >>= 1, bestdiff >>= 1) {
+ unsigned int m;
+
+ if (fwant < ACCESS_FBINFO(features.pll.vco_freq_min)) break;
+ for (m = ACCESS_FBINFO(features.pll.in_div_min); m <= ACCESS_FBINFO(features.pll.in_div_max); m++) {
+ unsigned int diff, fvco;
+ unsigned int n;
+
+ n = (fwant * (m + 1) + (fxtal >> 1)) / fxtal - 1;
+ if (n > ACCESS_FBINFO(features.pll.feed_div_max))
+ break;
+ if (n < ACCESS_FBINFO(features.pll.feed_div_min))
+ n = ACCESS_FBINFO(features.pll.feed_div_min);
+ fvco = (fxtal * (n + 1)) / (m + 1);
+ if (fvco < fwant)
+ diff = fwant - fvco;
+ else
+ diff = fvco - fwant;
+ if (diff < bestdiff) {
+ bestdiff = diff;
+ *post = p;
+ *in = m;
+ *feed = n;
+ bestvco = fvco;
+ }
+ }
+ }
+ dprintk(KERN_ERR "clk: %02X %02X %02X %d %d %d\n", *in, *feed, *post, fxtal, bestvco, fwant);
+ return bestvco;
+}
+
+#ifdef NEED_DAC1064
+static void DAC1064_calcclock(CPMINFO unsigned int freq, unsigned int fmax, unsigned int* in, unsigned int* feed, unsigned int* post) {
+ unsigned int fvco;
+ unsigned int p;
+
+ DBG("DAC1064_calcclock")
+
+ fvco = PLL_calcclock(PMINFO freq, fmax, in, feed, &p);
+ p = (1 << p) - 1;
+ if (fvco <= 100000)
+ ;
+ else if (fvco <= 140000)
+ p |= 0x08;
+ else if (fvco <= 180000)
+ p |= 0x10;
+ else
+ p |= 0x18;
+ *post = p;
+}
+#endif
+
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+static int Ti3026_calcclock(CPMINFO unsigned int freq, unsigned int fmax, int* in, int* feed, int* post) {
+ unsigned int fvco;
+ unsigned int lin, lfeed, lpost;
+
+ DBG("Ti3026_calcclock")
+
+ fvco = PLL_calcclock(PMINFO freq, fmax, &lin, &lfeed, &lpost);
+ fvco >>= (*post = lpost);
+ *in = 64 - lin;
+ *feed = 64 - lfeed;
+ return fvco;
+}
+
+static int Ti3026_setpclk(CPMINFO struct matrox_hw_state* hw, int clk, int Bpp) {
+ unsigned int f_pll;
+ unsigned int pixfeed, pixin, pixpost;
+ unsigned int loopfeed, loopin, looppost, loopdiv, z;
+
+ DBG("Ti3026_setpclk")
+
+ f_pll = Ti3026_calcclock(PMINFO clk, ACCESS_FBINFO(max_pixel_clock), &pixin, &pixfeed, &pixpost);
+
+ hw->DACclk[0] = pixin | 0xC0;
+ hw->DACclk[1] = pixfeed;
+ hw->DACclk[2] = pixpost | 0xB0;
+ if (ACCESS_FBINFO(curr.var.bits_per_pixel) == 24) {
+ loopfeed = 3; /* set lm to any possible value */
+ loopin = 3 * 32 / Bpp;
+ } else {
+ loopfeed = 4;
+ loopin = 4 * 32 / Bpp;
+ }
+ z = (110000 * loopin) / (f_pll * loopfeed);
+ loopdiv = 0; /* div 2 */
+ if (z < 2)
+ looppost = 0;
+ else if (z < 4)
+ looppost = 1;
+ else if (z < 8)
+ looppost = 2;
+ else {
+ looppost = 3;
+ loopdiv = z/16;
+ }
+ if (ACCESS_FBINFO(curr.var.bits_per_pixel) == 24) {
+ hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
+ hw->DACclk[4] = (65 - loopfeed) | 0x80;
+ if (ACCESS_FBINFO(accel.ramdac_rev) > 0x20) {
+ if (isInterleave(MINFO))
+ hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_8_3;
+ else {
+ hw->DACclk[4] &= ~0xC0;
+ hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3;
+ }
+ } else {
+ if (isInterleave(MINFO))
+ ; /* default... */
+ else {
+ hw->DACclk[4] ^= 0xC0; /* change from 0x80 to 0x40 */
+ hw->DACreg[POS3026_XLATCHCTRL] = TVP3026A_XLATCHCTRL_4_3;
+ }
+ }
+ hw->DACclk[5] = looppost | 0xF8;
+ if (ACCESS_FBINFO(devflags.mga_24bpp_fix))
+ hw->DACclk[5] ^= 0x40;
+ } else {
+ hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
+ hw->DACclk[4] = 65 - loopfeed;
+ hw->DACclk[5] = looppost | 0xF0;
+ }
+ hw->DACreg[POS3026_XMEMPLLCTRL] = loopdiv | TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL;
+ return 0;
+}
+#endif
+
+static void var2my(struct fb_var_screeninfo* var, struct my_timming* mt) {
+ unsigned int pixclock = var->pixclock;
+
+ DBG("var2my")
+
+ if (!pixclock) pixclock = 10000; /* 10ns = 100MHz */
+ mt->pixclock = 1000000000 / pixclock;
+ if (mt->pixclock < 1) mt->pixclock = 1;
+ mt->dblscan = var->vmode & FB_VMODE_DOUBLE;
+ mt->interlaced = var->vmode & FB_VMODE_INTERLACED;
+ mt->HDisplay = var->xres;
+ mt->HSyncStart = mt->HDisplay + var->right_margin;
+ mt->HSyncEnd = mt->HSyncStart + var->hsync_len;
+ mt->HTotal = mt->HSyncEnd + var->left_margin;
+ mt->VDisplay = var->yres;
+ mt->VSyncStart = mt->VDisplay + var->lower_margin;
+ mt->VSyncEnd = mt->VSyncStart + var->vsync_len;
+ mt->VTotal = mt->VSyncEnd + var->upper_margin;
+ mt->sync = var->sync;
+}
+
+static int vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+ unsigned int hd, hs, he, hbe, ht;
+ unsigned int vd, vs, ve, vt;
+ unsigned int wd;
+ unsigned int divider;
+ int i;
+
+ DBG("vgaHWinit")
+
+ hw->SEQ[0] = 0x00;
+ hw->SEQ[1] = 0x01; /* or 0x09 */
+ hw->SEQ[2] = 0x0F; /* bitplanes */
+ hw->SEQ[3] = 0x00;
+ hw->SEQ[4] = 0x0E;
+ /* CRTC 0..7, 9, 16..19, 21, 22 are reprogrammed by Matrox Millenium code... Hope that by MGA1064 too */
+ if (m->dblscan) {
+ m->VTotal <<= 1;
+ m->VDisplay <<= 1;
+ m->VSyncStart <<= 1;
+ m->VSyncEnd <<= 1;
+ }
+ if (m->interlaced) {
+ m->VTotal >>= 1;
+ m->VDisplay >>= 1;
+ m->VSyncStart >>= 1;
+ m->VSyncEnd >>= 1;
+ }
+
+ /* GCTL is ignored when not using 0xA0000 aperture */
+ hw->GCTL[0] = 0x00;
+ hw->GCTL[1] = 0x00;
+ hw->GCTL[2] = 0x00;
+ hw->GCTL[3] = 0x00;
+ hw->GCTL[4] = 0x00;
+ hw->GCTL[5] = 0x40;
+ hw->GCTL[6] = 0x05;
+ hw->GCTL[7] = 0x0F;
+ hw->GCTL[8] = 0xFF;
+
+ /* Whole ATTR is ignored in PowerGraphics mode */
+ for (i = 0; i < 16; i++)
+ hw->ATTR[i] = i;
+ hw->ATTR[16] = 0x41;
+ hw->ATTR[17] = 0xFF;
+ hw->ATTR[18] = 0x0F;
+ hw->ATTR[19] = 0x00;
+ hw->ATTR[20] = 0x00;
+
+ hd = m->HDisplay >> 3;
+ hs = m->HSyncStart >> 3;
+ he = m->HSyncEnd >> 3;
+ ht = m->HTotal >> 3;
+ /* standard timmings are in 8pixels, but for interleaved we cannot */
+ /* do it for 4bpp (because of (4bpp >> 1(interleaved))/4 == 0) */
+ /* using 16 or more pixels per unit can save us */
+ divider = ACCESS_FBINFO(curr.final_bppShift);
+ while (divider & 3) {
+ hd >>= 1;
+ hs >>= 1;
+ he >>= 1;
+ ht >>= 1;
+ divider <<= 1;
+ }
+ divider = divider / 4;
+ /* divider can be from 1 to 8 */
+ while (divider > 8) {
+ hd <<= 1;
+ hs <<= 1;
+ he <<= 1;
+ ht <<= 1;
+ divider >>= 1;
+ }
+ hd = hd - 1;
+ hs = hs - 1;
+ he = he - 1;
+ ht = ht - 1;
+ vd = m->VDisplay - 1;
+ vs = m->VSyncStart - 1;
+ ve = m->VSyncEnd - 1;
+ vt = m->VTotal - 2;
+ if (((ht & 0x0F) == 0x0E) || ((ht & 0x0F) == 0x04))
+ ht++;
+ hbe = ht;
+ wd = ACCESS_FBINFO(curr.var.xres_virtual) * ACCESS_FBINFO(curr.final_bppShift) / 64;
+
+ hw->CRTCEXT[0] = 0;
+ hw->CRTCEXT[5] = 0;
+ if (m->interlaced) {
+ hw->CRTCEXT[0] = 0x80;
+ hw->CRTCEXT[5] = (hs + he - ht) >> 1;
+ if (!m->dblscan)
+ wd <<= 1;
+ vt &= ~1;
+ }
+ hw->CRTCEXT[0] |= (wd & 0x300) >> 4;
+ hw->CRTCEXT[1] = (((ht - 4) & 0x100) >> 8) |
+ ((hd & 0x100) >> 7) | /* blanking */
+ ((hs & 0x100) >> 6) | /* sync start */
+ (hbe & 0x040); /* end hor. blanking */
+ hw->CRTCEXT[2] = ((vt & 0xC00) >> 10) |
+ ((vd & 0x400) >> 8) | /* disp end */
+ ((vd & 0xC00) >> 7) | /* vblanking start */
+ ((vs & 0xC00) >> 5);
+ hw->CRTCEXT[3] = (divider - 1) | 0x80;
+ hw->CRTCEXT[4] = 0;
+
+ hw->CRTC[0] = ht-4;
+ hw->CRTC[1] = hd;
+ hw->CRTC[2] = hd;
+ hw->CRTC[3] = (hbe & 0x1F) | 0x80;
+ hw->CRTC[4] = hs;
+ hw->CRTC[5] = ((hbe & 0x20) << 2) | (he & 0x1F);
+ hw->CRTC[6] = vt & 0xFF;
+ hw->CRTC[7] = ((vt & 0x100) >> 8) |
+ ((vd & 0x100) >> 7) |
+ ((vs & 0x100) >> 6) |
+ ((vd & 0x100) >> 5) |
+ 0x10 |
+ ((vt & 0x200) >> 4) |
+ ((vd & 0x200) >> 3) |
+ ((vs & 0x200) >> 2);
+ hw->CRTC[8] = 0x00;
+ hw->CRTC[9] = ((vd & 0x200) >> 4) | 0x40;
+ if (m->dblscan && !m->interlaced)
+ hw->CRTC[9] |= 0x80;
+ for (i = 10; i < 16; i++)
+ hw->CRTC[i] = 0x00;
+ hw->CRTC[16] = vs /* & 0xFF */;
+ hw->CRTC[17] = (ve & 0x0F) | 0x20;
+ hw->CRTC[18] = vd /* & 0xFF */;
+ hw->CRTC[19] = wd /* & 0xFF */;
+ hw->CRTC[20] = 0x00;
+ hw->CRTC[21] = vd /* & 0xFF */;
+ hw->CRTC[22] = (vt + 1) /* & 0xFF */;
+ hw->CRTC[23] = 0xC3;
+ hw->CRTC[24] = 0xFF;
+ return 0;
+};
+
+#ifdef NEED_DAC1064
+
+static const unsigned char MGA1064_DAC_regs[] = {
+ M1064_XCURADDL, M1064_XCURADDH, M1064_XCURCTRL,
+ M1064_XCURCOL0RED, M1064_XCURCOL0GREEN, M1064_XCURCOL0BLUE,
+ M1064_XCURCOL1RED, M1064_XCURCOL1GREEN, M1064_XCURCOL1BLUE,
+ M1064_XCURCOL2RED, M1064_XCURCOL2GREEN, M1064_XCURCOL2BLUE,
+ DAC1064_XVREFCTRL, M1064_XMULCTRL, M1064_XPIXCLKCTRL, M1064_XGENCTRL,
+ M1064_XMISCCTRL,
+ M1064_XGENIOCTRL, M1064_XGENIODATA, M1064_XZOOMCTRL, M1064_XSENSETEST,
+ M1064_XCRCBITSEL,
+ M1064_XCOLKEYMASKL, M1064_XCOLKEYMASKH, M1064_XCOLKEYL, M1064_XCOLKEYH };
+
+#define POS1064_XCURADDL 0
+#define POS1064_XCURADDH 1
+#define POS1064_XVREFCTRL 12
+#define POS1064_XMULCTRL 13
+#define POS1064_XGENCTRL 15
+
+static const unsigned char MGA1064_DAC[] = {
+ 0x00, 0x00, M1064_XCURCTRL_DIS,
+ 0x00, 0x00, 0x00, /* black */
+ 0xFF, 0xFF, 0xFF, /* white */
+ 0xFF, 0x00, 0x00, /* red */
+ 0x00, 0,
+ M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL,
+ M1064_XGENCTRL_VS_0 | M1064_XGENCTRL_ALPHA_DIS | M1064_XGENCTRL_BLACK_0IRE | M1064_XGENCTRL_NO_SYNC_ON_GREEN,
+ M1064_XMISCCTRL_DAC_EN | M1064_XMISCCTRL_MFC_VGA | M1064_XMISCCTRL_DAC_8BIT | M1064_XMISCCTRL_LUT_EN,
+ 0x10, 0x3F, M1064_XZOOMCTRL_1, M1064_XSENSETEST_BCOMP | M1064_XSENSETEST_GCOMP | M1064_XSENSETEST_RCOMP | M1064_XSENSETEST_PDOWN,
+ 0x00,
+ 0x00, 0x00, 0xFF, 0xFF};
+
+static void DAC1064_setpclk(CPMINFO struct matrox_hw_state* hw, unsigned long fout) {
+ unsigned int m, n, p;
+
+ DBG("DAC1064_setpclk")
+
+ DAC1064_calcclock(PMINFO fout, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p);
+ hw->DACclk[0] = m;
+ hw->DACclk[1] = n;
+ hw->DACclk[2] = p;
+}
+
+__initfunc(static void DAC1064_setmclk(CPMINFO struct matrox_hw_state* hw, int oscinfo, unsigned long fmem)) {
+ u_int32_t mx;
+
+ DBG("DAC1064_setmclk")
+
+ mx = hw->MXoptionReg | 0x00000004;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx);
+ mx &= ~0x000000BB;
+ if (oscinfo & DAC1064_OPT_GDIV1)
+ mx |= 0x00000008;
+ if (oscinfo & DAC1064_OPT_MDIV1)
+ mx |= 0x00000010;
+ if (oscinfo & DAC1064_OPT_RESERVED)
+ mx |= 0x00000080;
+ if ((oscinfo & DAC1064_OPT_SCLK_MASK) == DAC1064_OPT_SCLK_PLL) {
+ /* select PCI clock until we have setup oscilator... */
+ int clk;
+ unsigned int m, n, p;
+
+ /* powerup system PLL, select PCI clock */
+ mx |= 0x00000020;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx);
+ mx &= ~0x00000004;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx);
+
+ /* !!! you must not access device if MCLK is not running !!!
+ Doing so cause immediate PCI lockup :-( Maybe they should
+ generate ABORT or I/O (parity...) error and Linux should
+ recover from this... (kill driver/process). But world is not
+ perfect... */
+ /* (bit 2 of PCI_OPTION_REG must be 0... and bits 0,1 must not
+ select PLL... because of PLL can be stopped at this time) */
+ DAC1064_calcclock(PMINFO fmem, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p);
+ outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3] = m);
+ outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4] = n);
+ outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5] = p);
+ for (clk = 65536; clk; --clk) {
+ if (inDAC1064(PMINFO DAC1064_XSYSPLLSTAT) & 0x40)
+ break;
+ }
+ if (!clk)
+ printk(KERN_ERR "matroxfb: aiee, SYSPLL not locked\n");
+ /* select PLL */
+ mx |= 0x00000005;
+ } else {
+ /* select specified system clock source */
+ mx |= oscinfo & DAC1064_OPT_SCLK_MASK;
+ }
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx);
+ mx &= ~0x00000004;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx);
+ hw->MXoptionReg = mx;
+}
+
+static int DAC1064_init_1(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+
+ DBG("DAC1064_init_1")
+
+ memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
+ switch (ACCESS_FBINFO(curr.var.bits_per_pixel)) {
+ /* case 4: not supported by MGA1064 DAC */
+ case 8:
+ hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
+ break;
+ case 16:
+ if (ACCESS_FBINFO(curr.var.green.length) == 5)
+ hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_15BPP_1BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
+ else
+ hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_16BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
+ break;
+ case 24:
+ hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_24BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
+ break;
+ case 32:
+ hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_32BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
+ break;
+ default:
+ return 1; /* unsupported depth */
+ }
+ hw->DACreg[POS1064_XVREFCTRL] = ACCESS_FBINFO(features.DAC1064.xvrefctrl);
+ hw->DACreg[POS1064_XGENCTRL] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK;
+ hw->DACreg[POS1064_XGENCTRL] |= (m->sync & FB_SYNC_ON_GREEN)?M1064_XGENCTRL_SYNC_ON_GREEN:M1064_XGENCTRL_NO_SYNC_ON_GREEN;
+ hw->DACreg[POS1064_XCURADDL] = ACCESS_FBINFO(features.DAC1064.cursorimage) >> 10;
+ hw->DACreg[POS1064_XCURADDH] = ACCESS_FBINFO(features.DAC1064.cursorimage) >> 18;
+ return 0;
+}
+
+static int DAC1064_init_2(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+
+ DBG("DAC1064_init_2")
+
+ DAC1064_setpclk(PMINFO hw, m->pixclock);
+ if (ACCESS_FBINFO(curr.var.bits_per_pixel) > 16) { /* 256 entries */
+ int i;
+
+ for (i = 0; i < 256; i++) {
+ hw->DACpal[i * 3 + 0] = i;
+ hw->DACpal[i * 3 + 1] = i;
+ hw->DACpal[i * 3 + 2] = i;
+ }
+ } else if (ACCESS_FBINFO(curr.var.bits_per_pixel) > 8) {
+ if (ACCESS_FBINFO(curr.var.green.length) == 5) { /* 0..31, 128..159 */
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ /* with p15 == 0 */
+ hw->DACpal[i * 3 + 0] = i << 3;
+ hw->DACpal[i * 3 + 1] = i << 3;
+ hw->DACpal[i * 3 + 2] = i << 3;
+ /* with p15 == 1 */
+ hw->DACpal[(i + 128) * 3 + 0] = i << 3;
+ hw->DACpal[(i + 128) * 3 + 1] = i << 3;
+ hw->DACpal[(i + 128) * 3 + 2] = i << 3;
+ }
+ } else {
+ int i;
+
+ for (i = 0; i < 64; i++) { /* 0..63 */
+ hw->DACpal[i * 3 + 0] = i << 3;
+ hw->DACpal[i * 3 + 1] = i << 2;
+ hw->DACpal[i * 3 + 2] = i << 3;
+ }
+ }
+ } else {
+ memset(hw->DACpal, 0, 768);
+ }
+ return 0;
+}
+
+static void DAC1064_restore_1(CPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw) {
+
+ DBG("DAC1064_restore_1")
+
+ outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3]);
+ outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4]);
+ outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5]);
+ if (!oldhw || memcmp(hw->DACreg, oldhw->DACreg, sizeof(MGA1064_DAC_regs))) {
+ unsigned int i;
+
+ for (i = 0; i < sizeof(MGA1064_DAC_regs); i++)
+ outDAC1064(PMINFO MGA1064_DAC_regs[i], hw->DACreg[i]);
+ }
+}
+
+static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw, struct display* p) {
+ unsigned int i;
+
+ DBG("DAC1064_restore_2")
+
+ for (i = 0; i < 3; i++)
+ outDAC1064(PMINFO M1064_XPIXPLLCM + i, hw->DACclk[i]);
+ while (!(inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40));
+ if (p && p->conp) {
+ matroxfb_DAC1064_createcursor(PMINFO p);
+ i = matroxfb_fastfont_tryset(PMINFO p);
+ } else
+ i = 0;
+ if (i) {
+ ACCESS_FBINFO(curr.putc) = matrox_cfbX_fastputc;
+ ACCESS_FBINFO(curr.putcs) = matrox_cfbX_fastputcs;
+ } else {
+ ACCESS_FBINFO(curr.putc) = matrox_cfbX_putc;
+ ACCESS_FBINFO(curr.putcs) = matrox_cfbX_putcs;
+ }
+#ifdef DEBUG
+ dprintk(KERN_DEBUG "DAC1064regs ");
+ for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
+ dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], hw->DACreg[i]);
+ if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... ");
+ }
+ dprintk("\n" KERN_DEBUG "DAC1064clk ");
+ for (i = 0; i < 6; i++)
+ dprintk("C%02X=%02X ", i, hw->DACclk[i]);
+ dprintk("\n");
+#endif
+}
+#endif /* NEED_DAC1064 */
+
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+static int MGA1064_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+
+ DBG("MGA1064_init")
+
+ if (DAC1064_init_1(PMINFO hw, m)) return 1;
+ if (vgaHWinit(PMINFO hw, m)) return 1;
+
+ hw->MiscOutReg = 0xCB;
+ if (m->sync & FB_SYNC_HOR_HIGH_ACT)
+ hw->MiscOutReg &= ~0x40;
+ if (m->sync & FB_SYNC_VERT_HIGH_ACT)
+ hw->MiscOutReg &= ~0x80;
+ if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
+ hw->CRTCEXT[3] |= 0x40;
+
+ if (DAC1064_init_2(PMINFO hw, m)) return 1;
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_FB_MATROX_G100
+static int MGAG100_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+
+ DBG("MGAG100_init")
+
+ if (DAC1064_init_1(PMINFO hw, m)) return 1;
+ hw->MXoptionReg &= ~0x2000;
+ if (vgaHWinit(PMINFO hw, m)) return 1;
+
+ hw->MiscOutReg = 0xEF;
+ if (m->sync & FB_SYNC_HOR_HIGH_ACT)
+ hw->MiscOutReg &= ~0x40;
+ if (m->sync & FB_SYNC_VERT_HIGH_ACT)
+ hw->MiscOutReg &= ~0x80;
+ if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
+ hw->CRTCEXT[3] |= 0x40;
+
+ if (DAC1064_init_2(PMINFO hw, m)) return 1;
+ return 0;
+}
+#endif /* G100 */
+
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+static int Ti3026_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+ u_int8_t muxctrl = isInterleave(MINFO) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT;
+
+ DBG("Ti3026_init")
+
+ memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg));
+ switch (ACCESS_FBINFO(curr.var.bits_per_pixel)) {
+ case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1; /* or _8_1, they are same */
+ hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
+ hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_4BIT;
+ hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV8;
+ hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW;
+ break;
+ case 8: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_8_1; /* or _4_1, they are same */
+ hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
+ hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_8BIT;
+ hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4;
+ hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW;
+ break;
+ case 16:
+ /* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used everytime) */
+ hw->DACreg[POS3026_XTRUECOLORCTRL] = (ACCESS_FBINFO(curr.var.green.length) == 5)? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555 ) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565);
+ hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT;
+ hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2;
+ break;
+ case 24:
+ /* XLATCHCTRL is: for (A) use _4_3 (?_8_3 is same? TBD), for (B) it is set in setpclk */
+ hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_888;
+ hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT;
+ hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4;
+ break;
+ case 32:
+ /* XLATCHCTRL should be _2_1 / _1_1... Why is not? (_2_1 is used everytime) */
+ hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT;
+ break;
+ default:
+ return 1; /* TODO: failed */
+ }
+ if (vgaHWinit(PMINFO hw, m)) return 1;
+
+ /* set SYNC */
+ hw->MiscOutReg = 0xCB;
+ if (m->sync & FB_SYNC_HOR_HIGH_ACT)
+ hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_HSYNC_NEG;
+ if (m->sync & FB_SYNC_VERT_HIGH_ACT)
+ hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_VSYNC_NEG;
+ if (m->sync & FB_SYNC_ON_GREEN)
+ hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_SYNC_ON_GREEN;
+
+ /* set DELAY */
+ if (ACCESS_FBINFO(video.len) < 0x400000)
+ hw->CRTCEXT[3] |= 0x08;
+ else if (ACCESS_FBINFO(video.len) > 0x400000)
+ hw->CRTCEXT[3] |= 0x10;
+
+ /* set HWCURSOR */
+ if (m->interlaced) {
+ hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_INTERLACED;
+ }
+ if (m->HTotal >= 1536)
+ hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_BLANK4096;
+
+ /* set interleaving */
+ hw->MXoptionReg &= ~0x00001000;
+ if (isInterleave(MINFO)) hw->MXoptionReg |= 0x00001000;
+
+ /* set DAC */
+ Ti3026_setpclk(PMINFO hw, m->pixclock, ACCESS_FBINFO(curr.final_bppShift));
+ return 0;
+}
+#endif /* CONFIG_FB_MATROX_MILLENIUM */
+
+static int matroxfb_get_cmap_len(struct fb_var_screeninfo *var) {
+
+ DBG("matroxfb_get_cmap_len")
+
+ switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB4
+ case 4:
+ return 16; /* pseudocolor... 16 entries HW palette */
+#endif
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ return 256; /* pseudocolor... 256 entries HW palette */
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ return 16; /* directcolor... 16 entries SW palette */
+ /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ return 16; /* directcolor... 16 entries SW palette */
+ /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ return 16; /* directcolor... 16 entries SW palette */
+ /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
+#endif
+ }
+ return 16; /* return something reasonable... or panic()? */
+}
+
+static int matroxfb_decode_var(CPMINFO struct fb_var_screeninfo *var, int *visual, int *video_cmap_len) {
+ unsigned int vramlen;
+ unsigned int memlen;
+
+ DBG("matroxfb_decode_var")
+
+ if ((var->xres > var->xres_virtual) || (var->yres > var->yres_virtual) ||
+ (var->xoffset > var->xres_virtual) || (var->yoffset > var->yres_virtual))
+ return -EINVAL;
+ switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB4
+ case 4: if (!ACCESS_FBINFO(capable.cfb4)) return -EINVAL;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB8
+ case 8: break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16: break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24: break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32: break;
+#endif
+ default: return -EINVAL;
+ }
+ vramlen = ACCESS_FBINFO(video.len_usable);
+ var->xres_virtual = matroxfb_pitch_adjust(PMINFO var->xres_virtual, var->bits_per_pixel);
+ memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;
+ if (memlen > vramlen)
+ return -EINVAL; /* out of memory */
+ /* There is hardware bug that no line can cross 4MB boundary */
+ /* give up for CFB24, it is impossible to easy workaround it */
+ /* for other try to do something */
+ if (!ACCESS_FBINFO(capable.cross4MB) && (memlen > 0x400000) && (var->bits_per_pixel != 24)) {
+ int new_xres = var->xres_virtual;
+
+ if (new_xres <= 512)
+ new_xres = 512;
+ else if (new_xres <= 1024)
+ new_xres = 1024;
+ else if (new_xres <= 2048)
+ new_xres = 2048;
+ else
+ new_xres = var->xres_virtual;
+ memlen = new_xres * var->bits_per_pixel / 8;
+ /* if now out of memory, try shrink virtual height */
+ /* but if new virtual height is smaller than visible height, return -EINVAL */
+ if (var->yres_virtual * memlen > vramlen) {
+ unsigned int new_yres;
+
+ new_yres = vramlen / memlen;
+ if (new_yres < var->yres)
+ return -EINVAL;
+ var->yres_virtual = new_yres;
+ }
+ var->xres_virtual = new_xres;
+ }
+
+ if (var->bits_per_pixel == 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;
+ *visual = MX_VISUAL_PSEUDOCOLOR;
+ } else if (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;
+ *visual = MX_VISUAL_PSEUDOCOLOR;
+ } else {
+ if (var->bits_per_pixel <= 16) {
+ if (var->green.length == 5) {
+ 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 = 15;
+ var->transp.length = 1;
+ } else {
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ }
+ } else if (var->bits_per_pixel <= 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;
+ } else {
+ 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;
+ }
+ dprintk("matroxfb: truecolor: "
+ "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
+ var->transp.length,
+ var->red.length,
+ var->green.length,
+ var->blue.length,
+ var->transp.offset,
+ var->red.offset,
+ var->green.offset,
+ var->blue.offset);
+ *visual = MX_VISUAL_DIRECTCOLOR;
+ }
+ *video_cmap_len = matroxfb_get_cmap_len(var);
+ dprintk(KERN_INFO "requested %d*%d/%dbpp (%d*%d)\n", var->xres, var->yres, var->bits_per_pixel,
+ var->xres_virtual, var->yres_virtual);
+ return 0;
+}
+
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+__initfunc(static void ti3026_setMCLK(CPMINFO struct matrox_hw_state* hw, int fout)) {
+ unsigned int f_pll;
+ unsigned int pclk_m, pclk_n, pclk_p;
+ unsigned int mclk_m, mclk_n, mclk_p;
+ unsigned int rfhcnt, mclk_ctl;
+ int tmout;
+
+ DBG("ti3026_setMCLK")
+
+ f_pll = Ti3026_calcclock(PMINFO fout, ACCESS_FBINFO(max_pixel_clock), &mclk_n, &mclk_m, &mclk_p);
+
+ /* save pclk */
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0xFC);
+ pclk_n = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0xFD);
+ pclk_m = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0xFE);
+ pclk_p = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
+
+ /* stop pclk */
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0xFE);
+ outTi3026(PMINFO TVP3026_XPIXPLLDATA, 0x00);
+
+ /* set pclk to new mclk */
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0xFC);
+ outTi3026(PMINFO TVP3026_XPIXPLLDATA, mclk_n | 0xC0);
+ outTi3026(PMINFO TVP3026_XPIXPLLDATA, mclk_m);
+ outTi3026(PMINFO TVP3026_XPIXPLLDATA, mclk_p | 0xB0);
+
+ /* wait for PLL to lock */
+ for (tmout = 500000; tmout; tmout--) {
+ if (inTi3026(PMINFO TVP3026_XPIXPLLDATA) & 0x40)
+ break;
+ udelay(10);
+ };
+ if (!tmout)
+ printk(KERN_ERR "matroxfb: Temporary pixel PLL not locked after 5 secs\n");
+
+ /* output pclk on mclk pin */
+ mclk_ctl = inTi3026(PMINFO TVP3026_XMEMPLLCTRL);
+ outTi3026(PMINFO TVP3026_XMEMPLLCTRL, mclk_ctl & 0xE7);
+ outTi3026(PMINFO TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_STROBEMKC4);
+
+ /* stop MCLK */
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0xFB);
+ outTi3026(PMINFO TVP3026_XMEMPLLDATA, 0x00);
+
+ /* set mclk to new freq */
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0xF3);
+ outTi3026(PMINFO TVP3026_XMEMPLLDATA, mclk_n | 0xC0);
+ outTi3026(PMINFO TVP3026_XMEMPLLDATA, mclk_m);
+ outTi3026(PMINFO TVP3026_XMEMPLLDATA, mclk_p | 0xB0);
+
+ /* wait for PLL to lock */
+ for (tmout = 500000; tmout; tmout--) {
+ if (inTi3026(PMINFO TVP3026_XMEMPLLDATA) & 0x40)
+ break;
+ udelay(10);
+ }
+ if (!tmout)
+ printk(KERN_ERR "matroxfb: Memory PLL not locked after 5 secs\n");
+
+ f_pll = f_pll * 333 / (10000 << mclk_p);
+ if (isMilleniumII(MINFO)) {
+ rfhcnt = (f_pll - 128) / 256;
+ if (rfhcnt > 15)
+ rfhcnt = 15;
+ } else {
+ rfhcnt = (f_pll - 64) / 128;
+ if (rfhcnt > 15)
+ rfhcnt = 0;
+ }
+ hw->MXoptionReg = (hw->MXoptionReg & ~0x000F0000) | (rfhcnt << 16);
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+
+ /* output MCLK to MCLK pin */
+ outTi3026(PMINFO TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
+ outTi3026(PMINFO TVP3026_XMEMPLLCTRL, (mclk_ctl ) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_STROBEMKC4);
+
+ /* stop PCLK */
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0xFE);
+ outTi3026(PMINFO TVP3026_XPIXPLLDATA, 0x00);
+
+ /* restore pclk */
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0xFC);
+ outTi3026(PMINFO TVP3026_XPIXPLLDATA, pclk_n);
+ outTi3026(PMINFO TVP3026_XPIXPLLDATA, pclk_m);
+ outTi3026(PMINFO TVP3026_XPIXPLLDATA, pclk_p);
+
+ /* wait for PLL to lock */
+ for (tmout = 500000; tmout; tmout--) {
+ if (inTi3026(PMINFO TVP3026_XPIXPLLDATA) & 0x40)
+ break;
+ udelay(10);
+ }
+ if (!tmout)
+ printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
+}
+
+__initfunc(static void ti3026_ramdac_init(WPMINFO struct matrox_hw_state* hw)) {
+
+ DBG("ti3026_ramdac_init")
+
+ ACCESS_FBINFO(features.pll.vco_freq_min) = 110000;
+ ACCESS_FBINFO(features.pll.ref_freq) = 114545;
+ ACCESS_FBINFO(features.pll.feed_div_min) = 2;
+ ACCESS_FBINFO(features.pll.feed_div_max) = 24;
+ ACCESS_FBINFO(features.pll.in_div_min) = 2;
+ ACCESS_FBINFO(features.pll.in_div_max) = 63;
+ ACCESS_FBINFO(features.pll.post_shift_max) = 3;
+ ti3026_setMCLK(PMINFO hw, 60000);
+}
+#endif
+
+__initfunc(static void matroxfb_fastfont_init(struct matrox_fb_info* minfo)) {
+ unsigned int size;
+
+ size = ACCESS_FBINFO(fastfont.size);
+ ACCESS_FBINFO(fastfont.size) = 0;
+ if (size) {
+ unsigned int end = ACCESS_FBINFO(video.len_usable);
+
+ if (size < end) {
+ unsigned int start;
+
+ start = (end - size) & PAGE_MASK;
+ if (start >= 0x00100000) {
+ ACCESS_FBINFO(video.len_usable) = start;
+ ACCESS_FBINFO(fastfont.mgabase) = start * 8;
+ ACCESS_FBINFO(fastfont.vbase) = ACCESS_FBINFO(video.vbase);
+ vaddr_add(&ACCESS_FBINFO(fastfont.vbase), start);
+ ACCESS_FBINFO(fastfont.size) = end - start;
+ }
+ }
+ }
+}
+
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+__initfunc(static void MGA1064_ramdac_init(WPMINFO struct matrox_hw_state* hw)) {
+
+ DBG("MGA1064_ramdac_init");
+
+ /* ACCESS_FBINFO(features.DAC1064.vco_freq_min) = 120000; */
+ ACCESS_FBINFO(features.pll.vco_freq_min) = 50000;
+ ACCESS_FBINFO(features.pll.ref_freq) = 14318;
+ ACCESS_FBINFO(features.pll.feed_div_min) = 100;
+ ACCESS_FBINFO(features.pll.feed_div_max) = 127;
+ ACCESS_FBINFO(features.pll.in_div_min) = 1;
+ ACCESS_FBINFO(features.pll.in_div_max) = 31;
+ ACCESS_FBINFO(features.pll.post_shift_max) = 3;
+ ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_EXTERNAL;
+ /* maybe cmdline MCLK= ?, doc says gclk=44MHz, mclk=66MHz... it was 55/83 with old values */
+ DAC1064_setmclk(PMINFO hw, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333);
+}
+
+__initfunc(static int MGA1064_preinit(WPMINFO struct matrox_hw_state* hw)) {
+ static const int vxres_mystique[] = { 512, 640, 768, 800, 832, 960,
+ 1024, 1152, 1280, 1600, 1664, 1920,
+ 2048, 0};
+ DBG("MGA1064_preinit")
+
+ /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
+ ACCESS_FBINFO(capable.vxres) = vxres_mystique;
+ ACCESS_FBINFO(features.accel.has_cacheflush) = 1;
+ ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor;
+
+ hw->MXoptionReg &= 0xC0000100;
+ hw->MXoptionReg |= 0x00094E20;
+ if (ACCESS_FBINFO(devflags.novga))
+ hw->MXoptionReg &= ~0x00000100;
+ if (ACCESS_FBINFO(devflags.nobios))
+ hw->MXoptionReg &= ~0x40000000;
+ if (ACCESS_FBINFO(devflags.nopciretry))
+ hw->MXoptionReg |= 0x20000000;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+ mga_setr(M_SEQ_INDEX, 0x01, 0x20);
+ mga_outl(M_CTLWTST, 0x00000000);
+ udelay(200);
+ mga_outl(M_MACCESS, 0x00008000);
+ udelay(100);
+ mga_outl(M_MACCESS, 0x0000C000);
+ return 0;
+}
+
+__initfunc(static void MGA1064_reset(WPMINFO struct matrox_hw_state* hw)) {
+
+ DBG("MGA1064_reset");
+
+ ACCESS_FBINFO(features.DAC1064.cursorimage) = ACCESS_FBINFO(video.len_usable) - 1024;
+ if (ACCESS_FBINFO(devflags.hwcursor))
+ ACCESS_FBINFO(video.len_usable) -= 1024;
+ matroxfb_fastfont_init(MINFO);
+ MGA1064_ramdac_init(PMINFO hw);
+}
+#endif
+
+#ifdef CONFIG_FB_MATROX_G100
+/* BIOS environ */
+static int x7AF4 = 0; /* flags */
+#if 0
+static int def50 = 0; /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */
+#endif
+
+__initfunc(static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p)) {
+ int reg;
+ int selClk;
+ int clk;
+
+ DBG("MGAG100_progPixClock")
+
+ outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS);
+ switch (flags & 3) {
+ case 0: reg = M1064_XPIXPLLAM; break;
+ case 1: reg = M1064_XPIXPLLBM; break;
+ default: reg = M1064_XPIXPLLCM; break;
+ }
+ outDAC1064(PMINFO reg++, m);
+ outDAC1064(PMINFO reg++, n);
+ outDAC1064(PMINFO reg, p);
+ selClk = mga_inb(M_MISC_REG_READ) & ~0xC;
+ /* there should be flags & 0x03 & case 0/1/else */
+ /* and we should first select source and after that we should wait for PLL */
+ /* and we are waiting for PLL with oscilator disabled... Is it right? */
+ switch (flags & 0x03) {
+ case 0x00: break;
+ case 0x01: selClk |= 4; break;
+ default: selClk |= 0x0C; break;
+ }
+ mga_outb(M_MISC_REG, selClk);
+ for (clk = 65536; clk; clk--)
+ if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40)
+ break;
+ if (!clk)
+ printk(KERN_ERR "matroxfb: Pixel PLL%c not locked after usual time\n", (reg-M1064_XPIXPLLAM-2)/4 + 'A');
+ selClk = inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_SRC_MASK;
+ switch (flags & 0x0C) {
+ case 0x00: selClk |= M1064_XPIXCLKCTRL_SRC_PCI; break;
+ case 0x04: selClk |= M1064_XPIXCLKCTRL_SRC_PLL; break;
+ default: selClk |= M1064_XPIXCLKCTRL_SRC_EXT; break;
+ }
+ outDAC1064(PMINFO M1064_XPIXCLKCTRL, selClk);
+ outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS);
+}
+
+__initfunc(static void MGAG100_setPixClock(CPMINFO int flags, int freq)) {
+ unsigned int m, n, p;
+
+ DBG("MGAG100_setPixClock")
+
+ DAC1064_calcclock(PMINFO freq, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p);
+ MGAG100_progPixClock(PMINFO flags, m, n, p);
+}
+
+__initfunc(static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw)) {
+ static const int vxres_g100[] = { 512, 640, 768, 800, 832, 960,
+ 1024, 1152, 1280, 1600, 1664, 1920,
+ 2048, 0};
+#if 0
+ u_int32_t reg50;
+ u_int32_t q;
+#endif
+
+ DBG("MGAG100_preinit")
+
+ /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
+ ACCESS_FBINFO(capable.vxres) = vxres_g100;
+ ACCESS_FBINFO(features.accel.has_cacheflush) = 1;
+ ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor;
+
+ hw->MXoptionReg &= 0xC0000100;
+ hw->MXoptionReg |= 0x00078C20;
+ if (ACCESS_FBINFO(devflags.novga))
+ hw->MXoptionReg &= ~0x00000100;
+ if (ACCESS_FBINFO(devflags.nobios))
+ hw->MXoptionReg &= ~0x40000000;
+ if (ACCESS_FBINFO(devflags.nopciretry))
+ hw->MXoptionReg |= 0x20000000;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+
+ mga_outl(M_CTLWTST, 0x03258A31); /* 03258A31 is x7AF0, default is 0x02032521 */
+#if 0
+ hw->MXoptionReg |= 0x1000;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+ pci_read_config_dword(ACCESS_FBINFO(pcidev), 0x50, &reg50);
+ q = def50 & 0x3000;
+ reg50 = (reg50 & ~0x3000) | q;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), 0x50, reg50);
+ mga_outb(0x1C05, 0x00);
+ mga_outb(0x1C05, 0x80);
+ udelay(100);
+ mga_outb(0x1C05, 0x40);
+ mga_outb(0x1C05, 0xC0);
+ pci_write_config_byte(ACCESS_FBINFO(pcidev), 0x50, def50 & 0x0F);
+ {
+ mga_outb(M_GRAPHICS_INDEX, 6);
+ mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4);
+ mga_setr(M_EXTVGA_INDEX, 0x03, 0x81);
+ mga_setr(M_EXTVGA_INDEX, 0x04, 0x00);
+ mga_writeb(ACCESS_FBINFO(video.vbase), 0x000, 0xAA);
+ mga_writeb(ACCESS_FBINFO(video.vbase), 0x800, 0x55);
+ if (mga_readb(ACCESS_FBINFO(video.vbase), 0x000) != 0xAA) {
+ hw->MXoptionReg &= ~0x1000;
+ }
+ }
+#endif
+ hw->MXoptionReg = (hw->MXoptionReg & ~0x1F8000) | 0x78000;
+ if (!(x7AF4 & 0x10))
+ hw->MXoptionReg |= 0x4000;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+ return 0;
+}
+
+__initfunc(static void MGAG100_reset(WPMINFO struct matrox_hw_state* hw)) {
+ u_int8_t b;
+
+ DBG("MGAG100_reset")
+
+ ACCESS_FBINFO(features.pll.vco_freq_min) = 50000;
+ ACCESS_FBINFO(features.pll.ref_freq) = 27000;
+ ACCESS_FBINFO(features.pll.feed_div_min) = 7;
+ ACCESS_FBINFO(features.pll.feed_div_max) = 127;
+ ACCESS_FBINFO(features.pll.in_div_min) = 1;
+ ACCESS_FBINFO(features.pll.in_div_max) = 31;
+ ACCESS_FBINFO(features.pll.post_shift_max) = 3;
+ ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_G100_DEFAULT;
+ ACCESS_FBINFO(features.DAC1064.cursorimage) = ACCESS_FBINFO(video.len_usable) - 1024;
+ if (ACCESS_FBINFO(devflags.hwcursor))
+ ACCESS_FBINFO(video.len_usable) -= 1024;
+ matroxfb_fastfont_init(MINFO);
+
+ {
+#ifdef G100_BROKEN_IBM_82351
+ u_int32_t d;
+
+ find 1014/22 (IBM/82351); /* if found and bridging Matrox, do some strange stuff */
+ pci_read_config_byte(ibm, PCI_SECONDARY_BUS, &b);
+ if (b == ACCESS_FBINFO(pcidev)->bus->number) {
+ pci_write_config_byte(ibm, PCI_COMMAND+1, 0); /* disable back-to-back & SERR */
+ pci_write_config_byte(ibm, 0x41, 0xF4); /* ??? */
+ pci_write_config_byte(ibm, PCI_IO_BASE, 0xF0); /* ??? */
+ pci_write_config_byte(ibm, PCI_IO_LIMIT, 0x00); /* ??? */
+ }
+#endif
+ if (x7AF4 & 8) {
+ hw->MXoptionReg |= 0x40;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+ }
+ mga_setr(M_EXTVGA_INDEX, 0x06, 0x50);
+ }
+ DAC1064_setmclk(PMINFO hw, DAC1064_OPT_SCLK_PLL, 120000);
+ MGAG100_setPixClock(PMINFO 4, 25175);
+ MGAG100_setPixClock(PMINFO 5, 28322);
+ if (x7AF4 & 0x10) {
+ b = inDAC1064(PMINFO M1064_XGENIODATA) & ~1;
+ outDAC1064(PMINFO M1064_XGENIODATA, b);
+ b = inDAC1064(PMINFO M1064_XGENIOCTRL) | 1;
+ outDAC1064(PMINFO M1064_XGENIOCTRL, b);
+ }
+}
+#endif
+
+static void vgaHWrestore(CPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw) {
+ int i;
+
+ DBG("vgaHWrestore")
+
+ dprintk(KERN_INFO "MiscOutReg: %02X\n", hw->MiscOutReg);
+ dprintk(KERN_INFO "SEQ regs: ");
+ for (i = 0; i < 5; i++)
+ dprintk("%02X:", hw->SEQ[i]);
+ dprintk("\n");
+ dprintk(KERN_INFO "GDC regs: ");
+ for (i = 0; i < 9; i++)
+ dprintk("%02X:", hw->GCTL[i]);
+ dprintk("\n");
+ dprintk(KERN_INFO "CRTC regs: ");
+ for (i = 0; i < 25; i++)
+ dprintk("%02X:", hw->CRTC[i]);
+ dprintk("\n");
+ dprintk(KERN_INFO "ATTR regs: ");
+ for (i = 0; i < 21; i++)
+ dprintk("%02X:", hw->ATTR[i]);
+ dprintk("\n");
+
+ mga_inb(M_ATTR_RESET);
+ mga_outb(M_ATTR_INDEX, 0);
+ mga_outb(M_MISC_REG, hw->MiscOutReg);
+ for (i = 1; i < 5; i++)
+ mga_setr(M_SEQ_INDEX, i, hw->SEQ[i]);
+ mga_setr(M_CRTC_INDEX, 17, hw->CRTC[17] & 0x7F);
+ for (i = 0; i < 25; i++)
+ mga_setr(M_CRTC_INDEX, i, hw->CRTC[i]);
+ for (i = 0; i < 9; i++)
+ mga_setr(M_GRAPHICS_INDEX, i, hw->GCTL[i]);
+ for (i = 0; i < 21; i++) {
+ mga_inb(M_ATTR_RESET);
+ mga_outb(M_ATTR_INDEX, i);
+ mga_outb(M_ATTR_INDEX, hw->ATTR[i]);
+ }
+ mga_outb(M_PALETTE_MASK, 0xFF);
+ mga_outb(M_DAC_REG, 0x00);
+ for (i = 0; i < 768; i++)
+ mga_outb(M_DAC_VAL, hw->DACpal[i]);
+ mga_inb(M_ATTR_RESET);
+ mga_outb(M_ATTR_INDEX, 0x20);
+}
+
+static int matrox_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *fb_info)
+{
+#ifdef CONFIG_FB_MATROX_MULTIHEAD
+ struct matrox_fb_info* minfo = (struct matrox_fb_info*)fb_info;
+#endif
+
+ DBG("matrox_setcolreg")
+
+ /*
+ * 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 >= ACCESS_FBINFO(curr.cmap_len))
+ return 1;
+
+ ACCESS_FBINFO(palette[regno].red) = red;
+ ACCESS_FBINFO(palette[regno].green) = green;
+ ACCESS_FBINFO(palette[regno].blue) = blue;
+ ACCESS_FBINFO(palette[regno].transp) = transp;
+
+ if (ACCESS_FBINFO(curr.var.grayscale)) {
+ /* gray = 0.30*R + 0.59*G + 0.11*B */
+ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+ }
+
+ red = CNVT_TOHW(red, ACCESS_FBINFO(curr.var.red.length));
+ green = CNVT_TOHW(green, ACCESS_FBINFO(curr.var.green.length));
+ blue = CNVT_TOHW(blue, ACCESS_FBINFO(curr.var.blue.length));
+ transp = CNVT_TOHW(transp, ACCESS_FBINFO(curr.var.transp.length));
+
+ switch (ACCESS_FBINFO(curr.var.bits_per_pixel)) {
+#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB4)
+#ifdef FBCON_HAS_CFB4
+ case 4:
+#endif
+#ifdef FBCON_HAS_CFB8
+ case 8:
+#endif
+ mga_outb(M_DAC_REG, regno);
+ mga_outb(M_DAC_VAL, red);
+ mga_outb(M_DAC_VAL, green);
+ mga_outb(M_DAC_VAL, blue);
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ ACCESS_FBINFO(cmap.cfb16[regno]) =
+ (red << ACCESS_FBINFO(curr.var.red.offset)) |
+ (green << ACCESS_FBINFO(curr.var.green.offset)) |
+ (blue << ACCESS_FBINFO(curr.var.blue.offset)) |
+ (transp << ACCESS_FBINFO(curr.var.transp.offset)); /* for 1:5:5:5 */
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ ACCESS_FBINFO(cmap.cfb24[regno]) =
+ (red << ACCESS_FBINFO(curr.var.red.offset)) |
+ (green << ACCESS_FBINFO(curr.var.green.offset)) |
+ (blue << ACCESS_FBINFO(curr.var.blue.offset));
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ ACCESS_FBINFO(cmap.cfb32[regno]) =
+ (red << ACCESS_FBINFO(curr.var.red.offset)) |
+ (green << ACCESS_FBINFO(curr.var.green.offset)) |
+ (blue << ACCESS_FBINFO(curr.var.blue.offset)) |
+ (transp << ACCESS_FBINFO(curr.var.transp.offset)); /* 8:8:8:8 */
+ break;
+#endif
+ }
+ return 0;
+}
+
+static void do_install_cmap(WPMINFO int con)
+{
+ struct display* dsp;
+
+ DBG("do_install_cmap")
+
+ if (con != ACCESS_FBINFO(currcon))
+ return;
+ if (con >= 0)
+ dsp = fb_display+con;
+ else
+ dsp = ACCESS_FBINFO(fbcon.disp);
+ if (dsp->cmap.len)
+ fb_set_cmap(&dsp->cmap, 1, matrox_setcolreg, &ACCESS_FBINFO(fbcon));
+ else
+ fb_set_cmap(fb_default_cmap(ACCESS_FBINFO(curr.cmap_len)),
+ 1, matrox_setcolreg, &ACCESS_FBINFO(fbcon));
+}
+
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+static void MGA1064_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw, struct display* p) {
+ int i;
+
+ DBG("MGA1064_restore")
+
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+ mga_outb(M_IEN, 0x00);
+ mga_outb(M_CACHEFLUSH, 0x00);
+ DAC1064_restore_1(PMINFO hw, oldhw);
+ vgaHWrestore(PMINFO hw, oldhw);
+ for (i = 0; i < 6; i++)
+ mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
+ DAC1064_restore_2(PMINFO hw, oldhw, p);
+}
+#endif
+
+#ifdef CONFIG_FB_MATROX_G100
+static void MGAG100_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw, struct display* p) {
+ int i;
+
+ DBG("MGAG100_restore")
+
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+ DAC1064_restore_1(PMINFO hw, oldhw);
+ vgaHWrestore(PMINFO hw, oldhw);
+ for (i = 0; i < 6; i++)
+ mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
+ DAC1064_restore_2(PMINFO hw, oldhw, p);
+}
+#endif
+
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw, struct display* p) {
+ int i;
+
+ DBG("Ti3026_restore")
+
+ dprintk(KERN_INFO "EXTVGA regs: ");
+ for (i = 0; i < 6; i++)
+ dprintk("%02X:", hw->CRTCEXT[i]);
+ dprintk("\n");
+
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+
+ vgaHWrestore(PMINFO hw, oldhw);
+ for (i = 0; i < 6; i++)
+ mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
+
+ for (i = 0; i < 21; i++) {
+ outTi3026(PMINFO DACseq[i], hw->DACreg[i]);
+ }
+ if (!oldhw || memcmp(hw->DACclk, oldhw->DACclk, 6)) {
+ /* agrhh... setting up PLL is very slow on Millenium... */
+ /* Mystique PLL is locked in few ms, but Millenium PLL lock takes about 0.15 s... */
+ /* Maybe even we should call schedule() ? */
+
+ outTi3026(PMINFO TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]);
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A);
+ outTi3026(PMINFO TVP3026_XLOOPPLLDATA, 0);
+ outTi3026(PMINFO TVP3026_XPIXPLLDATA, 0);
+
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0x00);
+ for (i = 0; i < 3; i++)
+ outTi3026(PMINFO TVP3026_XPIXPLLDATA, hw->DACclk[i]);
+ /* wait for PLL only if PLL clock requested (always for PowerMode, never for VGA) */
+ if (hw->MiscOutReg & 0x08) {
+ int tmout;
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0x3F);
+ for (tmout = 500000; tmout; --tmout) {
+ if (inTi3026(PMINFO TVP3026_XPIXPLLDATA) & 0x40)
+ break;
+ udelay(10);
+ }
+ if (!tmout)
+ printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
+ else
+ dprintk(KERN_INFO "PixelPLL: %d\n", 500000-tmout);
+ }
+ outTi3026(PMINFO TVP3026_XMEMPLLCTRL, hw->DACreg[POS3026_XMEMPLLCTRL]);
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0x00);
+ for (i = 3; i < 6; i++)
+ outTi3026(PMINFO TVP3026_XLOOPPLLDATA, hw->DACclk[i]);
+ if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[3] & 0xC0) == 0xC0)) {
+ int tmout;
+
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0x3F);
+ for (tmout = 500000; tmout; --tmout) {
+ if (inTi3026(PMINFO TVP3026_XLOOPPLLDATA) & 0x40)
+ break;
+ udelay(10);
+ }
+ if (!tmout)
+ printk(KERN_ERR "matroxfb: Loop PLL not locked after 5 secs\n");
+ else
+ dprintk(KERN_INFO "LoopPLL: %d\n", 500000-tmout);
+ }
+ }
+ if (p && p->conp) {
+ matroxfb_ti3026_createcursor(PMINFO p);
+ i = matroxfb_fastfont_tryset(PMINFO p);
+ } else
+ i = 0;
+ if (i) {
+ ACCESS_FBINFO(curr.putc) = matrox_cfbX_fastputc;
+ ACCESS_FBINFO(curr.putcs) = matrox_cfbX_fastputcs;
+ } else {
+ ACCESS_FBINFO(curr.putc) = matrox_cfbX_putc;
+ ACCESS_FBINFO(curr.putcs) = matrox_cfbX_putcs;
+ }
+
+ dprintk(KERN_DEBUG "3026DACregs ");
+ for (i = 0; i < 21; i++) {
+ dprintk("R%02X=%02X ", DACseq[i], hw->DACreg[i]);
+ if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... ");
+ }
+ dprintk("\n" KERN_DEBUG "DACclk ");
+ for (i = 0; i < 6; i++)
+ dprintk("C%02X=%02X ", i, hw->DACclk[i]);
+ dprintk("\n");
+}
+#endif
+
+static int matroxfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info)
+{
+
+ DBG("matroxfb_get_fix")
+
+#define minfo ((struct matrox_fb_info*)info)
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+ strcpy(fix->id,"MATROX");
+
+ fix->smem_start = (void*)ACCESS_FBINFO(video.base);
+ fix->smem_len = ACCESS_FBINFO(video.len);
+ fix->type = ACCESS_FBINFO(curr.video_type);
+ fix->visual = ACCESS_FBINFO(curr.visual);
+ fix->xpanstep = 8; /* 8 for 8bpp, 4 for 16bpp, 2 for 32bpp */
+ fix->ypanstep = 1;
+ fix->ywrapstep = 0;
+ fix->line_length = (ACCESS_FBINFO(curr.var.xres_virtual) * ACCESS_FBINFO(curr.var.bits_per_pixel)) >> 3;
+ fix->mmio_start = (void*)ACCESS_FBINFO(mmio.base);
+ fix->mmio_len = ACCESS_FBINFO(mmio.len);
+ fix->accel = ACCESS_FBINFO(devflags.accelerator);
+ return 0;
+#undef minfo
+}
+
+static int matroxfb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+
+ DBG("matroxfb_get_var")
+
+ if(con < 0)
+ *var=ACCESS_FBINFO2(info, curr.var);
+ else
+ *var=fb_display[con].var;
+ return 0;
+}
+
+static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+#define minfo ((struct matrox_fb_info*)info)
+ int err;
+ int visual;
+ int cmap_len;
+ struct display* display;
+ int chgvar;
+
+ DBG("matroxfb_set_var")
+
+ if ((err = matroxfb_decode_var(PMINFO var, &visual, &cmap_len)) != 0)
+ return err;
+ switch (var->activate & FB_ACTIVATE_MASK) {
+ case FB_ACTIVATE_TEST: return 0;
+ case FB_ACTIVATE_NXTOPEN: /* ?? */
+ case FB_ACTIVATE_NOW: break; /* continue */
+ default: return -EINVAL; /* unknown */
+ }
+ if (con >= 0) {
+ display = fb_display+con;
+ chgvar = ((display->var.xres != var->xres) ||
+ (display->var.yres != var->yres) ||
+ (display->var.xres_virtual != var->xres_virtual) ||
+ (display->var.yres_virtual != var->yres_virtual) ||
+ (display->var.bits_per_pixel != var->bits_per_pixel) ||
+ memcmp(&display->var.red, &var->red, sizeof(var->red)) ||
+ memcmp(&display->var.green, &var->green, sizeof(var->green)) ||
+ memcmp(&display->var.blue, &var->blue, sizeof(var->blue)));
+ } else {
+ display = ACCESS_FBINFO(fbcon.disp);
+ chgvar = 0;
+ }
+ display->var = *var;
+ /* cmap */
+ display->screen_base = vaddr_va(ACCESS_FBINFO(video.vbase));
+ display->visual = visual;
+ display->type = FB_TYPE_PACKED_PIXELS;
+ display->type_aux = 0;
+ display->ypanstep = 1;
+ display->ywrapstep = 0;
+ display->next_line = display->line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
+ display->can_soft_blank = 1;
+ display->inverse = ACCESS_FBINFO(devflags.inverse);
+ /* conp, fb_info, vrows, cursor_x, cursor_y, fgcol, bgcol */
+ /* next_plane, fontdata, _font*, userfont */
+ initMatrox(PMINFO display); /* dispsw */
+ /* dispsw, scrollmode, yscroll */
+ /* fgshift, bgshift, charmask */
+ if (chgvar && info && info->changevar)
+ info->changevar(con);
+ if (con == ACCESS_FBINFO(currcon)) {
+ unsigned int pos;
+
+ ACCESS_FBINFO(curr.var) = *var;
+ ACCESS_FBINFO(curr.visual) = visual;
+ ACCESS_FBINFO(curr.cmap_len) = cmap_len;
+ ACCESS_FBINFO(curr.final_bppShift) = matroxfb_get_final_bppShift(PMINFO var->bits_per_pixel);
+ if (visual == MX_VISUAL_PSEUDOCOLOR) {
+ int i;
+
+ for (i = 0; i < 16; i++) {
+ int j;
+
+ j = color_table[i];
+ ACCESS_FBINFO(palette[i].red) = default_red[j];
+ ACCESS_FBINFO(palette[i].green) = default_grn[j];
+ ACCESS_FBINFO(palette[i].blue) = default_blu[j];
+ }
+ }
+
+ { struct my_timming mt;
+ struct matrox_hw_state* hw;
+ struct matrox_hw_state* ohw;
+
+ var2my(var, &mt);
+ hw = ACCESS_FBINFO(newhw);
+ ohw = ACCESS_FBINFO(currenthw);
+
+ /* MXoptionReg is not set from scratch */
+ hw->MXoptionReg = ohw->MXoptionReg;
+ /* DACclk[3]..[5] are not initialized with DAC1064 */
+ memcpy(hw->DACclk, ohw->DACclk, sizeof(hw->DACclk));
+ /* others are initialized by init() */
+
+ del_timer(&ACCESS_FBINFO(cursor.timer));
+ ACCESS_FBINFO(cursor.state) = CM_ERASE;
+
+ ACCESS_FBINFO(hw_switch->init(PMINFO hw, &mt));
+ pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32;
+ if (mga_ydstorg(MINFO)) {
+ if (isInterleave(MINFO))
+ pos += mga_ydstorg(MINFO) >> 3;
+ else
+ pos += mga_ydstorg(MINFO) >> 2;
+ }
+
+ hw->CRTC[0x0D] = pos & 0xFF;
+ hw->CRTC[0x0C] = (pos & 0xFF00) >> 8;
+ hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F);
+ ACCESS_FBINFO(hw_switch->restore(PMINFO hw, ohw, display));
+ ACCESS_FBINFO(currenthw) = hw;
+ ACCESS_FBINFO(newhw) = ohw;
+ matrox_cfbX_init(MINFO);
+ do_install_cmap(PMINFO con);
+#if defined(CONFIG_FB_COMPAT_XPMAC)
+ if (console_fb_info == &ACCESS_FBINFO(fbcon)) {
+ int vmode, cmode;
+
+ display_info.width = var->xres;
+ display_info.height = var->yres;
+ display_info.depth = var->bits_per_pixel;
+ display_info.pitch = (var->xres_virtual)*(var->bits_per_pixel)/8;
+ if (mac_var_to_vmode(var, &vmode, &cmode)
+ display_info.mode = 0;
+ else
+ display_info.mode = vmode;
+ strcpy(display_info.name, ACCESS_FBINFO(matrox_name));
+ display_info.fb_address = ACCESS_FBINFO(video.base);
+ /* we should not expose this addresses outside of driver. Every access to DAC must be
+ exclusive locked by spinlock_irq(ACCESS_FBINFO(lock.DAC)) or by turning hardware cursor (flashing) OFF */
+ display_info.cmap_adr_address = ACCESS_FBINFO(mmio.base) + M_DAC_REG;
+ display_info.cmap_data_address = ACCESS_FBINFO(mmio.base) + M_DAC_VAL;
+ display_info.disp_reg_address = ACCESS_FBINFO(mmio.base);
+ }
+#endif /* CONFIG_FB_COMPAT_XPMAC */
+ }
+ }
+ return 0;
+#undef minfo
+}
+
+static int matrox_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+ unsigned *blue, unsigned *transp,
+ struct fb_info *info)
+{
+
+ DBG("matrox_getcolreg")
+
+#define minfo ((struct matrox_fb_info*)info)
+ /*
+ * Read a single color register and split it into colors/transparent.
+ * Return != 0 for invalid regno.
+ */
+
+ if (regno >= ACCESS_FBINFO(curr.cmap_len))
+ return 1;
+
+ *red = ACCESS_FBINFO(palette[regno].red);
+ *green = ACCESS_FBINFO(palette[regno].green);
+ *blue = ACCESS_FBINFO(palette[regno].blue);
+ *transp = ACCESS_FBINFO(palette[regno].transp);
+ return 0;
+#undef minfo
+}
+
+static int matroxfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ struct display* dsp = (con < 0) ? info->disp : fb_display+con;
+
+ DBG("matroxfb_get_cmap")
+
+ if (con == ACCESS_FBINFO2(info, currcon)) /* current console? */
+ return fb_get_cmap(cmap, kspc, matrox_getcolreg, info);
+ else if (dsp->cmap.len) /* non default colormap? */
+ fb_copy_cmap(&dsp->cmap, cmap, kspc ? 0 : 2);
+ else
+ fb_copy_cmap(fb_default_cmap(matroxfb_get_cmap_len(&dsp->var)),
+ cmap, kspc ? 0 : 2);
+ return 0;
+}
+
+static int matroxfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ unsigned int cmap_len;
+ struct display* dsp = (con < 0) ? info->disp : (fb_display + con);
+
+ DBG("matroxfb_set_cmap")
+
+ cmap_len = matroxfb_get_cmap_len(&dsp->var);
+ if (dsp->cmap.len != cmap_len) {
+ int err;
+
+ err = fb_alloc_cmap(&dsp->cmap, cmap_len, 0);
+ if (err)
+ return err;
+ }
+ if (con == ACCESS_FBINFO2(info, currcon)) /* current console? */
+ return fb_set_cmap(cmap, kspc, matrox_setcolreg, info);
+ else
+ fb_copy_cmap(cmap, &dsp->cmap, kspc ? 0 : 1);
+ return 0;
+}
+
+static int matroxfb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg, int con,
+ struct fb_info *info)
+{
+
+ DBG("matroxfb_ioctl")
+
+ return -EINVAL;
+}
+
+static struct fb_ops matroxfb_ops = {
+ matroxfb_open,
+ matroxfb_release,
+ matroxfb_get_fix,
+ matroxfb_get_var,
+ matroxfb_set_var,
+ matroxfb_get_cmap,
+ matroxfb_set_cmap,
+ matroxfb_pan_display,
+ matroxfb_ioctl,
+ NULL /* mmap */
+};
+
+static int matroxfb_switch(int con, struct fb_info *info)
+{
+#define minfo ((struct matrox_fb_info*)info)
+ struct fb_cmap* cmap;
+
+ DBG("matroxfb_switch");
+
+ if (ACCESS_FBINFO(currcon) >= 0) {
+ /* Do we have to save the colormap? */
+ cmap = &fb_display[ACCESS_FBINFO2(info, currcon)].cmap;
+ dprintk(KERN_DEBUG "switch1: con = %d, cmap.len = %d\n", ACCESS_FBINFO2(info, currcon), cmap->len);
+
+ if (cmap->len) {
+ dprintk(KERN_DEBUG "switch1a: %p %p %p %p\n", cmap->red, cmap->green, cmap->blue, cmap->transp);
+ fb_get_cmap(cmap, 1, matrox_getcolreg, info);
+#ifdef DEBUG
+ if (cmap->red) {
+ dprintk(KERN_DEBUG "switch1r: %X\n", cmap->red[0]);
+ }
+#endif
+ }
+ }
+ ACCESS_FBINFO(currcon) = con;
+ ACCESS_FBINFO(currcon_display) = fb_display+con;
+ fb_display[con].var.activate = FB_ACTIVATE_NOW;
+#ifdef DEBUG
+ cmap = &fb_display[con].cmap;
+ dprintk(KERN_DEBUG "switch2: con = %d, cmap.len = %d\n", con, cmap->len);
+ dprintk(KERN_DEBUG "switch2a: %p %p %p %p\n", cmap->red, cmap->green, cmap->blue, cmap->transp);
+ if (fb_display[con].cmap.red) {
+ dprintk(KERN_DEBUG "switch2r: %X\n", cmap->red[0]);
+ }
+#endif
+ matroxfb_set_var(&fb_display[con].var, con, info);
+#ifdef DEBUG
+ dprintk(KERN_DEBUG "switch3: con = %d, cmap.len = %d\n", con, cmap->len);
+ dprintk(KERN_DEBUG "switch3a: %p %p %p %p\n", cmap->red, cmap->green, cmap->blue, cmap->transp);
+ if (fb_display[con].cmap.red) {
+ dprintk(KERN_DEBUG "switch3r: %X\n", cmap->red[0]);
+ }
+#endif
+ return 0;
+#undef minfo
+}
+
+/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
+
+static void matroxfb_blank(int blank, struct fb_info *info)
+{
+#define minfo ((struct matrox_fb_info*)info)
+ int seq;
+ int crtc;
+
+ DBG("matroxfb_blank")
+
+ switch (blank) {
+ case 1: seq = 0x20; crtc = 0x00; break; /* works ??? */
+ case 2: seq = 0x20; crtc = 0x10; break;
+ case 3: seq = 0x20; crtc = 0x20; break;
+ case 4: seq = 0x20; crtc = 0x30; break;
+ default: seq = 0x00; crtc = 0x00; break;
+ }
+ mga_outb(M_SEQ_INDEX, 1);
+ mga_outb(M_SEQ_DATA, (mga_inb(M_SEQ_DATA) & ~0x20) | seq);
+ mga_outb(M_EXTVGA_INDEX, 1);
+ mga_outb(M_EXTVGA_DATA, (mga_inb(M_EXTVGA_DATA) & ~0x30) | crtc);
+#undef minfo
+}
+
+#define RSResolution(X) ((X) & 0x0F)
+#define RS640x400 1
+#define RS640x480 2
+#define RS800x600 3
+#define RS1024x768 4
+#define RS1280x1024 5
+#define RS1600x1200 6
+#define RS768x576 7
+#define RS960x720 8
+#define RS1152x864 9
+#define RS1408x1056 10
+/* B-F */
+static struct { int xres, yres, left, right, upper, lower, hslen, vslen, vfreq; } timmings[] __initdata = {
+ { 640, 400, 48, 16, 39, 8, 96, 2, 70 },
+ { 640, 480, 48, 16, 33, 10, 96, 2, 60 },
+ { 800, 600, 144, 24, 28, 8, 112, 6, 60 },
+ { 1024, 768, 160, 32, 30, 4, 128, 4, 60 },
+ { 1280, 1024, 224, 32, 32, 4, 136, 4, 60 },
+ { 1600, 1200, 272, 48, 32, 5, 152, 5, 60 },
+ { 768, 576, 144, 16, 28, 6, 112, 4, 60 },
+ { 960, 720, 144, 24, 28, 8, 112, 4, 60 },
+ { 1152, 864, 192, 32, 30, 4, 128, 4, 60 },
+ { 1408, 1056, 256, 40, 32, 5, 144, 5, 60 }
+};
+
+#define RSDepth(X) (((X) >> 4) & 0x0F)
+#define RS8bpp 0x1
+#define RS15bpp 0x2
+#define RS16bpp 0x3
+#define RS32bpp 0x4
+#define RS4bpp 0x5
+#define RS24bpp 0x6
+/* 7-F */
+static struct { struct fb_bitfield red, green, blue, transp; int bits_per_pixel; } colors[] __initdata = {
+ { { 0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 8 },
+ { { 10, 5, 0}, { 5, 5, 0}, { 0, 5, 0}, { 15, 1, 0}, 16 },
+ { { 11, 5, 0}, { 6, 5, 0}, { 0, 5, 0}, { 0, 0, 0}, 16 },
+ { { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 24, 8, 0}, 32 },
+ { { 0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 4 },
+ { { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 24 }
+};
+
+#define RSCreate(X,Y) ((X) | ((Y) << 4))
+static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __initdata = {
+/* default must be first */
+#ifdef FBCON_HAS_CFB8
+ { 0x101, RSCreate(RS640x480, RS8bpp ) },
+ { 0x100, RSCreate(RS640x400, RS8bpp ) },
+ { 0x180, RSCreate(RS768x576, RS8bpp ) },
+ { 0x103, RSCreate(RS800x600, RS8bpp ) },
+ { 0x188, RSCreate(RS960x720, RS8bpp ) },
+ { 0x105, RSCreate(RS1024x768, RS8bpp ) },
+ { 0x190, RSCreate(RS1152x864, RS8bpp ) },
+ { 0x107, RSCreate(RS1280x1024, RS8bpp ) },
+ { 0x198, RSCreate(RS1408x1056, RS8bpp ) },
+ { 0x11C, RSCreate(RS1600x1200, RS8bpp ) },
+#endif
+#ifdef FBCON_HAS_CFB4
+ { 0x102, RSCreate(RS800x600, RS4bpp ) },
+ { 0x104, RSCreate(RS1024x768, RS4bpp ) },
+#endif
+#ifdef FBCON_HAS_CFB16
+ { 0x110, RSCreate(RS640x480, RS15bpp) },
+ { 0x181, RSCreate(RS768x576, RS15bpp) },
+ { 0x113, RSCreate(RS800x600, RS15bpp) },
+ { 0x189, RSCreate(RS960x720, RS15bpp) },
+ { 0x116, RSCreate(RS1024x768, RS15bpp) },
+ { 0x191, RSCreate(RS1152x864, RS15bpp) },
+ { 0x119, RSCreate(RS1280x1024, RS15bpp) },
+ { 0x199, RSCreate(RS1408x1056, RS15bpp) },
+ { 0x11D, RSCreate(RS1600x1200, RS15bpp) },
+ { 0x111, RSCreate(RS640x480, RS16bpp) },
+ { 0x182, RSCreate(RS768x576, RS16bpp) },
+ { 0x114, RSCreate(RS800x600, RS16bpp) },
+ { 0x18A, RSCreate(RS960x720, RS16bpp) },
+ { 0x117, RSCreate(RS1024x768, RS16bpp) },
+ { 0x192, RSCreate(RS1152x864, RS16bpp) },
+ { 0x11A, RSCreate(RS1280x1024, RS16bpp) },
+ { 0x19A, RSCreate(RS1408x1056, RS16bpp) },
+ { 0x11E, RSCreate(RS1600x1200, RS16bpp) },
+#endif
+#ifdef FBCON_HAS_CFB24
+ { 0x1B2, RSCreate(RS640x480, RS24bpp) },
+ { 0x184, RSCreate(RS768x576, RS24bpp) },
+ { 0x1B5, RSCreate(RS800x600, RS24bpp) },
+ { 0x18C, RSCreate(RS960x720, RS24bpp) },
+ { 0x1B8, RSCreate(RS1024x768, RS24bpp) },
+ { 0x194, RSCreate(RS1152x864, RS24bpp) },
+ { 0x1BB, RSCreate(RS1280x1024, RS24bpp) },
+ { 0x19C, RSCreate(RS1408x1056, RS24bpp) },
+ { 0x1BF, RSCreate(RS1600x1200, RS24bpp) },
+#endif
+#ifdef FBCON_HAS_CFB32
+ { 0x112, RSCreate(RS640x480, RS32bpp) },
+ { 0x183, RSCreate(RS768x576, RS32bpp) },
+ { 0x115, RSCreate(RS800x600, RS32bpp) },
+ { 0x18B, RSCreate(RS960x720, RS32bpp) },
+ { 0x118, RSCreate(RS1024x768, RS32bpp) },
+ { 0x193, RSCreate(RS1152x864, RS32bpp) },
+ { 0x11B, RSCreate(RS1280x1024, RS32bpp) },
+ { 0x19B, RSCreate(RS1408x1056, RS32bpp) },
+#endif
+ { 0, 0 }};
+
+/* initialized by setup, see explanation at end of file (search for MODULE_PARM_DESC) */
+static unsigned int mem = 0; /* "matrox:mem:xxxxxM" */
+static int option_precise_width = 1; /* cannot be changed, option_precise_width==0 must imply noaccel */
+static int inv24 = 0; /* "matrox:inv24" */
+static int cross4MB = -1; /* "matrox:cross4MB" */
+static int disabled = 0; /* "matrox:disabled" */
+static int noaccel = 0; /* "matrox:noaccel" */
+static int nopan = 0; /* "matrox:nopan" */
+static int no_pci_retry = 0; /* "matrox:nopciretry" */
+static int novga = 0; /* "matrox:novga" */
+static int nobios = 0; /* "matrox:nobios" */
+static int inverse = 0; /* "matrox:inverse" */
+static int hwcursor = 1; /* "matrox:nohwcursor" */
+static int blink = 1; /* "matrox:noblink" */
+static int grayscale = 0; /* "matrox:grayscale" */
+static unsigned int fastfont = 0; /* "matrox:fastfont:xxxxx" */
+static int dev = -1; /* "matrox:dev:xxxxx" */
+static unsigned int vesa = 0x101; /* "matrox:vesa:xxxxx" */
+static unsigned int depth = 0; /* "matrox:depth:xxxxx" */
+static unsigned int xres = 0; /* "matrox:xres:xxxxx" */
+static unsigned int yres = 0; /* "matrox:yres:xxxxx" */
+static unsigned int upper = 0; /* "matrox:upper:xxxxx" */
+static unsigned int lower = 0; /* "matrox:lower:xxxxx" */
+static unsigned int vslen = 0; /* "matrox:vslen:xxxxx" */
+static unsigned int left = 0; /* "matrox:left:xxxxx" */
+static unsigned int right = 0; /* "matrox:right:xxxxx" */
+static unsigned int hslen = 0; /* "matrox:hslen:xxxxx" */
+static unsigned int pixclock = 0; /* "matrox:pixclock:xxxxx" */
+static int sync = -1; /* "matrox:sync:xxxxx" */
+static unsigned int fv = 0; /* "matrox:fv:xxxxx" */
+static unsigned int fh = 0; /* "matrox:fh:xxxxxk" */
+static unsigned int maxclk = 0; /* "matrox:maxclk:xxxxM" */
+static char fontname[64]; /* "matrox:font:xxxxx" */
+
+#ifndef MODULE
+__initfunc(void matroxfb_setup(char *options, int *ints)) {
+ char *this_opt;
+
+ DBG("matroxfb_setup")
+
+ fontname[0] = '\0';
+
+ if (!options || !*options)
+ return;
+
+ for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
+ if (!*this_opt) continue;
+
+ dprintk("matroxfb_setup: option %s\n", this_opt);
+
+ if (!strncmp(this_opt, "dev:", 4))
+ dev = simple_strtoul(this_opt+4, NULL, 0);
+ else if (!strncmp(this_opt, "depth:", 6)) {
+ switch (simple_strtoul(this_opt+6, NULL, 0)) {
+ case 4: depth = RS4bpp; break;
+ case 8: depth = RS8bpp; break;
+ case 15:depth = RS15bpp; break;
+ case 16:depth = RS16bpp; break;
+ case 24:depth = RS24bpp; break;
+ case 32:depth = RS32bpp; break;
+ default:
+ printk(KERN_ERR "matroxfb: unsupported color depth\n");
+ }
+ } else if (!strncmp(this_opt, "xres:", 5))
+ xres = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "yres:", 5))
+ yres = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "vslen:", 6))
+ vslen = simple_strtoul(this_opt+6, NULL, 0);
+ else if (!strncmp(this_opt, "hslen:", 6))
+ hslen = simple_strtoul(this_opt+6, NULL, 0);
+ else if (!strncmp(this_opt, "left:", 5))
+ left = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "right:", 6))
+ right = simple_strtoul(this_opt+6, NULL, 0);
+ else if (!strncmp(this_opt, "upper:", 6))
+ upper = simple_strtoul(this_opt+6, NULL, 0);
+ else if (!strncmp(this_opt, "lower:", 6))
+ lower = simple_strtoul(this_opt+6, NULL, 0);
+ else if (!strncmp(this_opt, "pixclock:", 9))
+ pixclock = simple_strtoul(this_opt+9, NULL, 0);
+ else if (!strncmp(this_opt, "sync:", 5))
+ sync = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "vesa:", 5))
+ vesa = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "font:", 5))
+ strcpy(fontname, this_opt+5);
+ else if (!strncmp(this_opt, "maxclk:", 7))
+ maxclk = simple_strtoul(this_opt+7, NULL, 0);
+ else if (!strncmp(this_opt, "fh:", 3))
+ fh = simple_strtoul(this_opt+3, NULL, 0);
+ else if (!strncmp(this_opt, "fv:", 3))
+ fv = simple_strtoul(this_opt+3, NULL, 0);
+ else if (!strncmp(this_opt, "mem:", 4))
+ mem = simple_strtoul(this_opt+4, NULL, 0);
+ else if (!strncmp(this_opt, "fastfont:", 9))
+ fastfont = simple_strtoul(this_opt+9, NULL, 0);
+ else if (!strcmp(this_opt, "nofastfont")) /* fastfont:N and nofastfont (nofastfont = fastfont:0) */
+ fastfont = 0;
+ else if (!strcmp(this_opt, "disabled")) /* nodisabled does not exist */
+ disabled = 1;
+ else if (!strcmp(this_opt, "enabled")) /* noenabled does not exist */
+ disabled = 0;
+ else {
+ int value = 1;
+
+ if (!strncmp(this_opt, "no", 2)) {
+ value = 0;
+ this_opt += 2;
+ }
+ if (! strcmp(this_opt, "inverse"))
+ inverse = value;
+ else if (!strcmp(this_opt, "accel"))
+ noaccel = !value;
+ else if (!strcmp(this_opt, "pan"))
+ nopan = !value;
+ else if (!strcmp(this_opt, "pciretry"))
+ no_pci_retry = !value;
+ else if (!strcmp(this_opt, "vga"))
+ novga = !value;
+ else if (!strcmp(this_opt, "bios"))
+ nobios = !value;
+ else if (!strcmp(this_opt, "inv24"))
+ inv24 = value;
+ else if (!strcmp(this_opt, "cross4MB"))
+ cross4MB = value;
+ else if (!strcmp(this_opt, "hwcursor"))
+ hwcursor = value;
+ else if (!strcmp(this_opt, "blink"))
+ blink = value;
+ else if (!strcmp(this_opt, "grayscale"))
+ grayscale = value;
+ else {
+ printk(KERN_ERR "matroxfb: unknown parameter %s%s\n", value?"":"no", this_opt);
+ }
+ }
+ }
+}
+#endif
+
+__initfunc(static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int* realOffset, unsigned int *realSize)) {
+ vaddr_t vm;
+ unsigned int offs;
+ unsigned int offs2;
+ unsigned char store;
+ unsigned char bytes[16];
+ unsigned char* tmp;
+ unsigned long cbase;
+ unsigned long mbase;
+ unsigned int clen;
+ unsigned int mlen;
+
+ DBG("matroxfb_getmemory")
+
+ vm = ACCESS_FBINFO(video.vbase);
+ maxSize &= ~0x1FFFFF; /* must be X*2MB (really it must be 2 or X*4MB) */
+ /* at least 2MB */
+ if (maxSize < 0x0200000) return 0;
+ if (maxSize > 0x1000000) maxSize = 0x1000000;
+
+ mga_outb(M_EXTVGA_INDEX, 0x03);
+ mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) | 0x80);
+
+ store = mga_readb(vm, 0x1234);
+ tmp = bytes;
+ for (offs = 0x100000; offs < maxSize; offs += 0x200000)
+ *tmp++ = mga_readb(vm, offs);
+ for (offs = 0x100000; offs < maxSize; offs += 0x200000)
+ mga_writeb(vm, offs, 0x02);
+ if (ACCESS_FBINFO(features.accel.has_cacheflush))
+ mga_outb(M_CACHEFLUSH, 0x00);
+ else
+ mga_writeb(vm, 0x1234, 0x99);
+ cbase = mbase = 0;
+ clen = mlen = 0;
+ for (offs = 0x100000; offs < maxSize; offs += 0x200000) {
+ if (mga_readb(vm, offs) != 0x02)
+ continue;
+ mga_writeb(vm, offs, mga_readb(vm, offs) - 0x02);
+ if (mga_readb(vm, offs))
+ continue;
+ if (offs - 0x100000 == cbase + clen) {
+ clen += 0x200000;
+ } else {
+ cbase = offs - 0x100000;
+ clen = 0x200000;
+ }
+ if ((clen > mlen)
+#ifndef MATROX_2MB_WITH_4MB_ADDON
+ && (cbase == 0)
+#endif
+ ) {
+ mbase = cbase;
+ mlen = clen;
+ }
+ }
+ tmp = bytes;
+ for (offs2 = 0x100000; offs2 < maxSize; offs2 += 0x200000)
+ mga_writeb(vm, offs2, *tmp++);
+ mga_writeb(vm, 0x1234, store);
+
+ mga_outb(M_EXTVGA_INDEX, 0x03);
+ mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) & ~0x80);
+
+ *realOffset = mbase;
+ *realSize = mlen;
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+ ACCESS_FBINFO(interleave) = !(!isMillenium(MINFO) || (mbase & 0x3FFFFF) || (mlen & 0x3FFFFF));
+#endif
+ return 1;
+}
+
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+__initfunc(static int Ti3026_preinit(WPMINFO struct matrox_hw_state* hw)) {
+ static const int vxres_mill2[] = { 512, 640, 768, 800, 832, 960,
+ 1024, 1152, 1280, 1600, 1664, 1920,
+ 2048, 0};
+ static const int vxres_mill1[] = { 640, 768, 800, 960,
+ 1024, 1152, 1280, 1600, 1920,
+ 2048, 0};
+
+ DBG("Ti3026_preinit")
+
+ ACCESS_FBINFO(millenium) = 1;
+ ACCESS_FBINFO(milleniumII) = (ACCESS_FBINFO(pcidev)->device != PCI_DEVICE_ID_MATROX_MIL);
+ ACCESS_FBINFO(capable.cfb4) = 1;
+ ACCESS_FBINFO(capable.vxres) = isMilleniumII(MINFO)?vxres_mill2:vxres_mill1;
+ ACCESS_FBINFO(cursor.timer.function) = matroxfb_ti3026_flashcursor;
+
+ /* preserve VGA I/O, BIOS and PPC */
+ hw->MXoptionReg &= 0xC0000100;
+ hw->MXoptionReg |= 0x002C0000;
+ if (ACCESS_FBINFO(devflags.novga))
+ hw->MXoptionReg &= ~0x00000100;
+ if (ACCESS_FBINFO(devflags.nobios))
+ hw->MXoptionReg &= ~0x40000000;
+ if (ACCESS_FBINFO(devflags.nopciretry))
+ hw->MXoptionReg |= 0x20000000;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+
+ ACCESS_FBINFO(accel.ramdac_rev) = inTi3026(PMINFO TVP3026_XSILICONREV);
+
+ outTi3026(PMINFO TVP3026_XCLKCTRL, TVP3026_XCLKCTRL_SRC_CLK0VGA | TVP3026_XCLKCTRL_CLKSTOPPED);
+ outTi3026(PMINFO TVP3026_XTRUECOLORCTRL, TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR);
+ outTi3026(PMINFO TVP3026_XMUXCTRL, TVP3026_XMUXCTRL_VGA);
+
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A);
+ outTi3026(PMINFO TVP3026_XLOOPPLLDATA, 0x00);
+ outTi3026(PMINFO TVP3026_XPIXPLLDATA, 0x00);
+
+ mga_outb(M_MISC_REG, 0x67);
+
+ outTi3026(PMINFO TVP3026_XMEMPLLCTRL, TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
+
+ mga_outl(M_RESET, 1);
+ udelay(250);
+ mga_outl(M_RESET, 0);
+ udelay(250);
+ mga_outl(M_MACCESS, 0x00008000);
+ udelay(10);
+ return 0;
+}
+
+__initfunc(static void Ti3026_reset(WPMINFO struct matrox_hw_state* hw)) {
+
+ DBG("Ti3026_reset")
+
+ matroxfb_fastfont_init(MINFO);
+
+ ti3026_ramdac_init(PMINFO hw);
+}
+#endif
+
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+static struct matrox_switch matrox_millenium = {
+ Ti3026_preinit, Ti3026_reset, Ti3026_init, Ti3026_restore
+};
+#endif
+
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+static struct matrox_switch matrox_mystique = {
+ MGA1064_preinit, MGA1064_reset, MGA1064_init, MGA1064_restore
+};
+#endif
+
+#ifdef CONFIG_FB_MATROX_G100
+static struct matrox_switch matrox_G100 = {
+ MGAG100_preinit, MGAG100_reset, MGAG100_init, MGAG100_restore
+};
+#endif
+
+struct video_board {
+ int maxvram;
+ int accelID;
+ struct matrox_switch* lowlevel;
+ };
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+static struct video_board vbMillenium __initdata = {0x0800000, FB_ACCEL_MATROX_MGA2064W, &matrox_millenium};
+static struct video_board vbMillenium2 __initdata = {0x1000000, FB_ACCEL_MATROX_MGA2164W, &matrox_millenium};
+static struct video_board vbMillenium2A __initdata = {0x1000000, FB_ACCEL_MATROX_MGA2164W_AGP, &matrox_millenium};
+#endif /* CONFIG_FB_MATROX_MILLENIUM */
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+static struct video_board vbMystique __initdata = {0x0800000, FB_ACCEL_MATROX_MGA1064SG, &matrox_mystique};
+#endif /* CONFIG_FB_MATROX_MYSTIQUE */
+#ifdef CONFIG_FB_MATROX_G100
+static struct video_board vbG100 __initdata = {0x0800000, FB_ACCEL_MATROX_MGAG100, &matrox_G100};
+static struct video_board vbG200 __initdata = {0x1000000, FB_ACCEL_MATROX_MGAG200, &matrox_G100};
+#endif
+
+#define DEVF_VIDEO64BIT 0x01
+#define DEVF_SWAPS 0x02
+#define DEVF_MILLENIUM 0x04
+#define DEVF_MILLENIUM2 0x08
+#define DEVF_CROSS4MB 0x10
+static struct board {
+ unsigned short vendor, device, rev, svid, sid;
+ unsigned int flags;
+ unsigned int maxclk;
+ struct video_board* base;
+ const char* name;
+ } dev_list[] __initdata = {
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL, 0xFF,
+ 0, 0,
+ DEVF_MILLENIUM,
+ 220000,
+ &vbMillenium,
+ "Millennium (PCI)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2, 0xFF,
+ 0, 0,
+ DEVF_MILLENIUM | DEVF_MILLENIUM2 | DEVF_SWAPS,
+ 220000,
+ &vbMillenium2,
+ "Millennium II (PCI)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2_AGP, 0xFF,
+ 0, 0,
+ DEVF_MILLENIUM | DEVF_MILLENIUM2 | DEVF_SWAPS,
+ 250000,
+ &vbMillenium2A,
+ "Millennium II (AGP)"},
+#endif
+#ifdef CONFIG_FB_MATROX_MYSTIQUE
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS, 0x02,
+ 0, 0,
+ DEVF_VIDEO64BIT,
+ 180000,
+ &vbMystique,
+ "Mystique (PCI)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS, 0xFF,
+ 0, 0,
+ DEVF_VIDEO64BIT | DEVF_SWAPS,
+ 220000,
+ &vbMystique,
+ "Mystique 220 (PCI)"},
+#endif
+#ifdef CONFIG_FB_MATROX_G100
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100, 0xFF,
+ PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MGA_G100_PCI,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
+ &vbG100,
+ "MGA-G100 (PCI)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100, 0xFF,
+ 0, 0,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
+ &vbG100,
+ "unknown G100 (PCI)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF,
+ PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_GENERIC,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
+ &vbG100,
+ "MGA-G100 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF,
+ PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MGA_G100_AGP,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
+ &vbG100,
+ "MGA-G100 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF,
+ PCI_SS_VENDOR_ID_SIEMENS_NIXDORF, PCI_SS_ID_SIEMENS_MGA_G100_AGP,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
+ &vbG100,
+ "MGA-G100 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF,
+ PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
+ &vbG100,
+ "Productiva G100 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF,
+ 0, 0,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
+ &vbG100,
+ "unknown G100 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
+ PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_GENERIC,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
+ &vbG200,
+ "MGA-G200 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
+ PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
+ &vbG200,
+ "Mystique G200 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
+ PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MILLENIUM_G200_AGP,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 250000,
+ &vbG200,
+ "Millennium G200 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
+ PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MARVEL_G200_AGP,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
+ &vbG200,
+ "Marvel G200 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
+ PCI_SS_VENDOR_ID_SIEMENS_NIXDORF, PCI_SS_ID_SIEMENS_MGA_G200_AGP,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
+ &vbG200,
+ "MGA-G200 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
+ 0, 0,
+ DEVF_VIDEO64BIT | DEVF_SWAPS,
+ 220000,
+ &vbG200,
+ "unknown G200 (AGP)"},
+#endif
+ {0, 0, 0xFF,
+ 0, 0,
+ 0,
+ 0,
+ NULL,
+ NULL}};
+
+__initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
+ unsigned long ctrlptr_phys = 0;
+ unsigned long video_base_phys = 0;
+ unsigned int memsize;
+ struct matrox_hw_state* hw = ACCESS_FBINFO(currenthw);
+
+ DBG("initMatrox2")
+
+ /* set default values... */
+ vesafb_defined.accel_flags = FB_ACCELF_TEXT;
+
+ ACCESS_FBINFO(hw_switch) = b->base->lowlevel;
+ ACCESS_FBINFO(devflags.accelerator) = b->base->accelID;
+ ACCESS_FBINFO(max_pixel_clock) = b->maxclk;
+
+ printk(KERN_INFO "matroxfb: Matrox %s detected\n", b->name);
+ ACCESS_FBINFO(devflags.video64bits) = b->flags & DEVF_VIDEO64BIT;
+ if (ACCESS_FBINFO(capable.cross4MB) < 0)
+ ACCESS_FBINFO(capable.cross4MB) = b->flags & DEVF_CROSS4MB;
+ if (b->flags & DEVF_SWAPS) {
+ ctrlptr_phys = ACCESS_FBINFO(pcidev)->base_address[1] & ~0x3FFF;
+ video_base_phys = ACCESS_FBINFO(pcidev)->base_address[0] & ~0x7FFFFF; /* aligned at 8MB (or 16 for Mill 2) */
+ } else {
+ ctrlptr_phys = ACCESS_FBINFO(pcidev)->base_address[0] & ~0x3FFF;
+ video_base_phys = ACCESS_FBINFO(pcidev)->base_address[1] & ~0x7FFFFF; /* aligned at 8MB */
+ }
+ if (!ctrlptr_phys) {
+ printk(KERN_ERR "matroxfb: control registers are not available, matroxfb disabled\n");
+ return -EINVAL;
+ }
+ if (!video_base_phys) {
+ printk(KERN_ERR "matroxfb: video RAM is not available in PCI address space, matroxfb disabled\n");
+ return -EINVAL;
+ }
+ if (mga_ioremap(ctrlptr_phys, 16384, MGA_IOREMAP_MMIO, &ACCESS_FBINFO(mmio.vbase))) {
+ printk(KERN_ERR "matroxfb: cannot ioremap(%lX, 16384), matroxfb disabled\n", ctrlptr_phys);
+ return -ENOMEM;
+ }
+ ACCESS_FBINFO(mmio.base) = ctrlptr_phys;
+ ACCESS_FBINFO(mmio.len) = 16384;
+ memsize = b->base->maxvram;
+/* convert mem (autodetect k, M) */
+ if (mem < 1024) mem *= 1024;
+ if (mem < 0x00100000) mem *= 1024;
+
+ if (mem && (mem < memsize))
+ memsize = mem;
+ ACCESS_FBINFO(video.base) = video_base_phys;
+ if (mga_ioremap(video_base_phys, memsize, MGA_IOREMAP_FB, &ACCESS_FBINFO(video.vbase))) {
+ printk(KERN_ERR "matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n",
+ video_base_phys, memsize);
+ mga_iounmap(ACCESS_FBINFO(mmio.vbase));
+ return -ENOMEM;
+ }
+ {
+ u_int32_t cmd;
+ u_int32_t mga_option;
+
+ /* Matrox MilleniumII is deactivated on bootup, but address
+ regions are assigned to board. So we have to enable it */
+ pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, &mga_option);
+ pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_COMMAND, &cmd);
+ mga_option &= 0x7FFFFFFF; /* clear BIG_ENDIAN */
+ if ((cmd & PCI_COMMAND_MEMORY) !=
+ PCI_COMMAND_MEMORY) {
+ /* But if we have to enable it, we have probably to
+ disable VGA I/O and BIOS... Sure? */
+ dprintk(KERN_WARNING "matroxfb: PCI BIOS did not enable device!\n");
+ cmd = (cmd | PCI_COMMAND_MEMORY) & ~PCI_COMMAND_VGA_PALETTE;
+ mga_option &= 0xBFFFFEFF;
+ ACCESS_FBINFO(devflags.novga) = 1;
+ ACCESS_FBINFO(devflags.nobios) = 1;
+ }
+ mga_option |= MX_OPTION_BSWAP;
+ if (pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, NULL)) {
+ if (!(mga_option & 0x20000000) && !ACCESS_FBINFO(devflags.nopciretry)) {
+ printk(KERN_WARNING "matroxfb: Disabling PCI retries due to i82437 present\n");
+ }
+ mga_option |= 0x20000000;
+ ACCESS_FBINFO(devflags.nopciretry) = 1;
+ }
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_COMMAND, cmd);
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mga_option);
+ hw->MXoptionReg = mga_option;
+
+ /* select non-DMA memory for PCI_MGA_DATA, otherwise dump of PCI cfg space can lock PCI bus */
+ /* maybe preinit() candidate, but it is same... for all devices... at this time... */
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MGA_INDEX, 0x00003C00);
+ }
+
+ if (ACCESS_FBINFO(hw_switch)->preinit(PMINFO hw)) {
+ mga_iounmap(ACCESS_FBINFO(video.vbase));
+ mga_iounmap(ACCESS_FBINFO(mmio.vbase));
+ return -ENXIO;
+ }
+
+ {
+ unsigned int offs;
+
+ if (!matroxfb_getmemory(PMINFO memsize, &offs, &ACCESS_FBINFO(video.len)) || !ACCESS_FBINFO(video.len)) {
+ printk(KERN_ERR "matroxfb: cannot determine memory size\n");
+ mga_iounmap(ACCESS_FBINFO(video.vbase));
+ mga_iounmap(ACCESS_FBINFO(mmio.vbase));
+ return -ENOMEM;
+ }
+#ifdef MATROX_2MB_WITH_4MB_ADDON
+#ifdef FBCON_HAS_CFB24
+ {
+ unsigned int end = offs + ACCESS_FBINFO(video.len);
+
+ if (offs)
+ offs = ((offs - 1) / (4096 * 3) + 1) * 4096 * 3;
+ ACCESS_FBINFO(video.len) = end - offs;
+ }
+#endif
+ mga_ydstorg(MINFO) = offs;
+ video_base_phys += offs;
+#endif
+ }
+ ACCESS_FBINFO(curr.video_type) = FB_TYPE_PACKED_PIXELS;
+ ACCESS_FBINFO(currcon) = -1;
+ ACCESS_FBINFO(currcon_display) = NULL;
+ mga_iounmap(ACCESS_FBINFO(video.vbase));
+ ACCESS_FBINFO(video.base) = video_base_phys;
+ if (mga_ioremap(video_base_phys, ACCESS_FBINFO(video.len), MGA_IOREMAP_FB, &ACCESS_FBINFO(video.vbase))) {
+ printk(KERN_ERR "matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n",
+ video_base_phys, ACCESS_FBINFO(video.len));
+ mga_iounmap(ACCESS_FBINFO(mmio.vbase));
+ return -ENOMEM;
+ }
+ ACCESS_FBINFO(video.len_usable) = ACCESS_FBINFO(video.len);
+ if (ACCESS_FBINFO(video.len_usable) > 0x08000000)
+ ACCESS_FBINFO(video.len_usable) = 0x08000000;
+#ifdef CONFIG_MTRR
+ ACCESS_FBINFO(mtrr.vram) = mtrr_add(video_base_phys, ACCESS_FBINFO(video.len), MTRR_TYPE_WRCOMB, 1);
+ ACCESS_FBINFO(mtrr.vram_valid) = 1;
+ printk(KERN_INFO "matroxfb: MTRR's turned on\n");
+#endif /* CONFIG_MTRR */
+
+/* validate params, autodetect k, M */
+ if (fh < 1000) fh *= 1000; /* 1kHz minimum */
+ if (maxclk < 1000) maxclk *= 1000; /* kHz -> Hz, MHz -> kHz */
+ if (maxclk < 1000000) maxclk *= 1000; /* kHz -> Hz, 1MHz minimum */
+ vesa &= 0x1DFF; /* mask out clearscreen, acceleration and so on */
+
+ ACCESS_FBINFO(fbcon.monspecs.hfmin) = 0;
+ ACCESS_FBINFO(fbcon.monspecs.hfmax) = fh;
+ ACCESS_FBINFO(fbcon.monspecs.vfmin) = 0;
+ ACCESS_FBINFO(fbcon.monspecs.vfmax) = fv;
+ ACCESS_FBINFO(fbcon.monspecs.dpms) = 0; /* TBD */
+
+/* static settings */
+ for (RSptr = vesamap; RSptr->vesa; RSptr++) {
+ if (RSptr->vesa == vesa) break;
+ }
+ if (!RSptr->vesa) {
+ printk(KERN_ERR "Invalid vesa mode 0x%04X\n", vesa);
+ RSptr = vesamap;
+ }
+ {
+ int res = RSResolution(RSptr->info)-1;
+ if (!left)
+ left = timmings[res].left;
+ if (!xres)
+ xres = timmings[res].xres;
+ if (!right)
+ right = timmings[res].right;
+ if (!hslen)
+ hslen = timmings[res].hslen;
+ if (!upper)
+ upper = timmings[res].upper;
+ if (!yres)
+ yres = timmings[res].yres;
+ if (!lower)
+ lower = timmings[res].lower;
+ if (!vslen)
+ vslen = timmings[res].vslen;
+ if (!(fv||fh||maxclk||pixclock))
+ fv = timmings[res].vfreq;
+ if (!depth)
+ depth = RSDepth(RSptr->info);
+ }
+ if (sync == -1) {
+ sync = 0;
+ if (yres < 480)
+ sync |= FB_SYNC_VERT_HIGH_ACT;
+ }
+ if (xres < 320)
+ xres = 320;
+ if (xres > 2048)
+ xres = 2048;
+ if (yres < 200)
+ yres = 200;
+ if (yres > 2048)
+ yres = 2048;
+ {
+ unsigned int tmp;
+
+ if (fv) {
+ tmp = fv * (upper + yres + lower + vslen);
+ if ((tmp < fh) || (fh == 0)) fh = tmp;
+ }
+ if (fh) {
+ tmp = fh * (left + xres + right + hslen);
+ if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp;
+ }
+ maxclk = (maxclk + 499) / 500;
+ if (maxclk) {
+ tmp = (2000000000 + maxclk) / maxclk;
+ if (tmp > pixclock) pixclock = tmp;
+ }
+ }
+ vesafb_defined.red = colors[depth-1].red;
+ vesafb_defined.green = colors[depth-1].green;
+ vesafb_defined.blue = colors[depth-1].blue;
+ vesafb_defined.bits_per_pixel = colors[depth-1].bits_per_pixel;
+ if (pixclock < 2000) /* > 500MHz */
+ pixclock = 4000; /* 250MHz */
+ if (pixclock > 1000000)
+ pixclock = 1000000; /* 1MHz */
+ vesafb_defined.xres = xres;
+ vesafb_defined.yres = yres;
+ vesafb_defined.xoffset = 0;
+ vesafb_defined.yoffset = 0;
+ vesafb_defined.grayscale = grayscale;
+ vesafb_defined.pixclock = pixclock;
+ vesafb_defined.left_margin = left;
+ vesafb_defined.right_margin = right;
+ vesafb_defined.hsync_len = hslen;
+ vesafb_defined.upper_margin = upper;
+ vesafb_defined.lower_margin = lower;
+ vesafb_defined.vsync_len = vslen;
+ vesafb_defined.sync = sync;
+ vesafb_defined.vmode = 0;
+
+ if (!ACCESS_FBINFO(devflags.novga))
+ request_region(0x3C0, 32, "matrox");
+ if (noaccel)
+ vesafb_defined.accel_flags &= ~FB_ACCELF_TEXT;
+
+ strcpy(ACCESS_FBINFO(fbcon.modename), "MATROX VGA");
+ ACCESS_FBINFO(fbcon.changevar) = NULL;
+ ACCESS_FBINFO(fbcon.node) = -1;
+ ACCESS_FBINFO(fbcon.fbops) = &matroxfb_ops;
+ ACCESS_FBINFO(fbcon.disp) = d;
+ ACCESS_FBINFO(fbcon.switch_con) = &matroxfb_switch;
+ ACCESS_FBINFO(fbcon.updatevar) = &matroxfb_updatevar;
+ ACCESS_FBINFO(fbcon.blank) = &matroxfb_blank;
+ ACCESS_FBINFO(fbcon.flags) = FBINFO_FLAG_DEFAULT;
+ ACCESS_FBINFO(hw_switch->reset(PMINFO hw));
+ ACCESS_FBINFO(video.len_usable) &= PAGE_MASK;
+#if defined(CONFIG_FB_COMPAT_XPMAC)
+ strcpy(ACCESS_FBINFO(matrox_name), "MTRX,"); /* OpenFirmware naming convension */
+ strcat(ACCESS_FBINFO(matrox_name), b->name);
+ if (!console_fb_info)
+ console_fb_info = &ACCESS_FBINFO(fbcon);
+#endif
+#if defined(CONFIG_PPC)
+ if ((xres <= 640) && (yres <= 480)) {
+ struct fb_var_screeninfo var;
+
+ if (default_vmode == VMODE_NVRAM)
+ default_vmode = nvram_read_byte(NV_VMODE);
+ 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.accel_flags = vesafb_defined.accel_flags;
+ vesafb_defined = var;
+ }
+ }
+#endif
+ {
+ int pixel_size = vesafb_defined.bits_per_pixel;
+ int avamem = ACCESS_FBINFO(video.len_usable);
+
+ vesafb_defined.xres_virtual = matroxfb_pitch_adjust(PMINFO xres, pixel_size);
+ if (nopan) {
+ vesafb_defined.yres_virtual = vesafb_defined.yres;
+ } else {
+ vesafb_defined.yres_virtual = (avamem * 8 / (pixel_size * vesafb_defined.xres_virtual)) & ~0x1F;
+ if (vesafb_defined.yres_virtual < vesafb_defined.yres)
+ vesafb_defined.yres_virtual = vesafb_defined.yres;
+ }
+ }
+ if (matroxfb_set_var(&vesafb_defined, -2, &ACCESS_FBINFO(fbcon))) {
+ printk(KERN_ERR "matroxfb: cannot set required parameters\n");
+ return -EINVAL;
+ }
+
+ printk(KERN_INFO "matroxfb: %dx%dx%dbpp (virtual: %dx%d)\n",
+ vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel,
+ vesafb_defined.xres_virtual, vesafb_defined.yres_virtual);
+ printk(KERN_INFO "matroxfb: framebuffer at 0x%lX, mapped to 0x%p, size %d\n",
+ ACCESS_FBINFO(video.base), vaddr_va(ACCESS_FBINFO(video.vbase)), ACCESS_FBINFO(video.len));
+
+/* We do not have to set currcon to 0... register_framebuffer do it for us on first console
+ * and we do not want currcon == 0 for subsequent framebuffers */
+
+ if (register_framebuffer(&ACCESS_FBINFO(fbcon)) < 0)
+ return -EINVAL;
+ printk("fb%d: %s frame buffer device\n",
+ GET_FB_IDX(ACCESS_FBINFO(fbcon.node)), ACCESS_FBINFO(fbcon.modename));
+ if (ACCESS_FBINFO(currcon) < 0) {
+ /* there is no console on this fb... but we have to initialize hardware
+ * until someone tells me what is proper thing to do */
+ printk(KERN_INFO "fb%d: initializing hardware\n",
+ GET_FB_IDX(ACCESS_FBINFO(fbcon.node)));
+ matroxfb_set_var(&vesafb_defined, -1, &ACCESS_FBINFO(fbcon));
+ }
+ return 0;
+}
+
+static struct matrox_fb_info* fb_list = NULL;
+
+__initfunc(static int matrox_init(void)) {
+ struct pci_dev* pdev = NULL;
+
+ DBG("matrox_init")
+
+ if (disabled)
+ return -ENXIO;
+ while ((pdev = pci_find(pdev)) != NULL) {
+ struct board* b;
+ u_int8_t rev;
+ u_int16_t svid;
+ u_int16_t sid;
+
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+ pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &svid);
+ pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &sid);
+ for (b = dev_list; b->vendor; b++) {
+ if ((b->vendor != pdev->vendor) || (b->device != pdev->device) || (b->rev < rev)) continue;
+ if (b->svid)
+ if ((b->svid != svid) || (b->sid != sid)) continue;
+ if (dev <= 0) {
+ struct matrox_fb_info* minfo;
+ struct display* d;
+ int err;
+
+#ifdef CONFIG_FB_MATROX_MULTIHEAD
+ minfo = (struct matrox_fb_info*)kmalloc(sizeof(*minfo), GFP_KERNEL);
+ if (minfo) {
+ d = (struct display*)kmalloc(sizeof(*d), GFP_KERNEL);
+ if (d) {
+#else
+ minfo = &global_mxinfo;
+ d = &global_disp;
+#endif
+ memset(MINFO, 0, sizeof(*MINFO));
+ memset(d, 0, sizeof(*d));
+
+ ACCESS_FBINFO(currenthw) = &ACCESS_FBINFO(hw1);
+ ACCESS_FBINFO(newhw) = &ACCESS_FBINFO(hw2);
+ ACCESS_FBINFO(pcidev) = pdev;
+ /* CMDLINE */
+ memcpy(ACCESS_FBINFO(fbcon.fontname), fontname, sizeof(ACCESS_FBINFO(fbcon.fontname)));
+ /* DEVFLAGS */
+ ACCESS_FBINFO(devflags.inverse) = inverse;
+ ACCESS_FBINFO(devflags.novga) = novga;
+ ACCESS_FBINFO(devflags.nobios) = nobios;
+ ACCESS_FBINFO(devflags.nopciretry) = no_pci_retry;
+ ACCESS_FBINFO(devflags.mga_24bpp_fix) = inv24;
+ ACCESS_FBINFO(devflags.precise_width) = option_precise_width;
+ ACCESS_FBINFO(devflags.hwcursor) = hwcursor;
+ ACCESS_FBINFO(devflags.blink) = blink;
+ ACCESS_FBINFO(capable.cross4MB) = cross4MB;
+
+ ACCESS_FBINFO(fastfont.size) = fastfont;
+
+ ACCESS_FBINFO(cursor.state) = CM_ERASE;
+ ACCESS_FBINFO(cursor.timer.prev) = ACCESS_FBINFO(cursor.timer.next) = NULL;
+ ACCESS_FBINFO(cursor.timer.data) = (unsigned long)MINFO;
+ spin_lock_init(&ACCESS_FBINFO(lock.DAC));
+
+ err = initMatrox2(PMINFO d, b);
+ if (!err) {
+ ACCESS_FBINFO(next_fb) = fb_list;
+ fb_list = MINFO;
+#ifdef CONFIG_FB_MATROX_MULTIHEAD
+ goto leave;
+#else
+ return 0;
+#endif
+ }
+#ifdef CONFIG_FB_MATROX_MULTIHEAD
+ kfree(d);
+ }
+ kfree(minfo);
+ }
+#endif
+ }
+#ifdef CONFIG_FB_MATROX_MULTIHEAD
+leave:;
+#endif
+ if (dev == 0) return 0;
+ if (dev > 0) dev--;
+ break;
+ }
+ }
+ return 0;
+}
+
+#ifndef MODULE
+__initfunc(void matroxfb_init(void))
+{
+ DBG("matroxfb_init")
+#if defined(CONFIG_FB_OF)
+/* Nothing to do, must be called from offb */
+#else
+ matrox_init();
+#endif
+}
+
+#if defined(CONFIG_FB_OF)
+__initfunc(void matrox_of_init(struct device_node *dp)) {
+ DBG("matrox_of_init");
+ matrox_init();
+}
+#endif /* CONFIG_FB_OF */
+
+#else
+
+MODULE_AUTHOR("(c) 1998 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200");
+MODULE_PARM(mem, "i");
+MODULE_PARM_DESC(mem, "Size of available memory in MB, KB or B (2,4,8,12,16MB, default=autodetect)");
+MODULE_PARM(disabled, "i");
+MODULE_PARM_DESC(disabled, "Disabled (0 or 1=disabled), meaningless for module (default=0)");
+MODULE_PARM(noaccel, "i");
+MODULE_PARM_DESC(noaccel, "Do not use accelerating engine (0 or 1=disabled) (default=0)");
+MODULE_PARM(nopan, "i");
+MODULE_PARM_DESC(nopan, "Disable pan on startup (0 or 1=disabled) (default=0)");
+MODULE_PARM(no_pci_retry, "i");
+MODULE_PARM_DESC(no_pci_retry, "PCI retries enabled (0 or 1=disabled) (default=0)");
+MODULE_PARM(novga, "i");
+MODULE_PARM_DESC(novga, "VGA I/O (0x3C0-0x3DF) disabled (0 or 1=disabled) (default=0)");
+MODULE_PARM(nobios, "i");
+MODULE_PARM_DESC(nobios, "Disables ROM BIOS (0 or 1=disabled) (default=do not change BIOS state)");
+MODULE_PARM(inv24, "i");
+MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)");
+MODULE_PARM(inverse, "i");
+MODULE_PARM_DESC(inverse, "Inverse (0 or 1) (default=0)");
+#ifdef CONFIG_FB_MATROX_MULTIHEAD
+MODULE_PARM(dev, "i");
+MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=all working)");
+#else
+MODULE_PARM(dev, "i");
+MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=first working)");
+#endif
+MODULE_PARM(vesa, "i");
+MODULE_PARM_DESC(vesa, "Startup videomode (0x100-0x1FF) (default=0x101)");
+MODULE_PARM(xres, "i");
+MODULE_PARM_DESC(xres, "Horizontal resolutioni (px), overrides xres from vesa (default=vesa)");
+MODULE_PARM(yres, "i");
+MODULE_PARM_DESC(yres, "Vertical resolution (scans), overrides yres from vesa (default=vesa)");
+MODULE_PARM(upper, "i");
+MODULE_PARM_DESC(upper, "Upper blank space (scans), overrides upper from vesa (default=vesa)");
+MODULE_PARM(lower, "i");
+MODULE_PARM_DESC(lower, "Lower blank space (scans), overrides lower from vesa (default=vesa)");
+MODULE_PARM(vslen, "i");
+MODULE_PARM_DESC(vslen, "Vertical sync length (scans), overrides lower from vesa (default=vesa)");
+MODULE_PARM(left, "i");
+MODULE_PARM_DESC(left, "Left blank space (px), overrides left from vesa (default=vesa)");
+MODULE_PARM(right, "i");
+MODULE_PARM_DESC(right, "Right blank space (px), overrides right from vesa (default=vesa)");
+MODULE_PARM(hslen, "i");
+MODULE_PARM_DESC(hslen, "Horizontal sync length (px), overrides hslen from vesa (default=vesa)");
+MODULE_PARM(pixclock, "i");
+MODULE_PARM_DESC(pixclock, "Pixelclock (ns), overrides pixclock from vesa (default=vesa)");
+MODULE_PARM(sync, "i");
+MODULE_PARM_DESC(sync, "Sync polarity, overrides sync from vesa (default=vesa)");
+MODULE_PARM(depth, "i");
+MODULE_PARM_DESC(depth, "Color depth (8,15,16,24,32) (default=vesa)");
+MODULE_PARM(maxclk, "i");
+MODULE_PARM_DESC(maxclk, "Startup maximal clock, 0-999MHz, 1000-999999kHz, 1000000-INF Hz");
+MODULE_PARM(fh, "i");
+MODULE_PARM_DESC(fh, "Startup horizontal frequency, 0-999kHz, 1000-INF Hz");
+MODULE_PARM(fv, "i");
+MODULE_PARM_DESC(fv, "Startup vertical frequency, 0-INF Hz\n"
+"You should specify \"fv:max_monitor_vsync,fh:max_monitor_hsync,maxclk:max_monitor_dotclock\"\n");
+MODULE_PARM(hwcursor, "i");
+MODULE_PARM_DESC(hwcursor, "Enables hardware cursor (0 or 1) (default=0)");
+MODULE_PARM(blink, "i");
+MODULE_PARM_DESC(blink, "Enables hardware cursor blinking (0 or 1) (default=1)");
+MODULE_PARM(fastfont, "i");
+MODULE_PARM_DESC(fastfont, "Specifies, how much memory should be used for font data (0, 1024-65536 are reasonable) (default=0)");
+MODULE_PARM(grayscale, "i");
+MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)");
+MODULE_PARM(cross4MB, "i");
+MODULE_PARM_DESC(cross4MB, "Specifies that 4MB boundary can be in middle of line. It cannot at least on Millennium (I/II).");
+
+__initfunc(int init_module(void)) {
+
+ DBG("init_module")
+
+#ifdef DEBUG
+ if( disabled )
+ return 0;
+#endif /* DEBUG */
+
+ if (depth == 0)
+ depth = 0; /* default */
+ else if (depth == 4)
+ depth = RS4bpp;
+ else if (depth == 8)
+ depth = RS8bpp;
+ else if (depth == 15)
+ depth = RS15bpp;
+ else if (depth == 16)
+ depth = RS16bpp;
+ else if (depth == 24)
+ depth = RS24bpp;
+ else if (depth == 32)
+ depth = RS32bpp;
+ else {
+ printk(KERN_ERR "matroxfb: depth %d is not supported, using default\n", depth);
+ depth = 0;
+ }
+ matrox_init();
+ if (!fb_list) return -ENXIO;
+ return 0;
+}
+
+void cleanup_module(void) {
+
+ DBG("cleanup_module")
+
+#ifdef DEBUG
+ if( disabled )
+ return;
+#endif /* DEBUG */
+
+ while (fb_list) {
+ struct matrox_fb_info* minfo;
+
+ minfo = fb_list;
+ fb_list = fb_list->next_fb;
+ unregister_framebuffer(&ACCESS_FBINFO(fbcon));
+ del_timer(&ACCESS_FBINFO(cursor.timer));
+#ifdef CONFIG_MTRR
+ if (ACCESS_FBINFO(mtrr.vram_valid))
+ mtrr_del(ACCESS_FBINFO(mtrr.vram), ACCESS_FBINFO(video.base), ACCESS_FBINFO(video.len));
+#endif
+ mga_iounmap(ACCESS_FBINFO(mmio.vbase));
+ mga_iounmap(ACCESS_FBINFO(video.vbase));
+#ifdef CONFIG_FB_MATROX_MULTIHEAD
+ kfree_s(ACCESS_FBINFO(fbcon.disp), sizeof(struct display));
+ kfree_s(minfo, sizeof(struct matrox_fb_info));
+#endif
+ }
+}
+#endif /* MODULE */
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/video/mdacon.c b/drivers/video/mdacon.c
new file mode 100644
index 000000000..ea5afadd8
--- /dev/null
+++ b/drivers/video/mdacon.c
@@ -0,0 +1,617 @@
+/*
+ * linux/drivers/video/mdacon.c -- Low level MDA based console driver
+ *
+ * (c) 1998 Andrew Apted <ajapted@netspace.net.au>
+ *
+ * including portions (c) 1995-1998 Patrick Caulfield.
+ *
+ * This file is based on the VGA console driver (vgacon.c):
+ *
+ * Created 28 Sep 1997 by Geert Uytterhoeven
+ *
+ * Rewritten by Martin Mares <mj@ucw.cz>, July 1998
+ *
+ * and on the old console.c, vga.c and vesa_blank.c drivers:
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * 1995 Jay Estabrook
+ *
+ * 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/types.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/console_struct.h>
+#include <linux/string.h>
+#include <linux/kd.h>
+#include <linux/malloc.h>
+#include <linux/vt_kern.h>
+#include <linux/vt_buffer.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/vga.h>
+
+
+/* description of the hardware layout */
+
+static unsigned long mda_vram_base; /* Base of video memory */
+static unsigned long mda_vram_len; /* Size of video memory */
+static unsigned int mda_num_columns; /* Number of text columns */
+static unsigned int mda_num_lines; /* Number of text lines */
+
+static unsigned int mda_index_port; /* Register select port */
+static unsigned int mda_value_port; /* Register value port */
+static unsigned int mda_mode_port; /* Mode control port */
+static unsigned int mda_status_port; /* Status and Config port */
+static unsigned int mda_gfx_port; /* Graphics control port */
+
+/* current hardware state */
+
+static int mda_origin_loc=-1;
+static int mda_cursor_loc=-1;
+static int mda_cursor_size_from=-1;
+static int mda_cursor_size_to=-1;
+
+static enum { TYPE_MDA, TYPE_HERC, TYPE_HERCPLUS, TYPE_HERCCOLOR } mda_type;
+static char *mda_type_name;
+
+/* console information */
+
+static int mda_first_vc = 13;
+static int mda_last_vc = 16;
+
+static struct vc_data *mda_display_fg = NULL;
+
+#ifdef MODULE_PARM
+MODULE_PARM(mda_first_vc, "1-255i");
+MODULE_PARM(mda_last_vc, "1-255i");
+#endif
+
+
+/* MDA register values
+ */
+
+#define MDA_CURSOR_BLINKING 0x00
+#define MDA_CURSOR_OFF 0x20
+#define MDA_CURSOR_SLOWBLINK 0x60
+
+#define MDA_MODE_GRAPHICS 0x02
+#define MDA_MODE_VIDEO_EN 0x08
+#define MDA_MODE_BLINK_EN 0x20
+#define MDA_MODE_GFX_PAGE1 0x80
+
+#define MDA_STATUS_HSYNC 0x01
+#define MDA_STATUS_VSYNC 0x80
+#define MDA_STATUS_VIDEO 0x08
+
+#define MDA_CONFIG_COL132 0x08
+#define MDA_GFX_MODE_EN 0x01
+#define MDA_GFX_PAGE_EN 0x02
+
+
+/*
+ * MDA could easily be classified as "pre-dinosaur hardware".
+ */
+
+static void write_mda_b(unsigned int val, unsigned char reg)
+{
+ unsigned long flags;
+
+ save_flags(flags); cli();
+
+ outb_p(reg, mda_index_port);
+ outb_p(val, mda_value_port);
+
+ restore_flags(flags);
+}
+
+static void write_mda_w(unsigned int val, unsigned char reg)
+{
+ unsigned long flags;
+
+ save_flags(flags); cli();
+
+ outb_p(reg, mda_index_port); outb_p(val >> 8, mda_value_port);
+ outb_p(reg+1, mda_index_port); outb_p(val & 0xff, mda_value_port);
+
+ restore_flags(flags);
+}
+
+static int test_mda_b(unsigned char val, unsigned char reg)
+{
+ unsigned long flags;
+
+ save_flags(flags); cli();
+
+ outb_p(reg, mda_index_port);
+ outb (val, mda_value_port);
+
+ udelay(20); val = (inb_p(mda_value_port) == val);
+
+ restore_flags(flags);
+
+ return val;
+}
+
+static inline void mda_set_origin(unsigned int location)
+{
+ if (mda_origin_loc == location)
+ return;
+
+ write_mda_w(location >> 1, 0x0c);
+
+ mda_origin_loc = location;
+}
+
+static inline void mda_set_cursor(unsigned int location)
+{
+ if (mda_cursor_loc == location)
+ return;
+
+ write_mda_w(location >> 1, 0x0e);
+
+ mda_cursor_loc = location;
+}
+
+static inline void mda_set_cursor_size(int from, int to)
+{
+ if (mda_cursor_size_from==from && mda_cursor_size_to==to)
+ return;
+
+ if (from > to) {
+ write_mda_b(MDA_CURSOR_OFF, 0x0a); /* disable cursor */
+ } else {
+ write_mda_b(from, 0x0a); /* cursor start */
+ write_mda_b(to, 0x0b); /* cursor end */
+ }
+
+ mda_cursor_size_from = from;
+ mda_cursor_size_to = to;
+}
+
+
+#ifndef MODULE
+__initfunc(void mdacon_setup(char *str, int *ints))
+{
+ /* command line format: mdacon=<first>,<last> */
+
+ if (ints[0] < 2)
+ return;
+
+ if (ints[1] < 1 || ints[1] > MAX_NR_CONSOLES ||
+ ints[2] < 1 || ints[2] > MAX_NR_CONSOLES)
+ return;
+
+ mda_first_vc = ints[1]-1;
+ mda_last_vc = ints[2]-1;
+}
+#endif
+
+#ifdef MODULE
+static int mda_detect(void)
+#else
+__initfunc(static int mda_detect(void))
+#endif
+{
+ int count=0;
+ u16 *p, p_save;
+ u16 *q, q_save;
+
+ /* do a memory check */
+
+ p = (u16 *) mda_vram_base;
+ q = (u16 *) (mda_vram_base + 0x01000);
+
+ p_save = scr_readw(p); q_save = scr_readw(q);
+
+ scr_writew(0xAA55, p); if (scr_readw(p) == 0xAA55) count++;
+ scr_writew(0x55AA, p); if (scr_readw(p) == 0x55AA) count++;
+ scr_writew(p_save, p);
+
+ if (count != 2) {
+ return 0;
+ }
+
+ /* check if we have 4K or 8K */
+
+ scr_writew(0xA55A, q); scr_writew(0x0000, p);
+ if (scr_readw(q) == 0xA55A) count++;
+
+ scr_writew(0x5AA5, q); scr_writew(0x0000, p);
+ if (scr_readw(q) == 0x5AA5) count++;
+
+ scr_writew(p_save, p); scr_writew(q_save, q);
+
+ if (count == 4) {
+ mda_vram_len = 0x02000;
+ }
+
+ /* Ok, there is definitely a card registering at the correct
+ * memory location, so now we do an I/O port test.
+ */
+
+ if (! test_mda_b(0x66, 0x0f)) { /* cursor low register */
+ return 0;
+ }
+ if (! test_mda_b(0x99, 0x0f)) { /* cursor low register */
+ return 0;
+ }
+
+ /* See if the card is a Hercules, by checking whether the vsync
+ * bit of the status register is changing. This test lasts for
+ * approximately 1/10th of a second.
+ */
+
+ p_save = q_save = inb_p(mda_status_port) & MDA_STATUS_VSYNC;
+
+ for (count=0; count < 50000 && p_save == q_save; count++) {
+ q_save = inb(mda_status_port) & MDA_STATUS_VSYNC;
+ udelay(2);
+ }
+
+ if (p_save != q_save) {
+ switch (inb_p(mda_status_port) & 0x70) {
+ case 0x10:
+ mda_type = TYPE_HERCPLUS;
+ mda_type_name = "HerculesPlus";
+ break;
+ case 0x50:
+ mda_type = TYPE_HERCCOLOR;
+ mda_type_name = "HerculesColor";
+ break;
+ default:
+ mda_type = TYPE_HERC;
+ mda_type_name = "Hercules";
+ break;
+ }
+ }
+
+ return 1;
+}
+
+#ifdef MODULE
+static void mda_initialize(void)
+#else
+__initfunc(static void mda_initialize(void))
+#endif
+{
+ write_mda_b(97, 0x00); /* horizontal total */
+ write_mda_b(80, 0x01); /* horizontal displayed */
+ write_mda_b(82, 0x02); /* horizontal sync pos */
+ write_mda_b(15, 0x03); /* horizontal sync width */
+
+ write_mda_b(25, 0x04); /* vertical total */
+ write_mda_b(6, 0x05); /* vertical total adjust */
+ write_mda_b(25, 0x06); /* vertical displayed */
+ write_mda_b(25, 0x07); /* vertical sync pos */
+
+ write_mda_b(2, 0x08); /* interlace mode */
+ write_mda_b(13, 0x09); /* maximum scanline */
+ write_mda_b(12, 0x0a); /* cursor start */
+ write_mda_b(13, 0x0b); /* cursor end */
+
+ write_mda_w(0x0000, 0x0c); /* start address */
+ write_mda_w(0x0000, 0x0e); /* cursor location */
+
+ outb_p(MDA_MODE_VIDEO_EN | MDA_MODE_BLINK_EN, mda_mode_port);
+ outb_p(0x00, mda_status_port);
+ outb_p(0x00, mda_gfx_port);
+}
+
+#ifdef MODULE
+static const char *mdacon_startup(void)
+#else
+__initfunc(static const char *mdacon_startup(void))
+#endif
+{
+ mda_num_columns = 80;
+ mda_num_lines = 25;
+
+ mda_vram_base = VGA_MAP_MEM(0xb0000);
+ mda_vram_len = 0x01000;
+
+ mda_index_port = 0x3b4;
+ mda_value_port = 0x3b5;
+ mda_mode_port = 0x3b8;
+ mda_status_port = 0x3ba;
+ mda_gfx_port = 0x3bf;
+
+ mda_type = TYPE_MDA;
+ mda_type_name = "MDA";
+
+ if (! mda_detect()) {
+ printk("mdacon: MDA card not detected.");
+ return NULL;
+ }
+
+ if (mda_type != TYPE_MDA) {
+ mda_initialize();
+ }
+
+ printk("mdacon: %s with %ldK of memory detected.\n",
+ mda_type_name, mda_vram_len/1024);
+
+ return "MDA-2";
+}
+
+static void mdacon_init(struct vc_data *c, int init)
+{
+ c->vc_complement_mask = 0x0800; /* reverse video */
+ c->vc_display_fg = &mda_display_fg;
+
+ if (init) {
+ c->vc_cols = mda_num_columns;
+ c->vc_rows = mda_num_lines;
+ } else {
+ vc_resize_con(mda_num_lines, mda_num_columns, c->vc_num);
+ }
+
+ /* make the first MDA console visible */
+
+ if (mda_display_fg == NULL)
+ mda_display_fg = c;
+
+ MOD_INC_USE_COUNT;
+}
+
+static void mdacon_deinit(struct vc_data *c)
+{
+ /* con_set_default_unimap(c->vc_num); */
+
+ if (mda_display_fg == c)
+ mda_display_fg = NULL;
+
+ MOD_DEC_USE_COUNT;
+}
+
+static inline u16 mda_convert_attr(u16 ch)
+{
+ u16 attr = 0x0700;
+
+ /* Underline and reverse-video are mutually exclusive on MDA.
+ * Since reverse-video is used for cursors and selected areas,
+ * it takes precedence.
+ */
+
+ if (ch & 0x0800) attr = 0x7000; /* reverse */
+ else if (ch & 0x0400) attr = 0x0100; /* underline */
+
+ return ((ch & 0x0200) << 2) | /* intensity */
+ (ch & 0x8000) | /* blink */
+ (ch & 0x00ff) | attr;
+}
+
+static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
+ u8 blink, u8 underline, u8 reverse)
+{
+ /* The attribute is just a bit vector:
+ *
+ * Bit 0..1 : intensity (0..2)
+ * Bit 2 : underline
+ * Bit 3 : reverse
+ * Bit 7 : blink
+ */
+
+ return (intensity & 3) |
+ ((underline & 1) << 2) |
+ ((reverse & 1) << 3) |
+ ((blink & 1) << 7);
+}
+
+static void mdacon_invert_region(struct vc_data *c, u16 *p, int count)
+{
+ for (; count > 0; count--) {
+ scr_writew(scr_readw(p) ^ 0x0800, p++);
+ }
+}
+
+#define MDA_ADDR(x,y) ((u16 *) mda_vram_base + (y)*mda_num_columns + (x))
+
+static void mdacon_putc(struct vc_data *c, int ch, int y, int x)
+{
+ scr_writew(mda_convert_attr(ch), MDA_ADDR(x, y));
+}
+
+static void mdacon_putcs(struct vc_data *c, const unsigned short *s,
+ int count, int y, int x)
+{
+ u16 *dest = MDA_ADDR(x, y);
+
+ for (; count > 0; count--) {
+ scr_writew(mda_convert_attr(*s++), dest++);
+ }
+}
+
+static void mdacon_clear(struct vc_data *c, int y, int x,
+ int height, int width)
+{
+ u16 *dest = MDA_ADDR(x, y);
+ u16 eattr = mda_convert_attr(c->vc_video_erase_char);
+
+ if (width <= 0 || height <= 0)
+ return;
+
+ if (x==0 && width==mda_num_columns) {
+ scr_memsetw(dest, eattr, height*width*2);
+ } else {
+ for (; height > 0; height--, dest+=mda_num_columns)
+ scr_memsetw(dest, eattr, width*2);
+ }
+}
+
+static void mdacon_bmove(struct vc_data *c, int sy, int sx,
+ int dy, int dx, int height, int width)
+{
+ u16 *src, *dest;
+
+ if (width <= 0 || height <= 0)
+ return;
+
+ if (sx==0 && dx==0 && width==mda_num_columns) {
+ scr_memmovew(MDA_ADDR(0,dy), MDA_ADDR(0,sy), height*width*2);
+
+ } else if (dy < sy || (dy == sy && dx < sx)) {
+ src = MDA_ADDR(sx, sy);
+ dest = MDA_ADDR(dx, dy);
+
+ for (; height > 0; height--) {
+ scr_memmovew(dest, src, width*2);
+ src += mda_num_columns;
+ dest += mda_num_columns;
+ }
+ } else {
+ src = MDA_ADDR(sx, sy+height-1);
+ dest = MDA_ADDR(dx, dy+height-1);
+
+ for (; height > 0; height--) {
+ scr_memmovew(dest, src, width*2);
+ src -= mda_num_columns;
+ dest -= mda_num_columns;
+ }
+ }
+}
+
+static int mdacon_switch(struct vc_data *c)
+{
+ return 1; /* redrawing needed */
+}
+
+static int mdacon_set_palette(struct vc_data *c, unsigned char *table)
+{
+ return -EINVAL;
+}
+
+static int mdacon_blank(struct vc_data *c, int blank)
+{
+ if (blank) {
+ outb_p(0x00, mda_mode_port); /* disable video */
+ } else {
+ outb_p(MDA_MODE_VIDEO_EN | MDA_MODE_BLINK_EN, mda_mode_port);
+ }
+
+ return 0;
+}
+
+static int mdacon_font_op(struct vc_data *c, struct console_font_op *op)
+{
+ return -ENOSYS;
+}
+
+static int mdacon_scrolldelta(struct vc_data *c, int lines)
+{
+ return 0;
+}
+
+static void mdacon_cursor(struct vc_data *c, int mode)
+{
+ if (mode == CM_ERASE) {
+ mda_set_cursor(mda_vram_len - 1);
+ return;
+ }
+
+ mda_set_cursor(c->vc_y*mda_num_columns*2 + c->vc_x*2);
+
+ switch (c->vc_cursor_type & 0x0f) {
+
+ case CUR_LOWER_THIRD: mda_set_cursor_size(10, 13); break;
+ case CUR_LOWER_HALF: mda_set_cursor_size(7, 13); break;
+ case CUR_TWO_THIRDS: mda_set_cursor_size(4, 13); break;
+ case CUR_BLOCK: mda_set_cursor_size(1, 13); break;
+ case CUR_NONE: mda_set_cursor_size(14, 13); break;
+ default: mda_set_cursor_size(12, 13); break;
+ }
+}
+
+static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
+{
+ u16 eattr = mda_convert_attr(c->vc_video_erase_char);
+
+ if (!lines)
+ return 0;
+
+ if (lines > c->vc_rows) /* maximum realistic size */
+ lines = c->vc_rows;
+
+ switch (dir) {
+
+ case SM_UP:
+ scr_memmovew(MDA_ADDR(0,t), MDA_ADDR(0,t+lines),
+ (b-t-lines)*mda_num_columns*2);
+ scr_memsetw(MDA_ADDR(0,b-lines), eattr,
+ lines*mda_num_columns*2);
+ break;
+
+ case SM_DOWN:
+ scr_memmovew(MDA_ADDR(0,t+lines), MDA_ADDR(0,t),
+ (b-t-lines)*mda_num_columns*2);
+ scr_memsetw(MDA_ADDR(0,t), eattr, lines*mda_num_columns*2);
+ break;
+ }
+
+ return 0;
+}
+
+
+/*
+ * The console `switch' structure for the MDA based console
+ */
+
+struct consw mda_con = {
+ mdacon_startup, /* con_startup */
+ mdacon_init, /* con_init */
+ mdacon_deinit, /* con_deinit */
+ mdacon_clear, /* con_clear */
+ mdacon_putc, /* con_putc */
+ mdacon_putcs, /* con_putcs */
+ mdacon_cursor, /* con_cursor */
+ mdacon_scroll, /* con_scroll */
+ mdacon_bmove, /* con_bmove */
+ mdacon_switch, /* con_switch */
+ mdacon_blank, /* con_blank */
+ mdacon_font_op, /* con_font_op */
+ mdacon_set_palette, /* con_set_palette */
+ mdacon_scrolldelta, /* con_scrolldelta */
+ NULL, /* con_set_origin */
+ NULL, /* con_save_screen */
+ mdacon_build_attr, /* con_build_attr */
+ mdacon_invert_region, /* con_invert_region */
+};
+
+#ifdef MODULE
+void mda_console_init(void)
+#else
+__initfunc(void mda_console_init(void))
+#endif
+{
+ if (mda_first_vc > mda_last_vc)
+ return;
+
+ take_over_console(&mda_con, mda_first_vc, mda_last_vc, 0);
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+ mda_console_init();
+
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ give_up_console(&mda_con);
+}
+
+#endif
diff --git a/drivers/video/mdafb.c b/drivers/video/mdafb.c
deleted file mode 100644
index 35190d580..000000000
--- a/drivers/video/mdafb.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * 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/offb.c b/drivers/video/offb.c
index 0e6e57f56..d66176242 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -31,10 +31,13 @@
#endif
#include <asm/io.h>
#include <asm/prom.h>
+#include <asm/bootx.h>
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "macmodes.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb32.h>
+#include <video/macmodes.h>
static int currcon = 0;
@@ -47,6 +50,14 @@ struct fb_info_offb {
struct { u_char red, green, blue, pad; } palette[256];
volatile unsigned char *cmap_adr;
volatile unsigned char *cmap_data;
+ union {
+#ifdef FBCON_HAS_CFB16
+ u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u32 cfb32[16];
+#endif
+ } fbcon_cmap;
};
#ifdef __powerpc__
@@ -91,6 +102,12 @@ struct fb_info *console_fb_info = NULL;
struct vc_mode display_info;
#endif /* CONFIG_FB_COMPAT_XPMAC */
+extern boot_infos_t *boot_infos;
+
+static int offb_init_driver(struct device_node *);
+static void offb_init_nodriver(struct device_node *);
+static void offb_init_fb(const char *name, const char *full_name, int width,
+ int height, int depth, int pitch, unsigned long address);
/*
* Interface to the low level console driver
@@ -175,7 +192,8 @@ static int offb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
struct display *display;
- int oldbpp = -1, err;
+ unsigned int oldbpp = 0;
+ int err;
int activate = var->activate;
struct fb_info_offb *info2 = (struct fb_info_offb *)info;
@@ -197,7 +215,7 @@ static int offb_set_var(struct fb_var_screeninfo *var, int con,
oldbpp = display->var.bits_per_pixel;
display->var = *var;
}
- if (oldbpp != var->bits_per_pixel) {
+ if ((oldbpp != var->bits_per_pixel) || (display->cmap.len == 0)) {
if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
return err;
do_install_cmap(con, info);
@@ -229,8 +247,7 @@ static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
if (con == currcon) /* current console? */
- return fb_get_cmap(cmap, &fb_display[con].var, kspc, offb_getcolreg,
- info);
+ return fb_get_cmap(cmap, kspc, offb_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
@@ -258,8 +275,7 @@ static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return err;
}
if (con == currcon) /* current console? */
- return fb_set_cmap(cmap, &fb_display[con].var, kspc, offb_setcolreg,
- info);
+ return fb_set_cmap(cmap, kspc, offb_setcolreg, info);
else
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
@@ -279,12 +295,21 @@ extern void atyfb_of_init(struct device_node *dp);
#ifdef CONFIG_FB_S3TRIO
extern void s3triofb_init_of(struct device_node *dp);
#endif /* CONFIG_FB_S3TRIO */
+#ifdef CONFIG_FB_IMSTT
+extern void imsttfb_of_init(struct device_node *dp);
+#endif
#ifdef CONFIG_FB_CT65550
extern void chips_of_init(struct device_node *dp);
#endif /* CONFIG_FB_CT65550 */
+#ifdef CONFIG_FB_MATROX
+extern void matrox_of_init(struct device_node *dp);
+#endif /* CONFIG_FB_MATROX */
#ifdef CONFIG_FB_CONTROL
extern void control_of_init(struct device_node *dp);
#endif /* CONFIG_FB_CONTROL */
+#ifdef CONFIG_FB_VALKYRIE
+extern void valkyrie_of_init(struct device_node *dp);
+#endif /* CONFIG_FB_VALKYRIE */
#ifdef CONFIG_FB_PLATINUM
extern void platinum_of_init(struct device_node *dp);
#endif /* CONFIG_FB_PLATINUM */
@@ -297,193 +322,365 @@ extern void platinum_of_init(struct device_node *dp);
__initfunc(void offb_init(void))
{
struct device_node *dp;
- int dpy, i, *pp, len;
- unsigned *up, address;
- struct fb_fix_screeninfo *fix;
- struct fb_var_screeninfo *var;
- struct display *disp;
- struct fb_info_offb *info;
+ unsigned int dpy;
+ struct device_node *displays = find_type_devices("display");
+ struct device_node *macos_display = NULL;
+
+ /* If we're booted from BootX... */
+ if (prom_num_displays == 0 && boot_infos != 0) {
+ unsigned long addr = (unsigned long) boot_infos->dispDeviceBase;
+ if (!ofonly) {
+ /* find the device node corresponding to the macos display */
+ for (dp = displays; dp != NULL; dp = dp->next) {
+ int i;
+ /*
+ * Grrr... It looks like the MacOS ATI driver
+ * munges the assigned-addresses property (but
+ * the AAPL,address value is OK).
+ */
+ if (strncmp(dp->name, "ATY,", 4) == 0 && dp->n_addrs == 1) {
+ unsigned int *ap = (unsigned int *)
+ get_property(dp, "AAPL,address", NULL);
+ if (ap != NULL) {
+ dp->addrs[0].address = *ap;
+ dp->addrs[0].size = 0x01000000;
+ }
+ }
+ /*
+ * See if the display address is in one of the address
+ * ranges for this display.
+ */
+ for (i = 0; i < dp->n_addrs; ++i) {
+ if (dp->addrs[i].address <= addr
+ && addr < dp->addrs[i].address + dp->addrs[i].size)
+ break;
+ }
+ if (i < dp->n_addrs) {
+ printk(KERN_INFO "MacOS display is %s\n", dp->full_name);
+ macos_display = dp;
+ break;
+ }
+ }
+ }
+
+ /* initialize it */
+ if (macos_display == NULL || !offb_init_driver(macos_display)) {
+ offb_init_fb("MacOS display", "MacOS display",
+ boot_infos->dispDeviceRect[2],
+ boot_infos->dispDeviceRect[3],
+ boot_infos->dispDeviceDepth,
+ boot_infos->dispDeviceRowBytes, addr);
+ }
+ }
for (dpy = 0; dpy < prom_num_displays; dpy++) {
- if (!(dp = find_path_device(prom_display_paths[dpy])))
- continue;
+ if ((dp = find_path_device(prom_display_paths[dpy])))
+ if (ofonly || !offb_init_driver(dp))
+ offb_init_nodriver(dp);
+ }
- if (!ofonly) {
+ if (!ofonly) {
+ for (dp = find_type_devices("display"); dp != NULL; dp = dp->next) {
+ for (dpy = 0; dpy < prom_num_displays; dpy++)
+ if (strcmp(dp->full_name, prom_display_paths[dpy]) == 0)
+ break;
+ if (dpy >= prom_num_displays && dp != macos_display)
+ offb_init_driver(dp);
+ }
+ }
+}
+
+__initfunc(static int offb_init_driver(struct device_node *dp))
+{
#ifdef CONFIG_FB_ATY
- if (!strncmp(dp->name, "ATY", 3)) {
- atyfb_of_init(dp);
- continue;
- }
+ if (!strncmp(dp->name, "ATY", 3)) {
+ atyfb_of_init(dp);
+ return 1;
+ }
#endif /* CONFIG_FB_ATY */
#ifdef CONFIG_FB_S3TRIO
- if (s3triofb_init_of(dp))
- continue;
+ if (s3triofb_init_of(dp))
+ return 1;
#endif /* CONFIG_FB_S3TRIO */
+#ifdef CONFIG_FB_IMSTT
+ if (!strncmp(dp->name, "IMS,tt128mb", 11)) {
+ imsttfb_of_init(dp);
+ return 1;
+ }
+#endif
#ifdef CONFIG_FB_CT65550
- if (!strcmp(dp->name, "chips65550")) {
- chips_of_init(dp);
- continue;
- }
+ if (!strcmp(dp->name, "chips65550")) {
+ chips_of_init(dp);
+ return 1;
+ }
#endif /* CONFIG_FB_CT65550 */
+#ifdef CONFIG_FB_MATROX
+ if (!strncmp(dp->name, "MTRX", 4)) {
+ matrox_of_init(dp);
+ return 1;
+ }
+#endif /* CONFIG_FB_MATROX */
#ifdef CONFIG_FB_CONTROL
- if(!strcmp(dp->name, "control")) {
- control_of_init(dp);
- continue;
- }
+ if(!strcmp(dp->name, "control")) {
+ control_of_init(dp);
+ return 1;
+ }
#endif /* CONFIG_FB_CONTROL */
+#ifdef CONFIG_FB_VALKYRIE
+ if(!strcmp(dp->name, "valkyrie")) {
+ valkyrie_of_init(dp);
+ return 1;
+ }
+#endif /* CONFIG_FB_VALKYRIE */
#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;
- }
+ if (!strncmp(dp->name, "platinum",8)) {
+ platinum_of_init(dp);
+ return 1;
+ }
#endif /* CONFIG_FB_PLATINUM */
+ return 0;
+}
+
+__initfunc(static void offb_init_nodriver(struct device_node *dp))
+{
+ int *pp, i;
+ unsigned int len;
+ int width = 640, height = 480, depth = 8, pitch;
+ unsigned *up, address;
+
+ if ((pp = (int *)get_property(dp, "depth", &len)) != NULL
+ && len == sizeof(int))
+ depth = *pp;
+ if ((pp = (int *)get_property(dp, "width", &len)) != NULL
+ && len == sizeof(int))
+ width = *pp;
+ if ((pp = (int *)get_property(dp, "height", &len)) != NULL
+ && len == sizeof(int))
+ height = *pp;
+ if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL
+ && len == sizeof(int))
+ pitch = *pp;
+ else
+ pitch = width;
+ if ((up = (unsigned *)get_property(dp, "address", &len)) != NULL
+ && len == sizeof(unsigned))
+ address = (u_long)*up;
+ else {
+ for (i = 0; i < dp->n_addrs; ++i)
+ if (dp->addrs[i].size >= len)
+ break;
+ if (i >= dp->n_addrs) {
+ printk("no framebuffer address found for %s\n", dp->full_name);
+ return;
}
+ address = (u_long)dp->addrs[i].address;
- info = kmalloc(sizeof(struct fb_info_offb), GFP_ATOMIC);
- fix = &info->fix;
- var = &info->var;
- disp = &info->disp;
+ /* kludge for valkyrie */
+ if (strcmp(dp->name, "valkyrie") == 0)
+ address += 0x1000;
+ }
+ offb_init_fb(dp->name, dp->full_name, width, height, depth,
+ pitch, address);
+}
- strcpy(fix->id, "OFfb ");
- strncat(fix->id, dp->name, sizeof(fix->id));
- fix->id[sizeof(fix->id)-1] = '\0';
+__initfunc(static void offb_init_fb(const char *name, const char *full_name,
+ int width, int height, int depth,
+ int pitch, unsigned long address))
+{
+ int i;
+ struct fb_fix_screeninfo *fix;
+ struct fb_var_screeninfo *var;
+ struct display *disp;
+ struct fb_info_offb *info;
- 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
- && len == sizeof(int))
- var->xres = var->xres_virtual = *pp;
- if ((pp = (int *)get_property(dp, "height", &len)) != NULL
- && len == sizeof(int))
- var->yres = var->yres_virtual = *pp;
- if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL
- && len == sizeof(int))
- fix->line_length = *pp;
- else
- fix->line_length = var->xres_virtual;
- fix->smem_len = fix->line_length*var->yres;
- if ((up = (unsigned *)get_property(dp, "address", &len)) != NULL
- && len == sizeof(unsigned))
- address = (u_long)*up;
- else {
- for (i = 0; i < dp->n_addrs; ++i)
- if (dp->addrs[i].size >= len)
- break;
- if (i >= dp->n_addrs) {
- printk("no framebuffer address found for %s\n", dp->full_name);
- kfree(info);
- continue;
- }
- address = (u_long)dp->addrs[i].address;
- }
- fix->smem_start = (char *)address;
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->type_aux = 0;
+ printk(KERN_INFO "Using unsupported %dx%d %s at %lx, depth=%d, pitch=%d\n",
+ width, height, name, address, depth, pitch);
+ if (depth != 8 && depth != 16 && depth != 32) {
+ printk("%s: can't use depth = %d\n", full_name, depth);
+ return;
+ }
+
+ info = kmalloc(sizeof(struct fb_info_offb), GFP_ATOMIC);
+ if (info == 0)
+ return;
+ memset(info, 0, sizeof(*info));
+
+ fix = &info->fix;
+ var = &info->var;
+ disp = &info->disp;
+
+ strcpy(fix->id, "OFfb ");
+ strncat(fix->id, name, sizeof(fix->id));
+ fix->id[sizeof(fix->id)-1] = '\0';
+
+ var->xres = var->xres_virtual = width;
+ var->yres = var->yres_virtual = height;
+ fix->line_length = pitch;
+
+ fix->smem_start = (char *)address;
+ fix->smem_len = pitch * height;
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->type_aux = 0;
/* XXX kludge for ati */
- if (strncmp(dp->name, "ATY,", 4) == 0) {
- info->cmap_adr = ioremap(address + 0x7ff000, 0x1000) + 0xcc0;
- info->cmap_data = info->cmap_adr + 1;
- }
+ if (strncmp(name, "ATY,", 4) == 0) {
+ info->cmap_adr = ioremap(address + 0x7ff000, 0x1000) + 0xcc0;
+ info->cmap_data = info->cmap_adr + 1;
+ }
+
+ if (depth == 8)
+ fix->visual = info->cmap_adr ? FB_VISUAL_PSEUDOCOLOR
+ : FB_VISUAL_STATIC_PSEUDOCOLOR;
+ else
+ fix->visual = FB_VISUAL_TRUECOLOR;
- fix->visual = info->cmap_adr ? FB_VISUAL_PSEUDOCOLOR :
- FB_VISUAL_STATIC_PSEUDOCOLOR;
-
- var->xoffset = var->yoffset = 0;
- var->bits_per_pixel = 8;
- var->grayscale = 0;
- var->red.offset = var->green.offset = var->blue.offset = 0;
- var->red.length = var->green.length = var->blue.length = 8;
- var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
- var->transp.offset = var->transp.length = var->transp.msb_right = 0;
- var->nonstd = 0;
- var->activate = 0;
- var->height = var->width = -1;
- var->pixclock = 10000;
- var->left_margin = var->right_margin = 16;
- var->upper_margin = var->lower_margin = 16;
- var->hsync_len = var->vsync_len = 8;
- var->sync = 0;
- var->vmode = FB_VMODE_NONINTERLACED;
-
- disp->var = *var;
- disp->cmap.start = 0;
- disp->cmap.len = 0;
- disp->cmap.red = 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;
- disp->ypanstep = 0;
- disp->ywrapstep = 0;
- disp->line_length = fix->line_length;
- disp->can_soft_blank = info->cmap_adr ? 1 : 0;
- disp->inverse = 0;
+ var->xoffset = var->yoffset = 0;
+ var->bits_per_pixel = depth;
+ switch (depth) {
+ case 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 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 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 = var->green.msb_right = var->blue.msb_right = var->transp.msb_right = 0;
+ var->grayscale = 0;
+ var->nonstd = 0;
+ var->activate = 0;
+ var->height = var->width = -1;
+ var->pixclock = 10000;
+ var->left_margin = var->right_margin = 16;
+ var->upper_margin = var->lower_margin = 16;
+ var->hsync_len = var->vsync_len = 8;
+ var->sync = 0;
+ var->vmode = FB_VMODE_NONINTERLACED;
+
+ disp->var = *var;
+ disp->cmap.start = 0;
+ disp->cmap.len = 0;
+ disp->cmap.red = 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;
+ disp->ypanstep = 0;
+ disp->ywrapstep = 0;
+ disp->line_length = fix->line_length;
+ disp->can_soft_blank = info->cmap_adr ? 1 : 0;
+ disp->inverse = 0;
+ switch (depth) {
#ifdef FBCON_HAS_CFB8
- disp->dispsw = &fbcon_cfb8;
-#else
- disp->dispsw = NULL;
+ case 8:
+ disp->dispsw = &fbcon_cfb8;
+ break;
#endif
- disp->scrollmode = SCROLL_YREDRAW;
-
- strcpy(info->info.modename, "OFfb ");
- strncat(info->info.modename, dp->full_name,
- sizeof(info->info.modename));
- info->info.node = -1;
- info->info.fbops = &offb_ops;
- info->info.disp = disp;
- info->info.fontname[0] = '\0';
- info->info.changevar = NULL;
- info->info.switch_con = &offbcon_switch;
- info->info.updatevar = &offbcon_updatevar;
- info->info.blank = &offbcon_blank;
-
- for (i = 0; i < 16; i++) {
- int j = color_table[i];
- info->palette[i].red = default_red[j];
- info->palette[i].green = default_grn[j];
- info->palette[i].blue = default_blu[j];
- }
- offb_set_var(var, -1, &info->info);
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ disp->dispsw = &fbcon_cfb16;
+ disp->dispsw_data = info->fbcon_cmap.cfb16;
+ for (i = 0; i < 16; i++)
+ info->fbcon_cmap.cfb16[i] =
+ (((default_blu[i] >> 3) & 0x1f) << 10) |
+ (((default_grn[i] >> 3) & 0x1f) << 5) |
+ ((default_red[i] >> 3) & 0x1f);
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ disp->dispsw = &fbcon_cfb32;
+ disp->dispsw_data = info->fbcon_cmap.cfb32;
+ for (i = 0; i < 16; i++)
+ info->fbcon_cmap.cfb32[i] = (default_blu[i] << 16) |
+ (default_grn[i] << 8) |
+ default_red[i];
+ break;
+#endif
+ default:
+ disp->dispsw = &fbcon_dummy;
+ }
- if (register_framebuffer(&info->info) < 0) {
- kfree(info);
- return;
- }
+ disp->scrollmode = SCROLL_YREDRAW;
+
+ strcpy(info->info.modename, "OFfb ");
+ strncat(info->info.modename, full_name, sizeof(info->info.modename));
+ info->info.node = -1;
+ info->info.fbops = &offb_ops;
+ info->info.disp = disp;
+ info->info.fontname[0] = '\0';
+ info->info.changevar = NULL;
+ info->info.switch_con = &offbcon_switch;
+ info->info.updatevar = &offbcon_updatevar;
+ info->info.blank = &offbcon_blank;
+ info->info.flags = FBINFO_FLAG_DEFAULT;
+
+ for (i = 0; i < 16; i++) {
+ int j = color_table[i];
+ info->palette[i].red = default_red[j];
+ info->palette[i].green = default_grn[j];
+ info->palette[i].blue = default_blu[j];
+ }
+ offb_set_var(var, -1, &info->info);
- printk("fb%d: Open Firmware frame buffer device on %s\n",
- GET_FB_IDX(info->info.node), dp->full_name);
+ 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), full_name);
#ifdef CONFIG_FB_COMPAT_XPMAC
- if (!console_fb_info) {
- display_info.height = var->yres;
- display_info.width = var->xres;
- display_info.depth = 8;
- display_info.pitch = fix->line_length;
- display_info.mode = 0;
- strncpy(display_info.name, dp->name, sizeof(display_info.name));
- display_info.fb_address = 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 = address + 0x7ffc00;
- display_info.cmap_adr_address = address + 0x7ffcc0;
- display_info.cmap_data_address = address + 0x7ffcc1;
- }
- console_fb_info = &info->info;
+ if (!console_fb_info) {
+ display_info.height = var->yres;
+ display_info.width = var->xres;
+ display_info.depth = depth;
+ display_info.pitch = fix->line_length;
+ display_info.mode = 0;
+ strncpy(display_info.name, name, sizeof(display_info.name));
+ 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(name, "ATY,", 4) == 0) {
+ display_info.disp_reg_address = address + 0x7ffc00;
+ display_info.cmap_adr_address = address + 0x7ffcc0;
+ display_info.cmap_data_address = address + 0x7ffcc1;
}
-#endif /* CONFIG_FB_COMPAT_XPMAC) */
+ console_fb_info = &info->info;
}
+#endif /* CONFIG_FB_COMPAT_XPMAC) */
}
@@ -505,8 +702,7 @@ static int offbcon_switch(int con, struct fb_info *info)
{
/* Do we have to save the colormap? */
if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
- offb_getcolreg, info);
+ fb_get_cmap(&fb_display[currcon].cmap, 1, offb_getcolreg, info);
currcon = con;
/* Install new colormap */
@@ -561,9 +757,11 @@ static int offb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
if (!info2->cmap_adr || regno > 255)
return 1;
- *red = info2->palette[regno].red;
- *green = info2->palette[regno].green;
- *blue = info2->palette[regno].blue;
+
+ *red = (info2->palette[regno].red<<8) | info2->palette[regno].red;
+ *green = (info2->palette[regno].green<<8) | info2->palette[regno].green;
+ *blue = (info2->palette[regno].blue<<8) | info2->palette[regno].blue;
+ *transp = 0;
return 0;
}
@@ -578,12 +776,19 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
struct fb_info_offb *info2 = (struct fb_info_offb *)info;
-
+ int i;
+
if (!info2->cmap_adr || regno > 255)
return 1;
+
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+
info2->palette[regno].red = red;
info2->palette[regno].green = green;
info2->palette[regno].blue = blue;
+
*info2->cmap_adr = regno;
mach_eieio();
*info2->cmap_data = red;
@@ -592,6 +797,23 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
mach_eieio();
*info2->cmap_data = blue;
mach_eieio();
+
+ if (regno < 16)
+ switch (info2->var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ info2->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
+ regno;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ i = (regno << 8) | regno;
+ info2->fbcon_cmap.cfb32[regno] = (i << 16) | i;
+ break;
+#endif
+ }
+
return 0;
}
@@ -601,12 +823,10 @@ static void do_install_cmap(int con, struct fb_info *info)
if (con != currcon)
return;
if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
- offb_setcolreg, info);
+ fb_set_cmap(&fb_display[con].cmap, 1, offb_setcolreg, info);
else
fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
- &fb_display[con].var, 1, offb_setcolreg,
- info);
+ 1, offb_setcolreg, info);
}
@@ -632,24 +852,35 @@ int console_setmode(struct vc_mode *mode, int doit)
switch (mode->depth) {
case 8:
case 0: /* default */
- cmode = 0; /* CMODE_8 */
+ cmode = CMODE_8;
break;
case 16:
- cmode = 1; /* CMODE_16 */
+ cmode = CMODE_16;
break;
case 24:
case 32:
- cmode = 2; /* CMODE_32 */
+ cmode = 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;
+ var.activate = FB_ACTIVATE_TEST;
err = console_fb_info->fbops->fb_set_var(&var, fg_console,
console_fb_info);
- return err;
+ if (err || !doit)
+ return err;
+ else {
+ int unit;
+ var.activate = FB_ACTIVATE_NOW;
+ for (unit = 0; unit < MAX_NR_CONSOLES; unit++)
+ if (fb_display[unit].conp &&
+ (GET_FB_IDX(console_fb_info->node) == con2fb_map[unit]))
+ console_fb_info->fbops->fb_set_var(&var, unit,
+ console_fb_info);
+ }
+ return 0;
}
static u16 palette_red[16];
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index f2a3e9410..89f6860f2 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -1,19 +1,12 @@
/*
* 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
+ * Copyright (C) 1998 Franz Sirl
*
* 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.
+ * drivers/video/controlfb.c -- frame buffer device for
+ * Apple 'control' display chip.
+ * Copyright (C) 1998 Dan Jacobowitz
*
* Hardware information from:
* platinum.c: Console support for PowerMac "platinum" display adaptor.
@@ -47,18 +40,21 @@
#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 <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb32.h>
+#include <video/macmodes.h>
-#include "macmodes.h"
#include "platinumfb.h"
+static char fontname[40] __initdata = { 0 };
+
static int currcon = 0;
-static int switching = 0;
+
+static int default_vmode = VMODE_NVRAM;
+static int default_cmode = CMODE_NVRAM;
struct fb_par_platinum {
int vmode, cmode;
@@ -68,68 +64,104 @@ struct fb_par_platinum {
};
struct fb_info_platinum {
- struct fb_info info;
- struct fb_fix_screeninfo fix;
- struct fb_var_screeninfo var;
+ struct fb_info fb_info;
struct display disp;
- struct fb_par_platinum par;
+ struct fb_par_platinum default_par;
+ struct fb_par_platinum current_par;
+
struct {
__u8 red, green, blue;
- } palette[256];
+ } palette[256];
volatile struct cmap_regs *cmap_regs;
- unsigned long cmap_regs_phys;
+ unsigned long cmap_regs_phys;
volatile struct platinum_regs *platinum_regs;
- unsigned long platinum_regs_phys;
+ unsigned long platinum_regs_phys;
- __u8 *frame_buffer;
- __u8 *base_frame_buffer;
- unsigned long frame_buffer_phys;
+ __u8 *frame_buffer;
+ volatile __u8 *base_frame_buffer;
+ unsigned long frame_buffer_phys;
- int sense;
- unsigned long total_vram;
+ unsigned long total_vram;
+ int clktype;
+ int dactype;
+
+ union {
+#ifdef FBCON_HAS_CFB16
+ u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u32 cfb32[16];
+#endif
+ } fbcon_cmap;
};
/*
- * Exported functions
+ * Frame buffer device API
*/
-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);
+ struct fb_info *fb);
static int platinum_get_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info);
+ struct fb_info *fb);
static int platinum_set_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info);
+ struct fb_info *fb);
static int platinum_pan_display(struct fb_var_screeninfo *var, int con,
- struct fb_info *info);
+ struct fb_info *fb);
static int platinum_get_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info);
+ struct fb_info *info);
static int platinum_set_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info);
+ 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);
+ u_long arg, int con, struct fb_info *info);
+
+
+/*
+ * Interface to the low level console driver
+ */
+
+static int platinum_switch(int con, struct fb_info *fb);
+static int platinum_updatevar(int con, struct fb_info *fb);
+static void platinum_blank(int blank, struct fb_info *fb);
+
+
+/*
+ * internal functions
+ */
-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 int read_platinum_sense(struct fb_info_platinum *info);
+static void set_platinum_clock(struct fb_info_platinum *info);
+static void platinum_set_par(const struct fb_par_platinum *par, struct fb_info_platinum *info);
+static int platinum_par_to_var(struct fb_var_screeninfo *var,
+ const struct fb_par_platinum *par,
+ const struct fb_info_platinum *info);
+static int platinum_var_to_par(const struct fb_var_screeninfo *var,
+ struct fb_par_platinum *par,
+ const struct fb_info_platinum *info);
+static int platinum_encode_fix(struct fb_fix_screeninfo *fix,
+ const struct fb_par_platinum *par,
+ const struct fb_info_platinum *info);
+static int platinum_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+ u_int *transp, struct fb_info *fb);
+static int platinum_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *fb);
+static void do_install_cmap(int con, struct fb_info *info);
+
+
+/*
+ * Interface used by the world
+ */
+
+void platinum_init(void);
+#ifdef CONFIG_FB_OF
+void platinum_of_init(struct device_node *dp);
+#endif
+void platinum_setup(char *options, int *ints);
+
static struct fb_ops platinumfb_ops = {
platinum_open,
@@ -143,13 +175,6 @@ static struct fb_ops platinumfb_ops = {
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
@@ -167,76 +192,121 @@ 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)
+ struct fb_info *fb)
{
- struct fb_info_platinum *cp = (struct fb_info_platinum *) info;
+ const struct fb_info_platinum *info = (struct fb_info_platinum *)fb;
+ struct fb_par_platinum par;
- *fix = cp->fix;
+ if (con == -1)
+ par = info->default_par;
+ else
+ platinum_var_to_par(&fb_display[con].var, &par, info);
+
+ platinum_encode_fix(fix, &par, info);
return 0;
}
static int platinum_get_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
+ struct fb_info *fb)
{
- struct fb_info_platinum *cp = (struct fb_info_platinum *) info;
+ const struct fb_info_platinum *info = (struct fb_info_platinum *)fb;
+
+ if (con == -1)
+ platinum_par_to_var(var, &info->default_par, info);
+ else
+ *var = fb_display[con].var;
- *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 *fb)
{
- struct fb_info_platinum *p = (struct fb_info_platinum *) info;
- struct display *disp;
+ struct fb_info_platinum *info = (struct fb_info_platinum *) fb;
struct fb_par_platinum par;
- int depthchange, err;
+ struct display *display;
+ int oldxres, oldyres, oldvxres, oldvyres, oldbpp, err;
+ int activate = var->activate;
+
+ display = (con >= 0) ? &fb_display[con] : fb->disp;
-// 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);
+ printk(KERN_ERR "platinum_set_var: error 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);
+ platinum_par_to_var(var, &par, info);
+
+ if ((activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) {
+ printk(KERN_INFO "platinum_set_var: Not activating.\n");
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;
+
+ oldxres = display->var.xres;
+ oldyres = display->var.yres;
+ oldvxres = display->var.xres_virtual;
+ oldvyres = display->var.yres_virtual;
+ oldbpp = display->var.bits_per_pixel;
+ display->var = *var;
+
+ if (oldxres != var->xres || oldyres != var->yres ||
+ oldvxres != var->xres_virtual || oldyres != var->yres_virtual ||
+ oldbpp != var->bits_per_pixel) {
+ struct fb_fix_screeninfo fix;
+
+ platinum_encode_fix(&fix, &par, info);
+ display->screen_base = (char *) info->frame_buffer + 0x1000;
+ display->visual = fix.visual;
+ display->type = fix.type;
+ display->type_aux = fix.type_aux;
+ display->ypanstep = fix.ypanstep;
+ display->ywrapstep = fix.ywrapstep;
+ display->line_length = fix.line_length;
+ display->can_soft_blank = 1;
+ display->inverse = 0;
+
+ switch(par.cmode) {
+#ifdef FBCON_HAS_CFB8
+ case CMODE_8:
+ display->dispsw = &fbcon_cfb8;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case CMODE_16:
+ display->dispsw = &fbcon_cfb16;
+ display->dispsw_data = info->fbcon_cmap.cfb16;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case CMODE_32:
+ display->dispsw = &fbcon_cfb32;
+ display->dispsw_data = info->fbcon_cmap.cfb32;
+ break;
+#endif
+ default:
+ display->dispsw = &fbcon_dummy;
+ break;
+ }
+
+ display->scrollmode = SCROLL_YREDRAW;
+ if (info->fb_info.changevar)
+ (*info->fb_info.changevar)(con);
}
- 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);
+
+ if (con == currcon)
+ platinum_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->fb_info);
+ }
+
return 0;
}
static int platinum_pan_display(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
+ struct fb_info *info)
{
/*
* Pan (or wrap, depending on the `vmode' field) the display using the
@@ -244,21 +314,18 @@ static int platinum_pan_display(struct fb_var_screeninfo *var, int con,
* 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)
+ struct fb_info *info)
{
-// FUNCID;
if (con == currcon) /* current console? */
- return fb_get_cmap(cmap, &fb_display[con].var, kspc,
- platinum_getcolreg, info);
+ return fb_get_cmap(cmap, kspc, platinum_getcolreg, info);
if (fb_display[con].cmap.len) /* non default colormap? */
- fb_copy_cmap(&fb_display[con].cmap, cmap, kspc? 0: 2);
+ 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);
@@ -267,63 +334,54 @@ static int platinum_get_cmap(struct fb_cmap *cmap, int kspc, int con,
}
static int platinum_set_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info)
+ struct fb_info *info)
{
- struct display *disp = &fb_display[con];
int err;
-// FUNCID;
- if (disp->cmap.len == 0) {
+ if (!fb_display[con].cmap.len) {
int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
- err = fb_alloc_cmap(&disp->cmap, size, 0);
+ err = fb_alloc_cmap(&fb_display[con].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 fb_set_cmap(cmap, kspc, platinum_setcolreg, info);
+ fb_copy_cmap(cmap, &fb_display[con].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)
+ u_long arg, int con, struct fb_info *info)
{
-// FUNCID;
+ printk(KERN_ERR "platinum_ioctl not yet implemented\n");
return -EINVAL;
}
-static int platinum_switch(int con, struct fb_info *info)
+static int platinum_switch(int con, struct fb_info *fb)
{
-// FUNCID;
+ struct fb_info_platinum *info = (struct fb_info_platinum *) fb;
+ struct fb_par_platinum par;
+
if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap,
- &fb_display[currcon].var, 1, platinum_getcolreg,
- info);
+ fb_get_cmap(&fb_display[currcon].cmap, 1, platinum_getcolreg,
+ fb);
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;
+ platinum_set_par(&par, info);
+ do_install_cmap(con, fb);
+
+ return 1;
}
-static int platinum_updatevar(int con, struct fb_info *info)
+static int platinum_updatevar(int con, struct fb_info *fb)
{
+ printk(KERN_ERR "platinum_updatevar is doing nothing yet.\n");
return 0;
}
-static void platinum_blank(int blank_mode, struct fb_info *info)
+static void platinum_blank(int blank, struct fb_info *fb)
{
/*
* Blank the screen if blank_mode != 0, else unblank. If blank == NULL
@@ -337,71 +395,68 @@ static void platinum_blank(int blank_mode, struct fb_info *info)
*/
/* [danj] I think there's something fishy about those constants... */
/*
- struct fb_info_platinum *p = (struct fb_info_platinum *) info;
+ struct fb_info_platinum *info = (struct fb_info_platinum *) fb;
int ctrl;
- ctrl = ld_le32(&p->platinum_regs->ctrl.r) | 0x33;
- if (blank_mode)
+ ctrl = ld_le32(&info->platinum_regs->ctrl.r) | 0x33;
+ if (blank)
--blank_mode;
- if (blank_mode & VESA_VSYNC_SUSPEND)
+ if (blank & VESA_VSYNC_SUSPEND)
ctrl &= ~3;
- if (blank_mode & VESA_HSYNC_SUSPEND)
+ if (blank & VESA_HSYNC_SUSPEND)
ctrl &= ~0x30;
- out_le32(&p->platinum_regs->ctrl.r, ctrl);
+ out_le32(&info->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)
+ u_int *blue, u_int *transp, struct fb_info *fb)
{
- struct fb_info_platinum *p = (struct fb_info_platinum *) info;
+ struct fb_info_platinum *info = (struct fb_info_platinum *) fb;
-// FUNCID;
- if (regno > 255 || regno < 0)
+ if (regno > 255)
return 1;
- *red = p->palette[regno].red;
- *green = p->palette[regno].green;
- *blue = p->palette[regno].blue;
+
+ *red = (info->palette[regno].red<<8) | info->palette[regno].red;
+ *green = (info->palette[regno].green<<8) | info->palette[regno].green;
+ *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue;
+ *transp = 0;
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)
+ u_int transp, struct fb_info *fb)
{
- struct fb_info_platinum *p = (struct fb_info_platinum *) info;
+ struct fb_info_platinum *info = (struct fb_info_platinum *) fb;
+ volatile struct cmap_regs *cmap_regs = info->cmap_regs;
+ int scale;
-// FUNCID;
- if (regno > 255 || regno < 0)
+ if (regno > 255)
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);
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+
+ info->palette[regno].red = red;
+ info->palette[regno].green = green;
+ info->palette[regno].blue = blue;
+
+ scale = (info->current_par.cmode == CMODE_16) ? 3 : 0;
+
+ out_8(&cmap_regs->addr, regno); /* tell clut what addr to fill */
+ out_8(&cmap_regs->lut, red<<scale); /* send one color channel at */
+ out_8(&cmap_regs->lut, green<<scale); /* a time... */
+ out_8(&cmap_regs->lut, blue<<scale);
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;
+ info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | (regno << 0);
#endif
#ifdef FBCON_HAS_CFB32
- fbcon_cfb32_cmap[regno] = (regno << 24) | (regno << 16) | (regno << 8) | regno;
- /* I think. */
-#endif
+ info->fbcon_cmap.cfb32[regno] = (regno << 24) | (regno << 16) | (regno << 8) | regno;
#endif
}
return 0;
@@ -409,53 +464,46 @@ static int platinum_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
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);
+ fb_set_cmap(&fb_display[con].cmap, 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);
+ fb_set_cmap(fb_default_cmap(size), 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];
+ return vmode_attrs[video_mode-1].vres *
+ (vmode_attrs[video_mode-1].hres * (1<<color_mode) + 0x20) +0x1000;
}
#define STORE_D2(a, d) { \
- out_8(&p->cmap_regs->addr, (a+32)); \
- out_8(&p->cmap_regs->d2, (d)); \
+ out_8(&cmap_regs->addr, (a+32)); \
+ out_8(&cmap_regs->d2, (d)); \
}
-static void set_platinum_clock(struct fb_info_platinum *p, unsigned char *clock_params)
+static void set_platinum_clock(struct fb_info_platinum *info)
{
-// FUNCID;
+ volatile struct cmap_regs *cmap_regs = info->cmap_regs;
+ struct platinum_regvals *init;
+
+ init = platinum_reg_init[info->current_par.vmode-1];
+
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]);
+ out_8(&cmap_regs->addr,3+32);
+
+ if (in_8(&cmap_regs->d2) == 2) {
+ STORE_D2(7, init->clock_params[info->clktype][0]);
+ STORE_D2(8, init->clock_params[info->clktype][1]);
STORE_D2(3, 3);
} else {
- STORE_D2(4, clock_params[0]);
- STORE_D2(5, clock_params[1]);
+ STORE_D2(4, init->clock_params[info->clktype][0]);
+ STORE_D2(5, init->clock_params[info->clktype][1]);
STORE_D2(3, 2);
}
@@ -464,131 +512,145 @@ static void set_platinum_clock(struct fb_info_platinum *p, unsigned char *clock_
}
-__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)
+static void platinum_set_par(const struct fb_par_platinum *par, struct fb_info_platinum *info)
{
- struct platinum_regvals *init;
- int i, dtype, clkmode;
- int vmode, cmode;
+ volatile struct platinum_regs *platinum_regs = info->platinum_regs;
+ volatile struct cmap_regs *cmap_regs = info->cmap_regs;
+ struct platinum_regvals *init;
+ int i;
+ int vmode, cmode;
-// FUNCID;
- vmode = p->par.vmode;
- cmode = p->par.cmode;
+ info->current_par = *par;
+
+ vmode = par->vmode;
+ cmode = par->cmode;
init = platinum_reg_init[vmode - 1];
/* Initialize display timing registers */
- out_be32(&p->platinum_regs->reg[24].r, 7); /* turn display off */
+ out_be32(&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 ?
+ out_be32(&platinum_regs->reg[i+32].r, init->regs[i]);
+
+ out_be32(&platinum_regs->reg[26+32].r, (info->total_vram == 0x100000 ?
+ init->offset[cmode] + 4 - cmode :
+ init->offset[cmode]));
+ out_be32(&platinum_regs->reg[16].r, (unsigned) info->frame_buffer_phys + 0x1000 - 0x10);
+ out_be32(&platinum_regs->reg[18].r, init->pitch[cmode]);
+ out_be32(&platinum_regs->reg[19].r, (info->total_vram == 0x100000 ?
+ init->mode[cmode+1] :
+ init->mode[cmode]));
+ out_be32(&platinum_regs->reg[20].r, (info->total_vram == 0x100000 ? 0x11 : 0x1011));
+ out_be32(&platinum_regs->reg[21].r, 0x100);
+ out_be32(&platinum_regs->reg[22].r, 1);
+ out_be32(&platinum_regs->reg[23].r, 1);
+ out_be32(&platinum_regs->reg[26].r, 0xc00);
+ out_be32(&platinum_regs->reg[27].r, 0x235);
+ /* out_be32(&platinum_regs->reg[27].r, 0x2aa); */
+
+ STORE_D2(0, (info->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]);
+ set_platinum_clock(info);
- out_be32(&p->platinum_regs->reg[24].r, 0); /* turn display on */
+ out_be32(&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;
+ if (console_fb_info == &info->fb_info) {
+ display_info.height = par->yres;
+ display_info.width = par->xres;
display_info.depth = ( (cmode == CMODE_32) ? 32 :
((cmode == CMODE_16) ? 16 : 8));
- display_info.pitch = p->fix.line_length;
+ display_info.pitch = vmode_attrs[vmode-1].hres * (1<<cmode) + 0x20;
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;
+ display_info.fb_address = info->frame_buffer_phys + 0x1000;
+ display_info.cmap_adr_address = info->cmap_regs_phys;
+ display_info.cmap_data_address = info->cmap_regs_phys + 0x30;
+ display_info.disp_reg_address = info->platinum_regs_phys;
+
}
#endif /* CONFIG_FB_COMPAT_XPMAC */
}
+
+__initfunc(static int init_platinum(struct fb_info_platinum *info))
+{
+ struct fb_var_screeninfo var;
+ struct display *disp;
+ int sense;
+ int j,k;
+
+ sense = read_platinum_sense(info);
+ printk(KERN_INFO "Monitor sense value = 0x%x, ", sense);
+
+ if (default_vmode == VMODE_NVRAM) {
+ default_vmode = nvram_read_byte(NV_VMODE);
+ if (default_vmode <= 0 || default_vmode > VMODE_MAX ||
+ !platinum_reg_init[default_vmode-1])
+ default_vmode = VMODE_CHOOSE;
+ }
+ if (default_vmode == VMODE_CHOOSE) {
+ 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;
+ /*
+ * Reduce the pixel size if we don't have enough VRAM.
+ */
+ while(default_cmode > CMODE_8 && platinum_vram_reqd(default_vmode, default_cmode) > info->total_vram)
+ default_cmode--;
+
+ printk("using video mode %d and color mode %d.\n", default_vmode, default_cmode);
+
+ mac_vmode_to_var(default_vmode, default_cmode, &var);
+
+ if (platinum_var_to_par(&var, &info->default_par, info)) {
+ printk(KERN_ERR "platinumfb: can't set default video mode\n");
+ return 0;
+ }
+
+ disp = &info->disp;
+
+ strcpy(info->fb_info.modename, "platinum");
+ info->fb_info.node = -1;
+ info->fb_info.fbops = &platinumfb_ops;
+ info->fb_info.disp = disp;
+ strcpy(info->fb_info.fontname, fontname);
+ info->fb_info.changevar = NULL;
+ info->fb_info.switch_con = &platinum_switch;
+ info->fb_info.updatevar = &platinum_updatevar;
+ info->fb_info.blank = &platinum_blank;
+ info->fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+ 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];
+ }
+ platinum_set_var(&var, -1, &info->fb_info);
+
+ if (register_framebuffer(&info->fb_info) < 0)
+ return 0;
+
+ printk(KERN_INFO "fb%d: platinum frame buffer device\n",
+ GET_FB_IDX(info->fb_info.node));
+
+ return 1;
+}
+
__initfunc(void platinum_init(void))
{
#ifndef CONFIG_FB_OF
@@ -600,17 +662,27 @@ __initfunc(void platinum_init(void))
#endif /* CONFIG_FB_OF */
}
+#ifdef __powerpc__
+#define invalidate_cache(addr) \
+ asm volatile("eieio; dcbi 0,%1" \
+ : "=m" (*(addr)) : "r" (addr) : "memory");
+#else
+#define invalidate_cache(addr)
+#endif
+
__initfunc(void platinum_of_init(struct device_node *dp))
{
- struct fb_info_platinum *p;
+ struct fb_info_platinum *info;
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)
+
+ info = kmalloc(sizeof(*info), GFP_ATOMIC);
+ if (info == 0)
return;
+ memset(info, 0, sizeof(*info));
/* Map in frame buffer and registers */
for (i = 0; i < dp->n_addrs; ++i) {
@@ -618,47 +690,67 @@ __initfunc(void platinum_of_init(struct device_node *dp))
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;
+ info->frame_buffer_phys = addr;
+ info->frame_buffer = __ioremap(addr, 0x400000, _PAGE_WRITETHRU);
+ info->base_frame_buffer = info->frame_buffer;
} else {
/* registers */
- p->platinum_regs_phys = addr;
- p->platinum_regs = ioremap(addr, size);
+ info->platinum_regs_phys = addr;
+ info->platinum_regs = ioremap(addr, size);
}
}
- p->cmap_regs_phys = 0xf301b000; /* XXX not in prom? */
- p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000);
+
+ info->cmap_regs_phys = 0xf301b000; /* XXX not in prom? */
+ info->cmap_regs = ioremap(info->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");
+ out_be32(&info->platinum_regs->reg[16].r, (unsigned)info->frame_buffer_phys);
+ out_be32(&info->platinum_regs->reg[20].r, 0x1011); /* select max vram */
+ out_be32(&info->platinum_regs->reg[24].r, 0); /* switch in vram */
+
+ info->base_frame_buffer[0x100000] = 0x34;
+ info->base_frame_buffer[0x100008] = 0x0;
+ invalidate_cache(&info->base_frame_buffer[0x100000]);
+ info->base_frame_buffer[0x200000] = 0x56;
+ info->base_frame_buffer[0x200008] = 0x0;
+ invalidate_cache(&info->base_frame_buffer[0x200000]);
+ info->base_frame_buffer[0x300000] = 0x78;
+ info->base_frame_buffer[0x300008] = 0x0;
+ invalidate_cache(&info->base_frame_buffer[0x300000]);
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);
+ bank1 = info->base_frame_buffer[0x100000] == 0x34;
+ bank2 = info->base_frame_buffer[0x200000] == 0x56;
+ bank3 = info->base_frame_buffer[0x300000] == 0x78;
+ info->total_vram = (bank0 + bank1 + bank2 + bank3) * 0x100000;
+ printk(KERN_INFO "Total VRAM = %dMB %d%d%d%d\n", (int) (info->total_vram / 1024 / 1024), bank3, bank2, bank1, bank0);
-// p->frame_buffer = p->base_frame_buffer
-// + platinum_reg_init[p->par.vmode-1]->fb_offset;
+ /*
+ * Try to determine whether we have an old or a new DACula.
+ */
+ out_8(&info->cmap_regs->addr, 0x40);
+ info->dactype = in_8(&info->cmap_regs->d2);
+ switch (info->dactype) {
+ case 0x3c:
+ info->clktype = 1;
+ break;
+ case 0x84:
+ info->clktype = 0;
+ break;
+ default:
+ info->clktype = 0;
+ printk(KERN_INFO "Unknown DACula type: %x\n", info->dactype);
+ break;
+ }
+
+ if (!init_platinum(info)) {
+ kfree(info);
+ return;
+ }
#ifdef CONFIG_FB_COMPAT_XPMAC
-#if 0
- console_set_cmap_ptr = platinum_set_cmap;
- console_setmode_ptr = platinum_console_setmode;
+ if (!console_fb_info)
+ console_fb_info = &info->fb_info;
#endif
-#endif /* CONFIG_FB_COMPAT_XPMAC */
-
- init_platinum(p);
}
/*
@@ -666,387 +758,141 @@ __initfunc(void platinum_of_init(struct device_node *dp))
* 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)
+static int read_platinum_sense(struct fb_info_platinum *info)
{
+ volatile struct platinum_regs *platinum_regs = info->platinum_regs;
int sense;
- out_be32(&p->platinum_regs->reg[23].r, 7); /* turn off drivers */
+ out_be32(&platinum_regs->reg[23].r, 7); /* turn off drivers */
__delay(2000);
- sense = (~in_be32(&p->platinum_regs->reg[23].r) & 7) << 8;
+ sense = (~in_be32(&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 */
+ out_be32(&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 */
+ sense |= (~in_be32(&platinum_regs->reg[23].r) & 3) << 4;
+ out_be32(&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 */
+ sense |= (~in_be32(&platinum_regs->reg[23].r) & 4) << 1;
+ sense |= (~in_be32(&platinum_regs->reg[23].r) & 1) << 2;
+ out_be32(&platinum_regs->reg[23].r, 6); /* drive C low */
__delay(2000);
- sense |= (~in_be32(&p->platinum_regs->reg[23].r) & 6) >> 1;
+ sense |= (~in_be32(&platinum_regs->reg[23].r) & 6) >> 1;
- out_be32(&p->platinum_regs->reg[23].r, 7); /* turn off drivers */
+ out_be32(&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");
+static int platinum_var_to_par(const struct fb_var_screeninfo *var,
+ struct fb_par_platinum *par,
+ const struct fb_info_platinum *info)
+{
+ if(mac_var_to_vmode(var, &par->vmode, &par->cmode) != 0) {
+ printk(KERN_ERR "platinum_var_to_par: mac_var_to_vmode unsuccessful.\n");
+ printk(KERN_ERR "platinum_var_to_par: var->xres = %d\n", var->xres);
+ printk(KERN_ERR "platinum_var_to_par: var->yres = %d\n", var->yres);
+ printk(KERN_ERR "platinum_var_to_par: var->xres_virtual = %d\n", var->xres_virtual);
+ printk(KERN_ERR "platinum_var_to_par: var->yres_virtual = %d\n", var->yres_virtual);
+ printk(KERN_ERR "platinum_var_to_par: var->bits_per_pixel = %d\n", var->bits_per_pixel);
+ printk(KERN_ERR "platinum_var_to_par: var->pixclock = %d\n", var->pixclock);
+ printk(KERN_ERR "platinum_var_to_par: var->vmode = %d\n", var->vmode);
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)
+ if(!platinum_reg_init[par->vmode-1]) {
+ printk(KERN_ERR "platinum_var_to_par, vmode %d not valid.\n", par->vmode);
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");
+ if (platinum_vram_reqd(par->vmode, par->cmode) > info->total_vram) {
+ printk(KERN_ERR "platinum_var_to_par, not enough ram for vmode %d, cmode %d.\n", par->vmode, par->cmode);
return -EINVAL;
}
- par->xres = xres;
- par->yres = yres;
- par->vxres = xres;
- par->vyres = yres;
+ par->xres = vmode_attrs[par->vmode-1].hres;
+ par->yres = vmode_attrs[par->vmode-1].vres;
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;
+ par->vxres = par->xres;
+ par->vyres = par->yres;
- 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)
+static int platinum_par_to_var(struct fb_var_screeninfo *var,
+ const struct fb_par_platinum *par,
+ const struct fb_info_platinum *info)
{
-// FUNCID;
- mac_vmode_to_var(par->vmode, par->cmode, var);
+ return 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)
+static int platinum_encode_fix(struct fb_fix_screeninfo *fix,
+ const struct fb_par_platinum *par,
+ const struct fb_info_platinum *info)
{
-// FUNCID;
memset(fix, 0, sizeof(*fix));
strcpy(fix->id, "platinum");
- fix->mmio_start = (char *)p->platinum_regs_phys;
+ fix->smem_start = (void *) (info->frame_buffer_phys + 0x1000);
+ fix->smem_len = (u32) info->total_vram - 0x1000;
+ fix->mmio_start = (char *) (info->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];
-
-}
+ fix->line_length = vmode_attrs[par->vmode-1].hres * (1<<par->cmode) + 0x20;
-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;
- }
+ return 0;
}
-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)
+/*
+ * Parse user speficied options (`video=platinumfb:')
+ */
+__initfunc(void platinum_setup(char *options, int *ints))
{
-// FUNCID;
- if(init) {
- platinum_init_fix(&p->fix, p);
- }
- platinum_par_to_fix(&p->par, &p->fix, p);
+ char *this_opt;
- platinum_par_to_var(&p->par, &p->var);
+ if (!options || !*options)
+ return;
- 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);
+ 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 (!strncmp(this_opt, "vmode:", 6)) {
+ int vmode = simple_strtoul(this_opt+6, NULL, 0);
+ if (vmode > 0 && vmode <= VMODE_MAX)
+ default_vmode = vmode;
+ } else if (!strncmp(this_opt, "cmode:", 6)) {
+ int depth = simple_strtoul(this_opt+6, NULL, 0);
+ switch (depth) {
+ case 8:
+ default_cmode = CMODE_8;
+ break;
+ case 15:
+ case 16:
+ default_cmode = CMODE_16;
+ break;
+ case 24:
+ case 32:
+ default_cmode = CMODE_32;
+ break;
+ }
+ }
}
}
-
-#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
index a9b4b1c8f..d3aa5c3ef 100644
--- a/drivers/video/platinumfb.h
+++ b/drivers/video/platinumfb.h
@@ -311,8 +311,6 @@ static struct platinum_regvals platinum_reg_init_1 = {
{{ 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,
@@ -366,34 +364,3 @@ struct vmode_attr vmode_attrs[VMODE_MAX] = {
{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/promcon.c b/drivers/video/promcon.c
index 76f945b45..9148f609e 100644
--- a/drivers/video/promcon.c
+++ b/drivers/video/promcon.c
@@ -1,4 +1,4 @@
-/* $Id: promcon.c,v 1.10 1998/07/24 15:31:53 jj Exp $
+/* $Id: promcon.c,v 1.12 1998/08/23 20:19:01 mj Exp $
* Console driver utilizing PROM sun terminal emulation
*
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
@@ -178,8 +178,6 @@ promcon_init(struct vc_data *conp, int init)
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);
}
}
diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c
index 548f88602..8bfffe147 100644
--- a/drivers/video/retz3fb.c
+++ b/drivers/video/retz3fb.c
@@ -36,12 +36,13 @@
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/pgtable.h>
+#include <asm/io.h>
-#include "retz3fb.h"
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include "retz3fb.h"
/* #define DEBUG if(1) */
#define DEBUG if(0)
@@ -98,38 +99,26 @@ struct display_data {
long v_dispend; /* Horizontal Display End */
};
-static struct retz3fb_par current_par;
-
-static int current_par_valid = 0;
-static int currcon = 0;
-
-static struct display disp;
-static struct fb_info fb_info;
-
-
-/*
- * Switch for Chipset Independency
- */
-
-static struct fb_hwswitch {
-
- /* Initialisation */
+struct retz3_fb_info {
+ struct fb_info info;
+ unsigned long base;
+ unsigned long fbmem;
+ unsigned long fbsize;
+ volatile unsigned char *regs;
+ unsigned long physfbmem;
+ unsigned long physregs;
+ int currcon;
+ int current_par_valid; /* set to 0 by memset */
+ struct display disp;
+ struct retz3fb_par current_par;
+ unsigned char color_table [256][3];
+};
- int (*init)(void);
- /* Display Control */
+static char fontname[40] __initdata = { 0 };
- int (*encode_fix)(struct fb_fix_screeninfo *fix, struct retz3fb_par *par);
- int (*decode_var)(struct fb_var_screeninfo *var, struct retz3fb_par *par);
- int (*encode_var)(struct fb_var_screeninfo *var, struct retz3fb_par *par);
- int (*getcolreg)(unsigned int regno, unsigned int *red, unsigned
- int *green, unsigned int *blue, unsigned int *transp,
- struct fb_info *info);
- int (*setcolreg)(unsigned int regno, unsigned int red, unsigned int
- green, unsigned int blue, unsigned int transp,
- struct fb_info *info);
- void (*blank)(int blank);
-} *fbhw;
+#define retz3info(info) ((struct retz3_fb_info *)(info))
+#define fbinfo(info) ((struct fb_info *)(info))
/*
@@ -139,13 +128,6 @@ static struct fb_hwswitch {
static char retz3fb_name[16] = "RetinaZ3";
-static unsigned char retz3_color_table [256][4];
-static unsigned long z3_mem;
-static unsigned long z3_fbmem;
-static unsigned long z3_size;
-static volatile unsigned char *z3_regs;
-
-
/*
* A small info on how to convert XFree86 timing values into fb
* timings - by Frank Neumann:
@@ -197,7 +179,7 @@ static struct fb_videomode retz3fb_predefined[] __initdata = {
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_ACCELF_TEXT, 38461, 28, 32, 12, 10, 96, 2,
- FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
}
},
/*
@@ -228,14 +210,14 @@ static struct fb_videomode retz3fb_predefined[] __initdata = {
640, 480, 640, 480, 0, 0, 16, 0,
{11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
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
+ 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, 0, 38461/3, 28, 32, 12, 10, 96, 2,
- FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
}
},
};
@@ -297,7 +279,7 @@ static struct display_switch fbcon_retz3_8;
* Accelerated Functions used by the low level console driver
*/
-static void retz3_bitblt(struct fb_var_screeninfo *scr,
+static void retz3_bitblt(struct display *p,
unsigned short curx, unsigned short cury, unsigned
short destx, unsigned short desty, unsigned short
width, unsigned short height, unsigned short cmd,
@@ -307,29 +289,28 @@ static void retz3_bitblt(struct fb_var_screeninfo *scr,
* Hardware Specific Routines
*/
-static int retz3_init(void);
-static int retz3_encode_fix(struct fb_fix_screeninfo *fix,
- struct retz3fb_par *par);
+static int retz3_encode_fix(struct fb_info *info,
+ struct fb_fix_screeninfo *fix,
+ struct retz3fb_par *par);
static int retz3_decode_var(struct fb_var_screeninfo *var,
- struct retz3fb_par *par);
+ struct retz3fb_par *par);
static int retz3_encode_var(struct fb_var_screeninfo *var,
- struct retz3fb_par *par);
+ struct retz3fb_par *par);
static int retz3_getcolreg(unsigned int regno, unsigned int *red,
unsigned int *green, unsigned int *blue,
unsigned int *transp, struct fb_info *info);
static int retz3_setcolreg(unsigned int regno, unsigned int red,
unsigned int green, unsigned int blue,
unsigned int transp, struct fb_info *info);
-static void retz3_blank(int blank);
-
/*
* Internal routines
*/
-static void retz3fb_get_par(struct retz3fb_par *par);
-static void retz3fb_set_par(struct retz3fb_par *par);
-static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
+static void retz3fb_get_par(struct fb_info *info, struct retz3fb_par *par);
+static void retz3fb_set_par(struct fb_info *info, struct retz3fb_par *par);
+static int do_fb_set_var(struct fb_info *info,
+ struct fb_var_screeninfo *var, int isactive);
static void do_install_cmap(int con, struct fb_info *info);
static void retz3fb_set_disp(int con, struct fb_info *info);
static int get_video_mode(const char *name);
@@ -381,12 +362,11 @@ static unsigned short find_fq(unsigned int freq)
}
-static int retz3_set_video(struct fb_var_screeninfo *var,
+static int retz3_set_video(struct fb_info *info,
+ struct fb_var_screeninfo *var,
struct retz3fb_par *par)
{
-#if 0
- float freq_f;
-#endif
+ volatile unsigned char *regs = retz3info(info)->regs;
unsigned int freq;
int xres, hfront, hsync, hback;
@@ -482,11 +462,11 @@ static int retz3_set_video(struct fb_var_screeninfo *var,
if (data.v_total >= 1024)
printk("MAYDAY: v_total >= 1024; bailing out!\n");
- reg_w(GREG_MISC_OUTPUT_W, 0xe3 | ((clocksel & 3) * 0x04));
- reg_w(GREG_FEATURE_CONTROL_W, 0x00);
+ reg_w(regs, GREG_MISC_OUTPUT_W, 0xe3 | ((clocksel & 3) * 0x04));
+ reg_w(regs, GREG_FEATURE_CONTROL_W, 0x00);
- seq_w(SEQ_RESET, 0x00);
- seq_w(SEQ_RESET, 0x03); /* reset sequencer logic */
+ seq_w(regs, SEQ_RESET, 0x00);
+ seq_w(regs, SEQ_RESET, 0x03); /* reset sequencer logic */
/*
* CLOCKING_MODE bits:
@@ -495,32 +475,32 @@ static int retz3_set_video(struct fb_var_screeninfo *var,
* (The CL drivers sets it to 0x21 with the comment:
* FullBandwidth (video off) and 8/9 dot clock)
*/
- seq_w(SEQ_CLOCKING_MODE, 0x01 | 0x00 /* 0x08 */);
+ seq_w(regs, SEQ_CLOCKING_MODE, 0x01 | 0x00 /* 0x08 */);
- seq_w(SEQ_MAP_MASK, 0x0f); /* enable writing to plane 0-3 */
- seq_w(SEQ_CHAR_MAP_SELECT, 0x00); /* doesn't matter in gfx-mode */
- seq_w(SEQ_MEMORY_MODE, 0x06); /* CL driver says 0x0e for 256 col mode*/
- seq_w(SEQ_RESET, 0x01);
- seq_w(SEQ_RESET, 0x03);
+ seq_w(regs, SEQ_MAP_MASK, 0x0f); /* enable writing to plane 0-3 */
+ seq_w(regs, SEQ_CHAR_MAP_SELECT, 0x00); /* doesn't matter in gfx-mode */
+ seq_w(regs, SEQ_MEMORY_MODE, 0x06); /* CL driver says 0x0e for 256 col mode*/
+ seq_w(regs, SEQ_RESET, 0x01);
+ seq_w(regs, SEQ_RESET, 0x03);
- seq_w(SEQ_EXTENDED_ENABLE, 0x05);
+ seq_w(regs, SEQ_EXTENDED_ENABLE, 0x05);
- seq_w(SEQ_CURSOR_CONTROL, 0x00); /* disable cursor */
- seq_w(SEQ_PRIM_HOST_OFF_HI, 0x00);
- seq_w(SEQ_PRIM_HOST_OFF_HI, 0x00);
- seq_w(SEQ_LINEAR_0, 0x4a);
- seq_w(SEQ_LINEAR_1, 0x00);
+ seq_w(regs, SEQ_CURSOR_CONTROL, 0x00); /* disable cursor */
+ seq_w(regs, SEQ_PRIM_HOST_OFF_HI, 0x00);
+ seq_w(regs, SEQ_PRIM_HOST_OFF_HI, 0x00);
+ seq_w(regs, SEQ_LINEAR_0, 0x4a);
+ seq_w(regs, SEQ_LINEAR_1, 0x00);
- seq_w(SEQ_SEC_HOST_OFF_HI, 0x00);
- seq_w(SEQ_SEC_HOST_OFF_LO, 0x00);
- seq_w(SEQ_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
+ seq_w(regs, SEQ_SEC_HOST_OFF_HI, 0x00);
+ seq_w(regs, SEQ_SEC_HOST_OFF_LO, 0x00);
+ seq_w(regs, SEQ_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
/*
* The lower 4 bits (0-3) are used to set the font-width for
* text-mode - DON'T try to set this for gfx-mode.
*/
- seq_w(SEQ_EXT_CLOCK_MODE, 0x10);
- seq_w(SEQ_EXT_VIDEO_ADDR, 0x03);
+ seq_w(regs, SEQ_EXT_CLOCK_MODE, 0x10);
+ seq_w(regs, SEQ_EXT_VIDEO_ADDR, 0x03);
/*
* Extended Pixel Control:
@@ -528,52 +508,52 @@ static int retz3_set_video(struct fb_var_screeninfo *var,
* bit 1: (Packed/Nibble Pixel Format ?)
* bit 4-5: depth, 0=1-8bpp, 1=9-16bpp, 2=17-24bpp
*/
- seq_w(SEQ_EXT_PIXEL_CNTL, 0x01 | (((bpp / 8) - 1) << 4));
-
- seq_w(SEQ_BUS_WIDTH_FEEDB, 0x04);
- seq_w(SEQ_COLOR_EXP_WFG, 0x01);
- seq_w(SEQ_COLOR_EXP_WBG, 0x00);
- seq_w(SEQ_EXT_RW_CONTROL, 0x00);
- seq_w(SEQ_MISC_FEATURE_SEL, (0x51 | (clocksel & 8)));
- seq_w(SEQ_COLOR_KEY_CNTL, 0x40);
- seq_w(SEQ_COLOR_KEY_MATCH0, 0x00);
- seq_w(SEQ_COLOR_KEY_MATCH1, 0x00);
- seq_w(SEQ_COLOR_KEY_MATCH2, 0x00);
- seq_w(SEQ_CRC_CONTROL, 0x00);
- seq_w(SEQ_PERF_SELECT, 0x10);
- seq_w(SEQ_ACM_APERTURE_1, 0x00);
- seq_w(SEQ_ACM_APERTURE_2, 0x30);
- seq_w(SEQ_ACM_APERTURE_3, 0x00);
- seq_w(SEQ_MEMORY_MAP_CNTL, 0x03);
+ seq_w(regs, SEQ_EXT_PIXEL_CNTL, 0x01 | (((bpp / 8) - 1) << 4));
+
+ seq_w(regs, SEQ_BUS_WIDTH_FEEDB, 0x04);
+ seq_w(regs, SEQ_COLOR_EXP_WFG, 0x01);
+ seq_w(regs, SEQ_COLOR_EXP_WBG, 0x00);
+ seq_w(regs, SEQ_EXT_RW_CONTROL, 0x00);
+ seq_w(regs, SEQ_MISC_FEATURE_SEL, (0x51 | (clocksel & 8)));
+ seq_w(regs, SEQ_COLOR_KEY_CNTL, 0x40);
+ seq_w(regs, SEQ_COLOR_KEY_MATCH0, 0x00);
+ seq_w(regs, SEQ_COLOR_KEY_MATCH1, 0x00);
+ seq_w(regs, SEQ_COLOR_KEY_MATCH2, 0x00);
+ seq_w(regs, SEQ_CRC_CONTROL, 0x00);
+ seq_w(regs, SEQ_PERF_SELECT, 0x10);
+ seq_w(regs, SEQ_ACM_APERTURE_1, 0x00);
+ seq_w(regs, SEQ_ACM_APERTURE_2, 0x30);
+ seq_w(regs, SEQ_ACM_APERTURE_3, 0x00);
+ seq_w(regs, SEQ_MEMORY_MAP_CNTL, 0x03);
/* unlock register CRT0..CRT7 */
- crt_w(CRT_END_VER_RETR, (data.v_sstop & 0x0f) | 0x20);
+ crt_w(regs, CRT_END_VER_RETR, (data.v_sstop & 0x0f) | 0x20);
/* Zuerst zu schreibende Werte nur per printk ausgeben */
DEBUG printk("CRT_HOR_TOTAL: %ld\n", data.h_total);
- crt_w(CRT_HOR_TOTAL, data.h_total & 0xff);
+ crt_w(regs, CRT_HOR_TOTAL, data.h_total & 0xff);
DEBUG printk("CRT_HOR_DISP_ENA_END: %ld\n", data.h_dispend);
- crt_w(CRT_HOR_DISP_ENA_END, (data.h_dispend) & 0xff);
+ crt_w(regs, CRT_HOR_DISP_ENA_END, (data.h_dispend) & 0xff);
DEBUG printk("CRT_START_HOR_BLANK: %ld\n", data.h_bstart);
- crt_w(CRT_START_HOR_BLANK, data.h_bstart & 0xff);
+ crt_w(regs, CRT_START_HOR_BLANK, data.h_bstart & 0xff);
DEBUG printk("CRT_END_HOR_BLANK: 128+%ld\n", data.h_bstop % 32);
- crt_w(CRT_END_HOR_BLANK, 0x80 | (data.h_bstop & 0x1f));
+ crt_w(regs, CRT_END_HOR_BLANK, 0x80 | (data.h_bstop & 0x1f));
DEBUG printk("CRT_START_HOR_RETR: %ld\n", data.h_sstart);
- crt_w(CRT_START_HOR_RETR, data.h_sstart & 0xff);
+ crt_w(regs, CRT_START_HOR_RETR, data.h_sstart & 0xff);
tmp = (data.h_sstop & 0x1f);
if (data.h_bstop & 0x20)
tmp |= 0x80;
DEBUG printk("CRT_END_HOR_RETR: %d\n", tmp);
- crt_w(CRT_END_HOR_RETR, tmp);
+ crt_w(regs, CRT_END_HOR_RETR, tmp);
DEBUG printk("CRT_VER_TOTAL: %ld\n", data.v_total & 0xff);
- crt_w(CRT_VER_TOTAL, (data.v_total & 0xff));
+ crt_w(regs, CRT_VER_TOTAL, (data.v_total & 0xff));
tmp = 0x10; /* LineCompare bit #9 */
if (data.v_total & 256)
@@ -591,9 +571,9 @@ static int retz3_set_video(struct fb_var_screeninfo *var,
if (data.v_sstart & 512)
tmp |= 0x80;
DEBUG printk("CRT_OVERFLOW: %d\n", tmp);
- crt_w(CRT_OVERFLOW, tmp);
+ crt_w(regs, CRT_OVERFLOW, tmp);
- crt_w(CRT_PRESET_ROW_SCAN, 0x00); /* not CL !!! */
+ crt_w(regs, CRT_PRESET_ROW_SCAN, 0x00); /* not CL !!! */
tmp = 0x40; /* LineCompare bit #8 */
if (data.v_bstart & 512)
@@ -601,47 +581,47 @@ static int retz3_set_video(struct fb_var_screeninfo *var,
if (var->vmode & FB_VMODE_DOUBLE)
tmp |= 0x80;
DEBUG printk("CRT_MAX_SCAN_LINE: %d\n", tmp);
- crt_w(CRT_MAX_SCAN_LINE, tmp);
+ crt_w(regs, CRT_MAX_SCAN_LINE, tmp);
- crt_w(CRT_CURSOR_START, 0x00);
- crt_w(CRT_CURSOR_END, 8 & 0x1f); /* font height */
+ crt_w(regs, CRT_CURSOR_START, 0x00);
+ crt_w(regs, CRT_CURSOR_END, 8 & 0x1f); /* font height */
- crt_w(CRT_START_ADDR_HIGH, 0x00);
- crt_w(CRT_START_ADDR_LOW, 0x00);
+ crt_w(regs, CRT_START_ADDR_HIGH, 0x00);
+ crt_w(regs, CRT_START_ADDR_LOW, 0x00);
- crt_w(CRT_CURSOR_LOC_HIGH, 0x00);
- crt_w(CRT_CURSOR_LOC_LOW, 0x00);
+ crt_w(regs, CRT_CURSOR_LOC_HIGH, 0x00);
+ crt_w(regs, CRT_CURSOR_LOC_LOW, 0x00);
DEBUG printk("CRT_START_VER_RETR: %ld\n", data.v_sstart & 0xff);
- crt_w(CRT_START_VER_RETR, (data.v_sstart & 0xff));
+ crt_w(regs, CRT_START_VER_RETR, (data.v_sstart & 0xff));
#if 1
/* 5 refresh cycles per scanline */
DEBUG printk("CRT_END_VER_RETR: 64+32+%ld\n", data.v_sstop % 16);
- crt_w(CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 0x40 | 0x20));
+ crt_w(regs, CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 0x40 | 0x20));
#else
DEBUG printk("CRT_END_VER_RETR: 128+32+%ld\n", data.v_sstop % 16);
- crt_w(CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 128 | 32));
+ crt_w(regs, CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 128 | 32));
#endif
DEBUG printk("CRT_VER_DISP_ENA_END: %ld\n", data.v_dispend & 0xff);
- crt_w(CRT_VER_DISP_ENA_END, (data.v_dispend & 0xff));
+ crt_w(regs, CRT_VER_DISP_ENA_END, (data.v_dispend & 0xff));
DEBUG printk("CRT_START_VER_BLANK: %ld\n", data.v_bstart & 0xff);
- crt_w(CRT_START_VER_BLANK, (data.v_bstart & 0xff));
+ crt_w(regs, CRT_START_VER_BLANK, (data.v_bstart & 0xff));
DEBUG printk("CRT_END_VER_BLANK: %ld\n", data.v_bstop & 0xff);
- crt_w(CRT_END_VER_BLANK, (data.v_bstop & 0xff));
+ crt_w(regs, CRT_END_VER_BLANK, (data.v_bstop & 0xff));
DEBUG printk("CRT_MODE_CONTROL: 0xe3\n");
- crt_w(CRT_MODE_CONTROL, 0xe3);
+ crt_w(regs, CRT_MODE_CONTROL, 0xe3);
DEBUG printk("CRT_LINE_COMPARE: 0xff\n");
- crt_w(CRT_LINE_COMPARE, 0xff);
+ crt_w(regs, CRT_LINE_COMPARE, 0xff);
tmp = (var->xres_virtual / 8) * (bpp / 8);
- crt_w(CRT_OFFSET, tmp);
+ crt_w(regs, CRT_OFFSET, tmp);
- crt_w(CRT_UNDERLINE_LOC, 0x07); /* probably font-height - 1 */
+ crt_w(regs, CRT_UNDERLINE_LOC, 0x07); /* probably font-height - 1 */
tmp = 0x20; /* Enable extended end bits */
if (data.h_total & 0x100)
@@ -655,12 +635,12 @@ static int retz3_set_video(struct fb_var_screeninfo *var,
if (var->vmode & FB_VMODE_INTERLACED)
tmp |= 0x10;
DEBUG printk("CRT_EXT_HOR_TIMING1: %d\n", tmp);
- crt_w(CRT_EXT_HOR_TIMING1, tmp);
+ crt_w(regs, CRT_EXT_HOR_TIMING1, tmp);
tmp = 0x00;
if (((var->xres_virtual / 8) * (bpp / 8)) & 0x100)
tmp |= 0x10;
- crt_w(CRT_EXT_START_ADDR, tmp);
+ crt_w(regs, CRT_EXT_START_ADDR, tmp);
tmp = 0x00;
if (data.h_total & 0x200)
@@ -673,7 +653,7 @@ static int retz3_set_video(struct fb_var_screeninfo *var,
tmp |= 0x08;
tmp |= ((data.h_bstop & 0xc0) >> 2);
tmp |= ((data.h_sstop & 0x60) << 1);
- crt_w(CRT_EXT_HOR_TIMING2, tmp);
+ crt_w(regs, CRT_EXT_HOR_TIMING2, tmp);
DEBUG printk("CRT_EXT_HOR_TIMING2: %d\n", tmp);
tmp = 0x10; /* Line compare bit 10 */
@@ -688,139 +668,84 @@ static int retz3_set_video(struct fb_var_screeninfo *var,
tmp |= ((data.v_bstop & 0x300) >> 3);
if (data.v_sstop & 0x10)
tmp |= 0x80;
- crt_w(CRT_EXT_VER_TIMING, tmp);
+ crt_w(regs, CRT_EXT_VER_TIMING, tmp);
DEBUG printk("CRT_EXT_VER_TIMING: %d\n", tmp);
- crt_w(CRT_MONITOR_POWER, 0x00);
+ crt_w(regs, CRT_MONITOR_POWER, 0x00);
/*
* Convert from ps to Hz.
*/
-#if 0
- freq_f = (1.0/(float)var->pixclock) * 1000000000;
- freq = ((unsigned int)freq_f) * 1000;
-#else
freq = 2000000000 / var->pixclock;
freq = freq * 500;
-#endif
best_freq = find_fq(freq);
- pll_w(0x02, best_freq);
+ pll_w(regs, 0x02, best_freq);
best_freq = find_fq(61000000);
- pll_w(0x0a, best_freq);
- pll_w(0x0e, 0x22);
-
- gfx_w(GFX_SET_RESET, 0x00);
- gfx_w(GFX_ENABLE_SET_RESET, 0x00);
- gfx_w(GFX_COLOR_COMPARE, 0x00);
- gfx_w(GFX_DATA_ROTATE, 0x00);
- gfx_w(GFX_READ_MAP_SELECT, 0x00);
- gfx_w(GFX_GRAPHICS_MODE, 0x00);
- gfx_w(GFX_MISC, 0x05);
- gfx_w(GFX_COLOR_XCARE, 0x0f);
- gfx_w(GFX_BITMASK, 0xff);
-
- reg_r(ACT_ADDRESS_RESET);
- attr_w(ACT_PALETTE0 , 0x00);
- attr_w(ACT_PALETTE1 , 0x01);
- attr_w(ACT_PALETTE2 , 0x02);
- attr_w(ACT_PALETTE3 , 0x03);
- attr_w(ACT_PALETTE4 , 0x04);
- attr_w(ACT_PALETTE5 , 0x05);
- attr_w(ACT_PALETTE6 , 0x06);
- attr_w(ACT_PALETTE7 , 0x07);
- attr_w(ACT_PALETTE8 , 0x08);
- attr_w(ACT_PALETTE9 , 0x09);
- attr_w(ACT_PALETTE10, 0x0a);
- attr_w(ACT_PALETTE11, 0x0b);
- attr_w(ACT_PALETTE12, 0x0c);
- attr_w(ACT_PALETTE13, 0x0d);
- attr_w(ACT_PALETTE14, 0x0e);
- attr_w(ACT_PALETTE15, 0x0f);
- reg_r(ACT_ADDRESS_RESET);
-
- attr_w(ACT_ATTR_MODE_CNTL, 0x09); /* 0x01 for CL */
-
- attr_w(ACT_OVERSCAN_COLOR, 0x00);
- attr_w(ACT_COLOR_PLANE_ENA, 0x0f);
- attr_w(ACT_HOR_PEL_PANNING, 0x00);
- attr_w(ACT_COLOR_SELECT, 0x00);
-
- reg_r(ACT_ADDRESS_RESET);
- reg_w(ACT_DATA, 0x20);
-
- reg_w(VDAC_MASK, 0xff);
+ pll_w(regs, 0x0a, best_freq);
+ pll_w(regs, 0x0e, 0x22);
+
+ gfx_w(regs, GFX_SET_RESET, 0x00);
+ gfx_w(regs, GFX_ENABLE_SET_RESET, 0x00);
+ gfx_w(regs, GFX_COLOR_COMPARE, 0x00);
+ gfx_w(regs, GFX_DATA_ROTATE, 0x00);
+ gfx_w(regs, GFX_READ_MAP_SELECT, 0x00);
+ gfx_w(regs, GFX_GRAPHICS_MODE, 0x00);
+ gfx_w(regs, GFX_MISC, 0x05);
+ gfx_w(regs, GFX_COLOR_XCARE, 0x0f);
+ gfx_w(regs, GFX_BITMASK, 0xff);
+
+ reg_r(regs, ACT_ADDRESS_RESET);
+ attr_w(regs, ACT_PALETTE0 , 0x00);
+ attr_w(regs, ACT_PALETTE1 , 0x01);
+ attr_w(regs, ACT_PALETTE2 , 0x02);
+ attr_w(regs, ACT_PALETTE3 , 0x03);
+ attr_w(regs, ACT_PALETTE4 , 0x04);
+ attr_w(regs, ACT_PALETTE5 , 0x05);
+ attr_w(regs, ACT_PALETTE6 , 0x06);
+ attr_w(regs, ACT_PALETTE7 , 0x07);
+ attr_w(regs, ACT_PALETTE8 , 0x08);
+ attr_w(regs, ACT_PALETTE9 , 0x09);
+ attr_w(regs, ACT_PALETTE10, 0x0a);
+ attr_w(regs, ACT_PALETTE11, 0x0b);
+ attr_w(regs, ACT_PALETTE12, 0x0c);
+ attr_w(regs, ACT_PALETTE13, 0x0d);
+ attr_w(regs, ACT_PALETTE14, 0x0e);
+ attr_w(regs, ACT_PALETTE15, 0x0f);
+ reg_r(regs, ACT_ADDRESS_RESET);
+
+ attr_w(regs, ACT_ATTR_MODE_CNTL, 0x09); /* 0x01 for CL */
+
+ attr_w(regs, ACT_OVERSCAN_COLOR, 0x00);
+ attr_w(regs, ACT_COLOR_PLANE_ENA, 0x0f);
+ attr_w(regs, ACT_HOR_PEL_PANNING, 0x00);
+ attr_w(regs, ACT_COLOR_SELECT, 0x00);
+
+ reg_r(regs, ACT_ADDRESS_RESET);
+ reg_w(regs, ACT_DATA, 0x20);
+
+ reg_w(regs, VDAC_MASK, 0xff);
/*
* Extended palette adressing ???
*/
switch (bpp){
case 8:
- reg_w(0x83c6, 0x00);
+ reg_w(regs, 0x83c6, 0x00);
break;
case 16:
- reg_w(0x83c6, 0x60);
+ reg_w(regs, 0x83c6, 0x60);
break;
case 24:
- reg_w(0x83c6, 0xe0);
+ reg_w(regs, 0x83c6, 0xe0);
break;
default:
printk("Illegal color-depth: %i\n", bpp);
}
- reg_w(VDAC_ADDRESS, 0x00);
-
- seq_w(SEQ_MAP_MASK, 0x0f );
-
- return 0;
-}
-
-/*
- * Initialization
- *
- * Set the default video mode for this chipset. If a video mode was
- * specified on the command line, it will override the default mode.
- */
-
-static int retz3_init(void)
-{
- short i;
-#if 0
- volatile unsigned long *CursorBase;
-#endif
-
- for (i = 0; i < 256; i++){
- for (i = 0; i < 256; i++){
- retz3_color_table [i][0] = i;
- retz3_color_table [i][1] = i;
- retz3_color_table [i][2] = i;
- retz3_color_table [i][3] = 0;
- }
- }
-
- /* Disable hardware cursor */
+ reg_w(regs, VDAC_ADDRESS, 0x00);
- seq_w(SEQ_CURSOR_Y_INDEX, 0x00);
-
-#if 0
- /* Initialize hardware cursor */
- CursorBase = (unsigned long *)((char *)(z3_mem) + z3_size - 0x400);
- for (i=0; i < 8; i++){
- *(CursorBase +(i*4)) = 0xffffff00;
- *(CursorBase+1+(i*4)) = 0xffff0000;
- *(CursorBase+2+(i*4)) = 0xffff0000;
- *(CursorBase+3+(i*4)) = 0xffff0000;
- }
- for (i=8; i < 64; i++){
- *(CursorBase +(i*4)) = 0xffff0000;
- *(CursorBase+1+(i*4)) = 0xffff0000;
- *(CursorBase+2+(i*4)) = 0xffff0000;
- *(CursorBase+3+(i*4)) = 0xffff0000;
- }
-#endif
-
- retz3_setcolreg (255, 56, 100, 160, 0, NULL /* unused */);
- retz3_setcolreg (254, 0, 0, 0, 0, NULL /* unused */);
+ seq_w(regs, SEQ_MAP_MASK, 0x0f );
return 0;
}
@@ -831,14 +756,17 @@ static int retz3_init(void)
* values in the `par' structure.
*/
-static int retz3_encode_fix(struct fb_fix_screeninfo *fix,
+static int retz3_encode_fix(struct fb_info *info,
+ struct fb_fix_screeninfo *fix,
struct retz3fb_par *par)
{
+ struct retz3_fb_info *zinfo = retz3info(info);
+
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 = (char *)z3_regs;
+ fix->smem_start = (char *)(zinfo->physfbmem);
+ fix->smem_len = zinfo->fbsize;
+ fix->mmio_start = (char *)(zinfo->physregs);
fix->mmio_len = 0x00c00000;
fix->type = FB_TYPE_PACKED_PIXELS;
@@ -846,7 +774,7 @@ static int retz3_encode_fix(struct fb_fix_screeninfo *fix,
if (par->bpp == 8)
fix->visual = FB_VISUAL_PSEUDOCOLOR;
else
- fix->visual = FB_VISUAL_DIRECTCOLOR;
+ fix->visual = FB_VISUAL_TRUECOLOR;
fix->xpanstep = 0;
fix->ypanstep = 0;
@@ -944,29 +872,33 @@ static int retz3_encode_var(struct fb_var_screeninfo *var,
/*
- * 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.
+ * Set a single color register. Return != 0 for invalid regno.
*/
static int retz3_setcolreg(unsigned int regno, unsigned int red,
unsigned int green, unsigned int blue,
unsigned int transp, struct fb_info *info)
{
+ struct retz3_fb_info *zinfo = retz3info(info);
+ volatile unsigned char *regs = zinfo->regs;
+
/* We'll get to this */
if (regno > 255)
return 1;
- retz3_color_table [regno][0] = red & 0xff;
- retz3_color_table [regno][1] = green & 0xff;
- retz3_color_table [regno][2] = blue & 0xff;
- retz3_color_table [regno][3] = transp;
+ red >>= 10;
+ green >>= 10;
+ blue >>= 10;
- reg_w(VDAC_ADDRESS_W, regno);
- reg_w(VDAC_DATA, (red & 0xff) >> 2);
- reg_w(VDAC_DATA, (green & 0xff) >> 2);
- reg_w(VDAC_DATA, (blue & 0xff) >> 2);
+ zinfo->color_table[regno][0] = red;
+ zinfo->color_table[regno][1] = green;
+ zinfo->color_table[regno][2] = blue;
+
+ reg_w(regs, VDAC_ADDRESS_W, regno);
+ reg_w(regs, VDAC_DATA, red);
+ reg_w(regs, VDAC_DATA, green);
+ reg_w(regs, VDAC_DATA, blue);
return 0;
}
@@ -981,50 +913,32 @@ static int retz3_getcolreg(unsigned int regno, unsigned int *red,
unsigned int *green, unsigned int *blue,
unsigned int *transp, struct fb_info *info)
{
+ struct retz3_fb_info *zinfo = retz3info(info);
+ int t;
+
if (regno > 255)
return 1;
- *red = retz3_color_table [regno][0];
- *green = retz3_color_table [regno][1];
- *blue = retz3_color_table [regno][2];
- *transp = retz3_color_table [regno][3];
+ t = zinfo->color_table[regno][0];
+ *red = (t<<10) | (t<<4) | (t>>2);
+ t = zinfo->color_table[regno][1];
+ *green = (t<<10) | (t<<4) | (t>>2);
+ t = zinfo->color_table[regno][2];
+ *blue = (t<<10) | (t<<4) | (t>>2);
+ *transp = 0;
return 0;
}
-/*
- * (Un)Blank the screen
- */
-
-void retz3_blank(int blank)
-{
- short i;
-
- if (blank)
- for (i = 0; i < 256; i++){
- reg_w(VDAC_ADDRESS_W, i);
- reg_w(VDAC_DATA, 0);
- reg_w(VDAC_DATA, 0);
- reg_w(VDAC_DATA, 0);
- }
- else
- for (i = 0; i < 256; i++){
- reg_w(VDAC_ADDRESS_W, i);
- reg_w(VDAC_DATA, retz3_color_table [i][0] >> 2);
- reg_w(VDAC_DATA, retz3_color_table [i][1] >> 2);
- reg_w(VDAC_DATA, retz3_color_table [i][2] >> 2);
- }
-}
-
-
-static void retz3_bitblt (struct fb_var_screeninfo *var,
+static void retz3_bitblt (struct display *p,
unsigned short srcx, unsigned short srcy,
unsigned short destx, unsigned short desty,
unsigned short width, unsigned short height,
unsigned short cmd, unsigned short mask)
{
-
- volatile unsigned long *acm = (unsigned long *) (z3_mem + ACM_OFFSET);
- unsigned long *pattern = (unsigned long *)(z3_fbmem + PAT_MEM_OFF);
+ struct fb_var_screeninfo *var = &p->var;
+ struct retz3_fb_info *zinfo = retz3info(p->fb_info);
+ volatile unsigned long *acm = (unsigned long *)(zinfo->base + ACM_OFFSET);
+ unsigned long *pattern = (unsigned long *)(zinfo->fbmem + PAT_MEM_OFF);
unsigned short mod;
unsigned long tmp;
@@ -1127,55 +1041,50 @@ static void retz3_MoveCursor (unsigned short x, unsigned short y)
}
#endif
-/* -------------------- Interfaces to hardware functions -------------------- */
-
-
-static struct fb_hwswitch retz3_switch = {
- retz3_init, retz3_encode_fix, retz3_decode_var, retz3_encode_var,
- retz3_getcolreg, retz3_setcolreg, retz3_blank
-};
-
-
-/* -------------------- Generic routines ------------------------------------ */
-
/*
* Fill the hardware's `par' structure.
*/
-static void retz3fb_get_par(struct retz3fb_par *par)
+static void retz3fb_get_par(struct fb_info *info, struct retz3fb_par *par)
{
- if (current_par_valid)
- *par = current_par;
+ struct retz3_fb_info *zinfo = retz3info(info);
+
+ if (zinfo->current_par_valid)
+ *par = zinfo->current_par;
else
- fbhw->decode_var(&retz3fb_default, par);
+ retz3_decode_var(&retz3fb_default, par);
}
-static void retz3fb_set_par(struct retz3fb_par *par)
+static void retz3fb_set_par(struct fb_info *info, struct retz3fb_par *par)
{
- current_par = *par;
- current_par_valid = 1;
+ struct retz3_fb_info *zinfo = retz3info(info);
+
+ zinfo->current_par = *par;
+ zinfo->current_par_valid = 1;
}
-static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
+static int do_fb_set_var(struct fb_info *info,
+ struct fb_var_screeninfo *var, int isactive)
{
int err, activate;
struct retz3fb_par par;
+ struct retz3_fb_info *zinfo = retz3info(info);
- if ((err = fbhw->decode_var(var, &par)))
+ if ((err = retz3_decode_var(var, &par)))
return err;
activate = var->activate;
/* XXX ... what to do about isactive ? */
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
- retz3fb_set_par(&par);
- fbhw->encode_var(var, &par);
+ retz3fb_set_par(info, &par);
+ retz3_encode_var(var, &par);
var->activate = activate;
- retz3_set_video(var, &current_par);
+ retz3_set_video(info, var, &zinfo->current_par);
return 0;
}
@@ -1183,15 +1092,15 @@ static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
static void do_install_cmap(int con, struct fb_info *info)
{
- if (con != currcon)
+ struct retz3_fb_info *zinfo = retz3info(info);
+
+ if (con != zinfo->currcon)
return;
if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
- fbhw->setcolreg, info);
+ fb_set_cmap(&fb_display[con].cmap, 1, retz3_setcolreg, info);
else
fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
- &fb_display[con].var, 1,
- fbhw->setcolreg, info);
+ 1, retz3_setcolreg, info);
}
@@ -1227,10 +1136,10 @@ static int retz3fb_get_fix(struct fb_fix_screeninfo *fix, int con,
int error = 0;
if (con == -1)
- retz3fb_get_par(&par);
+ retz3fb_get_par(info, &par);
else
- error = fbhw->decode_var(&fb_display[con].var, &par);
- return(error ? error : fbhw->encode_fix(fix, &par));
+ error = retz3_decode_var(&fb_display[con].var, &par);
+ return(error ? error : retz3_encode_fix(info, fix, &par));
}
@@ -1245,8 +1154,8 @@ static int retz3fb_get_var(struct fb_var_screeninfo *var, int con,
int error = 0;
if (con == -1) {
- retz3fb_get_par(&par);
- error = fbhw->encode_var(var, &par);
+ retz3fb_get_par(info, &par);
+ error = retz3_encode_var(var, &par);
} else
*var = fb_display[con].var;
return error;
@@ -1258,18 +1167,19 @@ static void retz3fb_set_disp(int con, struct fb_info *info)
{
struct fb_fix_screeninfo fix;
struct display *display;
+ struct retz3_fb_info *zinfo = retz3info(info);
if (con >= 0)
display = &fb_display[con];
else
- display = &disp; /* used during initialization */
+ display = &zinfo->disp; /* used during initialization */
retz3fb_get_fix(&fix, con, info);
if (con == -1)
con = 0;
- display->screen_base = fix.smem_start;
+ display->screen_base = (char *)zinfo->fbmem;
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
@@ -1277,6 +1187,12 @@ static void retz3fb_set_disp(int con, struct fb_info *info)
display->ywrapstep = fix.ywrapstep;
display->can_soft_blank = 1;
display->inverse = z3fb_inverse;
+
+ /*
+ * This seems to be about 20% faster.
+ */
+ display->scrollmode = SCROLL_YREDRAW;
+
switch (display->var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 8:
@@ -1293,12 +1209,13 @@ static void retz3fb_set_disp(int con, struct fb_info *info)
break;
#endif
default:
- display->dispsw = NULL;
+ display->dispsw = &fbcon_dummy;
break;
}
}
#endif
+
/*
* Set the User Defined Part of the Display
*/
@@ -1308,18 +1225,14 @@ static int retz3fb_set_var(struct fb_var_screeninfo *var, int con,
{
int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
struct display *display;
+ struct retz3_fb_info *zinfo = retz3info(info);
if (con >= 0)
display = &fb_display[con];
else
- display = &disp; /* used during initialization */
-
-#if 0
- if (con == -1)
- con = 0;
-#endif
+ display = &zinfo->disp; /* used during initialization */
- if ((err = do_fb_set_var(var, con == currcon)))
+ if ((err = do_fb_set_var(info, var, con == zinfo->currcon)))
return err;
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
oldxres = display->var.xres;
@@ -1339,7 +1252,7 @@ static int retz3fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_fix_screeninfo fix;
retz3fb_get_fix(&fix, con, info);
- display->screen_base = fix.smem_start;
+ display->screen_base = (char *)zinfo->fbmem;
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
@@ -1364,14 +1277,14 @@ static int retz3fb_set_var(struct fb_var_screeninfo *var, int con,
break;
#endif
default:
- display->dispsw = NULL;
+ display->dispsw = &fbcon_dummy;
break;
}
/*
retz3fb_set_disp(con, info);
*/
- if (fb_info.changevar)
- (*fb_info.changevar)(con);
+ if (info->changevar)
+ (*info->changevar)(con);
}
if (oldbpp != var->bits_per_pixel) {
@@ -1391,9 +1304,10 @@ static int retz3fb_set_var(struct fb_var_screeninfo *var, int con,
static int retz3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
- if (con == currcon) /* current console? */
- return(fb_get_cmap(cmap, &fb_display[con].var, kspc,
- fbhw->getcolreg, info));
+ struct retz3_fb_info *zinfo = retz3info(info);
+
+ if (con == zinfo->currcon) /* current console? */
+ return(fb_get_cmap(cmap, kspc, retz3_getcolreg, info));
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
@@ -1411,6 +1325,7 @@ static int retz3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
int err;
+ struct retz3_fb_info *zinfo = retz3info(info);
if (!fb_display[con].cmap.len) { /* no colormap allocated? */
if ((err = fb_alloc_cmap(&fb_display[con].cmap,
@@ -1418,9 +1333,8 @@ static int retz3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
0)))
return err;
}
- if (con == currcon) /* current console? */
- return(fb_set_cmap(cmap, &fb_display[con].var, kspc,
- fbhw->setcolreg, info));
+ if (con == zinfo->currcon) /* current console? */
+ return(fb_set_cmap(cmap, kspc, retz3_setcolreg, info));
else
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
@@ -1463,8 +1377,6 @@ __initfunc(void retz3fb_setup(char *options, int *ints))
{
char *this_opt;
- fb_info.fontname[0] = '\0';
-
if (!options || !*options)
return;
@@ -1473,9 +1385,10 @@ __initfunc(void retz3fb_setup(char *options, int *ints))
if (!strcmp(this_opt, "inverse")) {
z3fb_inverse = 1;
fb_invert_cmaps();
- } else if (!strncmp(this_opt, "font:", 5))
- strcpy(fb_info.fontname, this_opt+5);
- else
+ } else if (!strncmp(this_opt, "font:", 5)) {
+ strncpy(fontname, this_opt+5, 39);
+ fontname[39] = '\0';
+ }else
z3fb_mode = get_video_mode(this_opt);
}
}
@@ -1490,58 +1403,79 @@ __initfunc(void retz3fb_init(void))
unsigned long board_addr, board_size;
unsigned int key;
const struct ConfigDev *cd;
-
+ volatile unsigned char *regs;
struct retz3fb_par par;
+ struct retz3_fb_info *zinfo;
+ struct fb_info *fb_info;
+ short i;
if (!(key = zorro_find(ZORRO_PROD_MACROSYSTEMS_RETINA_Z3, 0, 0)))
return;
+ if (!(zinfo = kmalloc(sizeof(struct retz3_fb_info), GFP_KERNEL)))
+ return;
+ memset(zinfo, 0, sizeof(struct retz3_fb_info));
+
cd = zorro_get_board (key);
zorro_config_board (key, 0);
board_addr = (unsigned long)cd->cd_BoardAddr;
board_size = (unsigned long)cd->cd_BoardSize;
- z3_mem = kernel_map (board_addr, board_size,
- KERNELMAP_NOCACHE_SER, NULL);
-
- z3_regs = (char*) z3_mem;
- z3_fbmem = z3_mem + VIDEO_MEM_OFFSET;
-
+ zinfo->base = kernel_map (board_addr, board_size,
+ KERNELMAP_NOCACHE_SER, NULL);
+ zinfo->regs = (unsigned char *)(zinfo->base);
+ zinfo->fbmem = zinfo->base + VIDEO_MEM_OFFSET;
/* Get memory size - for now we asume its a 4MB board */
+ zinfo->fbsize = 0x00400000; /* 4 MB */
+ zinfo->physregs = board_addr;
+ zinfo->physfbmem = board_addr + VIDEO_MEM_OFFSET;
- z3_size = 0x00400000; /* 4 MB */
-
- fbhw = &retz3_switch;
+ fb_info = fbinfo(zinfo);
- fbhw->init();
+ for (i = 0; i < 256; i++){
+ for (i = 0; i < 256; i++){
+ zinfo->color_table[i][0] = i;
+ zinfo->color_table[i][1] = i;
+ zinfo->color_table[i][2] = i;
+ }
+ }
- strcpy(fb_info.modename, retz3fb_name);
- fb_info.changevar = NULL;
- fb_info.node = -1;
- fb_info.fbops = &retz3fb_ops;
- fb_info.disp = &disp;
- fb_info.switch_con = &z3fb_switch;
- fb_info.updatevar = &z3fb_updatevar;
- fb_info.blank = &z3fb_blank;
+ regs = zinfo->regs;
+ /* Disable hardware cursor */
+ seq_w(regs, SEQ_CURSOR_Y_INDEX, 0x00);
+
+ retz3_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, fb_info);
+ retz3_setcolreg (254, 0, 0, 0, 0, fb_info);
+
+ strcpy(fb_info->modename, retz3fb_name);
+ fb_info->changevar = NULL;
+ fb_info->node = -1;
+ fb_info->fbops = &retz3fb_ops;
+ fb_info->disp = &zinfo->disp;
+ fb_info->switch_con = &z3fb_switch;
+ fb_info->updatevar = &z3fb_updatevar;
+ fb_info->blank = &z3fb_blank;
+ fb_info->flags = FBINFO_FLAG_DEFAULT;
+ strncpy(fb_info->fontname, fontname, 40);
if (z3fb_mode == -1)
retz3fb_default = retz3fb_predefined[0].var;
- fbhw->decode_var(&retz3fb_default, &par);
- fbhw->encode_var(&retz3fb_default, &par);
+ retz3_decode_var(&retz3fb_default, &par);
+ retz3_encode_var(&retz3fb_default, &par);
- do_fb_set_var(&retz3fb_default, 0);
- retz3fb_get_var(&disp.var, -1, &fb_info);
+ do_fb_set_var(fb_info, &retz3fb_default, 0);
+ retz3fb_get_var(&zinfo->disp.var, -1, fb_info);
- retz3fb_set_disp(-1, &fb_info);
+ retz3fb_set_disp(-1, fb_info);
- do_install_cmap(0, &fb_info);
+ do_install_cmap(0, fb_info);
- if (register_framebuffer(&fb_info) < 0)
+ 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);
+ GET_FB_IDX(fb_info->node), fb_info->modename,zinfo->fbsize>>10);
/* TODO: This driver cannot be unloaded yet */
MOD_INC_USE_COUNT;
@@ -1550,14 +1484,15 @@ __initfunc(void retz3fb_init(void))
static int z3fb_switch(int con, struct fb_info *info)
{
+ struct retz3_fb_info *zinfo = retz3info(info);
+
/* Do we have to save the colormap? */
- if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap,
- &fb_display[currcon].var, 1, fbhw->getcolreg,
- info);
+ if (fb_display[zinfo->currcon].cmap.len)
+ fb_get_cmap(&fb_display[zinfo->currcon].cmap, 1,
+ retz3_getcolreg, info);
- do_fb_set_var(&fb_display[con].var, 1);
- currcon = con;
+ do_fb_set_var(info, &fb_display[con].var, 1);
+ zinfo->currcon = con;
/* Install new colormap */
do_install_cmap(con, info);
return 0;
@@ -1583,7 +1518,24 @@ static int z3fb_updatevar(int con, struct fb_info *info)
static void z3fb_blank(int blank, struct fb_info *info)
{
- fbhw->blank(blank);
+ struct retz3_fb_info *zinfo = retz3info(info);
+ volatile unsigned char *regs = retz3info(info)->regs;
+ short i;
+
+ if (blank)
+ for (i = 0; i < 256; i++){
+ reg_w(regs, VDAC_ADDRESS_W, i);
+ reg_w(regs, VDAC_DATA, 0);
+ reg_w(regs, VDAC_DATA, 0);
+ reg_w(regs, VDAC_DATA, 0);
+ }
+ else
+ for (i = 0; i < 256; i++){
+ reg_w(regs, VDAC_ADDRESS_W, i);
+ reg_w(regs, VDAC_DATA, zinfo->color_table[i][0]);
+ reg_w(regs, VDAC_DATA, zinfo->color_table[i][1]);
+ reg_w(regs, VDAC_DATA, zinfo->color_table[i][2]);
+ }
}
@@ -1628,31 +1580,31 @@ void cleanup_module(void)
*/
#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)
+static void fbcon_retz3_8_bmove(struct display *p, int sy, int sx,
+ int dy, int dx, int height, int width)
{
- int fontwidth = p->fontwidth;
+ int fontwidth = fontwidth(p);
sx *= fontwidth;
dx *= fontwidth;
width *= fontwidth;
- retz3_bitblt(&p->var,
+ retz3_bitblt(p,
(unsigned short)sx,
- (unsigned short)(sy*p->fontheight),
+ (unsigned short)(sy*fontheight(p)),
(unsigned short)dx,
- (unsigned short)(dy*p->fontheight),
+ (unsigned short)(dy*fontheight(p)),
(unsigned short)width,
- (unsigned short)(height*p->fontheight),
+ (unsigned short)(height*fontheight(p)),
Z3BLTcopy,
0xffff);
}
-static void fbcon_retz3_8_clear(struct vc_data *conp, struct display *p, int
- sy, int sx, int height, int width)
+static void fbcon_retz3_8_clear(struct vc_data *conp, struct display *p,
+ int sy, int sx, int height, int width)
{
unsigned short col;
- int fontwidth = p->fontwidth;
+ int fontwidth = fontwidth(p);
sx *= fontwidth;
width *= fontwidth;
@@ -1661,13 +1613,13 @@ static void fbcon_retz3_8_clear(struct vc_data *conp, struct display *p, int
col &= 0xff;
col |= (col << 8);
- retz3_bitblt(&p->var,
+ retz3_bitblt(p,
(unsigned short)sx,
- (unsigned short)(sy*p->fontheight),
+ (unsigned short)(sy*fontheight(p)),
(unsigned short)sx,
- (unsigned short)(sy*p->fontheight),
+ (unsigned short)(sy*fontheight(p)),
(unsigned short)width,
- (unsigned short)(height*p->fontheight),
+ (unsigned short)(height*fontheight(p)),
Z3BLTset,
col);
}
diff --git a/drivers/video/retz3fb.h b/drivers/video/retz3fb.h
index 149842860..5cc751067 100644
--- a/drivers/video/retz3fb.h
+++ b/drivers/video/retz3fb.h
@@ -16,40 +16,40 @@
/*
* Macros to read and write to registers.
*/
-#define reg_w(reg,dat) (*(z3_regs + reg) = dat)
-#define reg_r(reg) (*(z3_regs + reg))
+#define reg_w(regs, reg,dat) (*(regs + reg) = dat)
+#define reg_r(regs, reg) (*(regs + reg))
/*
* Macro to access the sequencer.
*/
-#define seq_w(sreg,sdat) \
- do{ reg_w(SEQ_IDX, sreg); reg_w(SEQ_DATA, sdat); } while(0)
+#define seq_w(regs, sreg, sdat) \
+ do{ reg_w(regs, SEQ_IDX, sreg); reg_w(regs, SEQ_DATA, sdat); } while(0)
/*
* Macro to access the CRT controller.
*/
-#define crt_w(creg,cdat) \
- do{ reg_w(CRT_IDX, creg); reg_w(CRT_DATA, cdat); } while(0)
+#define crt_w(regs, creg, cdat) \
+ do{ reg_w(regs, CRT_IDX, creg); reg_w(regs, CRT_DATA, cdat); } while(0)
/*
* Macro to access the graphics controller.
*/
-#define gfx_w(greg,gdat) \
- do{ reg_w(GFX_IDX, greg); reg_w(GFX_DATA, gdat); } while(0)
+#define gfx_w(regs, greg, gdat) \
+ do{ reg_w(regs, GFX_IDX, greg); reg_w(regs, GFX_DATA, gdat); } while(0)
/*
* Macro to access the attribute controller.
*/
-#define attr_w(areg,adat) \
- do{ reg_w(ACT_IDX, areg); reg_w(ACT_DATA, adat); } while(0)
+#define attr_w(regs, areg, adat) \
+ do{ reg_w(regs, ACT_IDX, areg); reg_w(regs, ACT_DATA, adat); } while(0)
/*
* Macro to access the pll.
*/
-#define pll_w(preg,pdat) \
- do{ reg_w(PLL_IDX, preg); \
- reg_w(PLL_DATA, (pdat & 0xff)); \
- reg_w(PLL_DATA, (pdat >> 8));\
+#define pll_w(regs, preg, pdat) \
+ do{ reg_w(regs, PLL_IDX, preg); \
+ reg_w(regs, PLL_DATA, (pdat & 0xff)); \
+ reg_w(regs, PLL_DATA, (pdat >> 8));\
} while(0)
/*
diff --git a/drivers/video/s3blit.h b/drivers/video/s3blit.h
deleted file mode 100644
index ef9340770..000000000
--- a/drivers/video/s3blit.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* s3 commands */
-#define S3_BITBLT 0xc011
-#define S3_TWOPOINTLINE 0x2811
-#define S3_FILLEDRECT 0x40b1
-
-#define S3_FIFO_EMPTY 0x0400
-#define S3_HDW_BUSY 0x0200
-
-/* Enhanced register mapping (MMIO mode) */
-
-#define S3_READ_SEL 0xbee8 /* offset f */
-#define S3_MULT_MISC 0xbee8 /* offset e */
-#define S3_ERR_TERM 0x92e8
-#define S3_FRGD_COLOR 0xa6e8
-#define S3_BKGD_COLOR 0xa2e8
-#define S3_PIXEL_CNTL 0xbee8 /* offset a */
-#define S3_FRGD_MIX 0xbae8
-#define S3_BKGD_MIX 0xb6e8
-#define S3_CUR_Y 0x82e8
-#define S3_CUR_X 0x86e8
-#define S3_DESTY_AXSTP 0x8ae8
-#define S3_DESTX_DIASTP 0x8ee8
-#define S3_MIN_AXIS_PCNT 0xbee8 /* offset 0 */
-#define S3_MAJ_AXIS_PCNT 0x96e8
-#define S3_CMD 0x9ae8
-#define S3_GP_STAT 0x9ae8
-#define S3_ADVFUNC_CNTL 0x4ae8
-#define S3_WRT_MASK 0xaae8
-#define S3_RD_MASK 0xaee8
-
-/* Enhanced register mapping (Packed MMIO mode, write only) */
-#define S3_ALT_CURXY 0x8100
-#define S3_ALT_CURXY2 0x8104
-#define S3_ALT_STEP 0x8108
-#define S3_ALT_STEP2 0x810c
-#define S3_ALT_ERR 0x8110
-#define S3_ALT_CMD 0x8118
-#define S3_ALT_MIX 0x8134
-#define S3_ALT_PCNT 0x8148
-#define S3_ALT_PAT 0x8168
-
-/* Drawing modes */
-#define S3_NOTCUR 0x0000
-#define S3_LOGICALZERO 0x0001
-#define S3_LOGICALONE 0x0002
-#define S3_LEAVEASIS 0x0003
-#define S3_NOTNEW 0x0004
-#define S3_CURXORNEW 0x0005
-#define S3_NOT_CURXORNEW 0x0006
-#define S3_NEW 0x0007
-#define S3_NOTCURORNOTNEW 0x0008
-#define S3_CURORNOTNEW 0x0009
-#define S3_NOTCURORNEW 0x000a
-#define S3_CURORNEW 0x000b
-#define S3_CURANDNEW 0x000c
-#define S3_NOTCURANDNEW 0x000d
-#define S3_CURANDNOTNEW 0x000e
-#define S3_NOTCURANDNOTNEW 0x000f
-
-#define S3_CRTC_ADR 0x03d4
-#define S3_CRTC_DATA 0x03d5
-
-#define S3_REG_LOCK2 0x39
-#define S3_HGC_MODE 0x45
-
-#define S3_HWGC_ORGX_H 0x46
-#define S3_HWGC_ORGX_L 0x47
-#define S3_HWGC_ORGY_H 0x48
-#define S3_HWGC_ORGY_L 0x49
-#define S3_HWGC_DX 0x4e
-#define S3_HWGC_DY 0x4f
-
-
-#define S3_LAW_CTL 0x58
diff --git a/drivers/video/sbusfb.c b/drivers/video/sbusfb.c
index a771c37bd..f4fbe2ec5 100644
--- a/drivers/video/sbusfb.c
+++ b/drivers/video/sbusfb.c
@@ -40,8 +40,11 @@
#include <linux/vt_kern.h>
#include <asm/uaccess.h>
+#include <asm/pgtable.h> /* io_remap_page_range() */
-#include "sbusfb.h"
+#include <video/sbusfb.h>
+
+#define DEFAULT_CURSOR_BLINK_RATE (2*HZ/5)
/*
* Interface used by the world
@@ -53,6 +56,7 @@ 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 int curblink __initdata = 1;
static struct {
int depth;
int xres, yres;
@@ -88,8 +92,6 @@ 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);
/*
@@ -143,8 +145,10 @@ static int sbusfb_release(struct fb_info *info, int user)
if (user) {
if (fb->vtconsole != -1) {
vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;
- if (fb->mmaped)
+ if (fb->mmaped) {
+ fb->graphmode--;
sbusfb_clear_margin(&fb_display[fb->vtconsole], 0);
+ }
}
if (fb->reset)
fb->reset(fb);
@@ -180,7 +184,8 @@ static int sbusfb_mmap(struct fb_info *info, struct file *file,
#ifdef __sparc_v9__
/* Align it as much as desirable */
{
- int j, max = -1, alignment, s = 0;
+ unsigned long j, alignment, s = 0;
+ int max = -1;
map_offset = vma->vm_offset+size;
for (i = 0; fb->mmap_map[i].size; i++) {
@@ -247,7 +252,9 @@ static int sbusfb_mmap(struct fb_info *info, struct file *file,
fb->mmaped = 1;
if (fb->consolecnt && fb_display[lastconsole].fb_info == info) {
fb->vtconsole = lastconsole;
+ fb->graphmode++;
vt_cons [lastconsole]->vc_mode = KD_GRAPHICS;
+ vc_cons[lastconsole].d->vc_sw->con_cursor(vc_cons[lastconsole].d,CM_ERASE);
} else if (fb->unblank && !fb->blanked)
(*fb->unblank)(fb);
}
@@ -258,6 +265,8 @@ static void sbusfb_clear_margin(struct display *p, int s)
{
struct fb_info_sbusfb *fb = sbusfbinfod(p);
+ if (fb->switch_from_graph)
+ (*fb->switch_from_graph)(fb);
if (fb->fill) {
unsigned short rects [16];
@@ -289,13 +298,13 @@ static void sbusfb_clear_margin(struct display *p, int s)
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);
+ mymemset (fb_base, skip_bytes - fb->x_margin / 8);
+ mymemset (fb_base + scr_size - skip_bytes + fb->x_margin / 8, 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);
+ mymemset (q, size);
} else {
fb_base -= (skip_bytes + fb->x_margin);
memset (fb_base, attr_bgcol(p,s), skip_bytes - fb->x_margin);
@@ -307,8 +316,6 @@ static void sbusfb_clear_margin(struct display *p, int s)
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)
@@ -414,13 +421,13 @@ static int sbus_hw_scursor (struct fbcursor *cursor, struct fb_info_sbusfb *fb)
copy_from_user (fb->cursor.bits [1], f.image, bytes))
return -EFAULT;
if (f.size.fbx <= 32) {
- u = ~(0xffffffff >> f.size.fbx);
+ u = 0xffffffff << (32 - 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));
+ u = 0xffffffff << (64 - f.size.fbx);
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];
@@ -443,42 +450,58 @@ static int sbus_hw_scursor (struct fbcursor *cursor, struct fb_info_sbusfb *fb)
static unsigned char hw_cursor_cmap[2] = { 0, 0xff };
+static void
+sbusfb_cursor_timer_handler(unsigned long dev_addr)
+{
+ struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)dev_addr;
+
+ if (!fb->setcursor) return;
+
+ if (fb->cursor.mode != 2) {
+ fb->cursor.enable ^= 1;
+ fb->setcursor(fb);
+ }
+
+ fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate;
+ add_timer(&fb->cursor.timer);
+}
+
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.mode = 2;
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;
+ if (fb->cursor.mode) {
+ fb->cursor.size.fbx = fontwidth(p);
+ fb->cursor.size.fby = fontheight(p);
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->cursor.bits[0][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p)));
+ fb->cursor.bits[1][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p)));
+ fb->cursor.bits[0][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
+ fb->cursor.bits[1][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
(*fb->setcursormap) (fb, hw_cursor_cmap, hw_cursor_cmap, hw_cursor_cmap);
(*fb->setcurshape) (fb);
- fb->hw_cursor_shown = 1;
+ fb->cursor.mode = 0;
}
- if (p->fontwidthlog)
- fb->cursor.cpos.fbx = (x << p->fontwidthlog) + fb->x_margin;
+ if (fontwidthlog(p))
+ fb->cursor.cpos.fbx = (x << fontwidthlog(p)) + 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;
+ fb->cursor.cpos.fbx = (x * fontwidth(p)) + fb->x_margin;
+ if (fontheightlog(p))
+ fb->cursor.cpos.fby = (y << fontheightlog(p)) + fb->y_margin;
else
- fb->cursor.cpos.fby = (y * p->fontheight) + fb->y_margin;
+ fb->cursor.cpos.fby = (y * fontheight(p)) + fb->y_margin;
(*fb->setcursor)(fb);
break;
}
@@ -492,7 +515,7 @@ 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);
+ return fb_get_cmap(cmap, 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
@@ -514,12 +537,12 @@ static int sbusfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return err;
}
if (con == currcon) { /* current console? */
- err = fb_set_cmap(cmap, &fb_display[con].var, kspc, sbusfb_setcolreg, info);
+ err = fb_set_cmap(cmap, kspc, sbusfb_setcolreg, info);
if (!err) {
struct fb_info_sbusfb *fb = sbusfbinfo(info);
if (fb->loadcmap)
- (*fb->loadcmap)(fb, cmap->start, cmap->len);
+ (*fb->loadcmap)(fb, &fb_display[con], cmap->start, cmap->len);
}
return err;
} else
@@ -610,7 +633,7 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
__put_user_ret(fb->color_map CM(i,2), bp, -EFAULT);
rp++; gp++; bp++;
}
- (*fb->loadcmap)(fb, index, count);
+ (*fb->loadcmap)(fb, NULL, index, count);
break;
}
case FBIOPUTCMAP_SPARC: { /* load color map entries */
@@ -643,7 +666,7 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
__get_user_ret(fb->color_map CM(i,2), bp, -EFAULT);
rp++; gp++; bp++;
}
- (*fb->loadcmap)(fb, index, count);
+ (*fb->loadcmap)(fb, NULL, index, count);
break;
}
case FBIOGCURMAX: {
@@ -661,7 +684,7 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
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 */
+ fb->cursor.mode = 2; /* Forget state of our text cursor */
}
return sbus_hw_scursor ((struct fbcursor *) arg, fb);
@@ -678,7 +701,8 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
(*fb->setcursor) (fb);
break;
default:
- /* FIXME: Call here possible fb specific ioctl */
+ if (fb->ioctl)
+ return fb->ioctl(fb, cmd, arg);
return -EINVAL;
}
return 0;
@@ -714,7 +738,8 @@ __initfunc(void sbusfb_setup(char *options, int *ints))
break;
memcpy(fontname, p+5, i);
fontname[i] = 0;
- }
+ } else if (!strncmp(p, "noblink", 7))
+ curblink = 0;
while (*p && *p != ' ' && *p != ',') p++;
if (*p != ',') break;
p++;
@@ -729,18 +754,20 @@ static int sbusfbcon_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, 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;
+ fb_get_cmap(&fb_display[currcon].cmap, 1, sbusfb_getcolreg, info);
+
+ if (info->display_fg) {
+ lastconsole = info->display_fg->vc_num;
+ if (lastconsole != con &&
+ (fontwidth(&fb_display[lastconsole]) != fontwidth(&fb_display[con]) ||
+ fontheight(&fb_display[lastconsole]) != fontheight(&fb_display[con])))
+ fb->cursor.mode = 1;
+ }
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) {
+ if (fb->graphmode || 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);
}
@@ -786,9 +813,10 @@ static int sbusfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
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);
+ *red = (fb->color_map CM(regno, 0)<<8) | fb->color_map CM(regno, 0);
+ *green = (fb->color_map CM(regno, 1)<<8) | fb->color_map CM(regno, 1);
+ *blue = (fb->color_map CM(regno, 2)<<8) | fb->color_map CM(regno, 2);
+ *transp = 0;
return 0;
}
@@ -806,6 +834,9 @@ static int sbusfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
if (!fb->color_map || regno > 255)
return 1;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
fb->color_map CM(regno, 0) = red;
fb->color_map CM(regno, 1) = green;
fb->color_map CM(regno, 2) = blue;
@@ -820,13 +851,12 @@ 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,
- sbusfb_setcolreg, info);
+ fb_set_cmap(&fb_display[con].cmap, 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);
+ 1, sbusfb_setcolreg, info);
if (fb->loadcmap)
- (*fb->loadcmap)(fb, 0, 256);
+ (*fb->loadcmap)(fb, &fb_display[con], 0, 256);
}
static int sbusfb_set_font(struct display *p, int width, int height)
@@ -859,7 +889,7 @@ static int sbusfb_set_font(struct display *p, int width, int height)
p->var.xres = w - 2*x_margin;
p->var.yres = h - 2*y_margin;
- fb->hw_cursor_shown = 0;
+ fb->cursor.mode = 1;
if (fb->margins)
fb->margins(fb, p, x_margin, y_margin);
@@ -987,6 +1017,7 @@ sizechange:
fb->info.switch_con = &sbusfbcon_switch;
fb->info.updatevar = &sbusfbcon_updatevar;
fb->info.blank = &sbusfbcon_blank;
+ fb->info.flags = FBINFO_FLAG_DEFAULT;
fb->cursor.hwsize.fbx = 32;
fb->cursor.hwsize.fby = 32;
@@ -1034,8 +1065,17 @@ sizechange:
goto sizechange;
disp->dispsw = &fb->dispsw;
- if (fb->setcursor)
+ if (fb->setcursor) {
fb->dispsw.cursor = sbusfb_cursor;
+ if (curblink) {
+ fb->cursor.blink_rate = DEFAULT_CURSOR_BLINK_RATE;
+ init_timer(&fb->cursor.timer);
+ fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate;
+ fb->cursor.timer.data = (unsigned long)fb;
+ fb->cursor.timer.function = sbusfb_cursor_timer_handler;
+ add_timer(&fb->cursor.timer);
+ }
+ }
fb->dispsw.set_font = sbusfb_set_font;
fb->setup = fb->dispsw.setup;
fb->dispsw.setup = sbusfb_disp_setup;
diff --git a/drivers/video/sbusfb.h b/drivers/video/sbusfb.h
deleted file mode 100644
index f65ca1d71..000000000
--- a/drivers/video/sbusfb.h
+++ /dev/null
@@ -1,116 +0,0 @@
-#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 1831e6b33..a99a3a0cd 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -17,8 +17,9 @@
#include <linux/malloc.h>
#include <linux/delay.h>
#include <linux/fb.h>
+#include <linux/init.h>
-#include "fbcon.h"
+#include <video/fbcon.h>
/*
@@ -83,13 +84,15 @@ static void xxx_detect(void)
* it as the default video mode
*/
+ struct xxxfb_par par;
+
/* ... */
xxx_get_par(&par);
xxx_encode_var(&default_var, &par);
}
static int xxx_encode_fix(struct fb_fix_screeninfo *fix, struct xxxfb_par *par,
- const struct fb_info *fb_info)
+ const struct fb_info *info)
{
/*
* This function should fill in the 'fix' structure based on the values
@@ -101,7 +104,7 @@ static int xxx_encode_fix(struct fb_fix_screeninfo *fix, struct xxxfb_par *par,
}
static int xxx_decode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par,
- const struct fb_info *fb_info)
+ const struct fb_info *info)
{
/*
* Get the video params out of 'var'. If a value doesn't fit, round it up,
@@ -122,7 +125,7 @@ static int xxx_decode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par,
}
static int xxx_encode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par,
- const struct fb_info *fb_info)
+ const struct fb_info *info)
{
/*
* Fill the 'var' structure based on the values in 'par' and maybe other
@@ -133,7 +136,7 @@ static int xxx_encode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par,
return 0;
}
-static void xxx_get_par(struct xxxfb_par *par, const struct fb_info *fb_info)
+static void xxx_get_par(struct xxxfb_par *par, const struct fb_info *info)
{
/*
* Fill the hardware's 'par' structure.
@@ -146,7 +149,7 @@ static void xxx_get_par(struct xxxfb_par *par, const struct fb_info *fb_info)
}
}
-static void xxx_set_par(struct xxxfb_par *par, const struct fb_info *fb_info)
+static void xxx_set_par(struct xxxfb_par *par, const struct fb_info *info)
{
/*
* Set the hardware according to 'par'.
@@ -159,10 +162,11 @@ static void xxx_set_par(struct xxxfb_par *par, const struct fb_info *fb_info)
static int xxx_getcolreg(unsigned regno, unsigned *red, unsigned *green,
unsigned *blue, unsigned *transp,
- const struct fb_info *fb_info)
+ const struct fb_info *info)
{
/*
* Read a single color register and split it into colors/transparent.
+ * The return values must have a 16 bit magnitude.
* Return != 0 for invalid regno.
*/
@@ -172,12 +176,12 @@ static int xxx_getcolreg(unsigned regno, unsigned *red, unsigned *green,
static int xxx_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
- const struct fb_info *fb_info)
+ const struct fb_info *info)
{
/*
- * Set a single color register. The values supplied are already rounded
- * down to the hardware's capabilities (according to the entries in the
- * `var' structure). Return != 0 for invalid regno.
+ * Set a single color register. The values supplied have a 16 bit
+ * magnitude.
+ * Return != 0 for invalid regno.
*/
if (regno < 16) {
@@ -185,25 +189,29 @@ static int xxx_setcolreg(unsigned regno, unsigned red, unsigned green,
* Make the first 16 colors of the palette available to fbcon
*/
if (is_cfb15) /* RGB 555 */
- fbcon_cfb15_cmap[regno] = be16_to_cpu((red << 10) | (green << 5) |
- blue);
+ ...fbcon_cmap.cfb16[regno] = ((red & 0xf800) >> 1) |
+ ((green & 0xf800) >> 6) |
+ ((blue & 0xf800) >> 11);
if (is_cfb16) /* RGB 565 */
- fbcon_cfb16_cmap[regno] = be16_to_cpu((red << 11) | (green << 5) |
- blue);
+ ...fbcon_cmap.cfb16[regno] = (red & 0xf800) |
+ ((green & 0xfc00) >> 5) |
+ ((blue & 0xf800) >> 11);
if (is_cfb24) /* RGB 888 */
- fbcon_cfb24_cmap[regno] = be32_to_cpu((red << 16) | (green << 8) |
- blue);
+ ...fbcon_cmap.cfb24[regno] = ((red & 0xff00) << 8) |
+ (green & 0xff00) |
+ ((blue & 0xff00) >> 8);
if (is_cfb32) /* RGBA 8888 */
- fbcon_cfb32_cmap[regno] = be32_to_cpu((red << 24) | (green << 16) |
- (blue << 8) | transp);
+ ...fbcon_cmap.cfb32[regno] = ((red & 0xff00) << 16) |
+ ((green & 0xff00) << 8) |
+ (blue & 0xff00) |
+ ((transp & 0xff00) >> 8);
}
/* ... */
return 0;
}
static int xxx_pan_display(struct fb_var_screeninfo *var,
- struct xxxfb_par *par,
- const struct fb_info *fb_info)
+ struct xxxfb_par *par, const struct fb_info *info)
{
/*
* Pan (or wrap, depending on the `vmode' field) the display using the
@@ -215,7 +223,7 @@ static int xxx_pan_display(struct fb_var_screeninfo *var,
return 0;
}
-static int xxx_blank(int blank_mode, const struct fb_info *fb_info)
+static int xxx_blank(int blank_mode, const struct fb_info *info)
{
/*
* Blank the screen if blank_mode != 0, else unblank. If blank == NULL
@@ -232,30 +240,45 @@ static int xxx_blank(int blank_mode, const struct fb_info *fb_info)
return 0;
}
-static struct display_switch *xxx_get_dispsw(const void *par,
- struct fb_info_gen *info)
+static void xxx_set_dispsw(const void *par, struct display *disp,
+ struct fb_info_gen *info)
{
+ unsigned long flags;
+
/*
- * Return a pointer to appropriate low level text console operations for
- * the video mode `par' of your video hardware. These can be generic
- * software routines, or hardware accelerated routines specifically
- * tailored for your hardware.
- * If you don't have any appropriate operations, simple fill in the NULL
- * pointer, and there will be no text output.
+ * Fill in a pointer to appropriate low level text console operations (and
+ * optionally a pointer to help data) for the video mode `par' of your
+ * video hardware. These can be generic software routines, or hardware
+ * accelerated routines specifically tailored for your hardware.
+ * If you don't have any appropriate operations, you must fill in a
+ * pointer to dummy operations, and there will be no text output.
*/
+ save_flags(flags); cli();
#ifdef FBCON_HAS_CFB8
- if (is_cfb8)
- return &fbcon_cfb8;
+ if (is_cfb8) {
+ disp->dispsw = fbcon_cfb8;
+ } else
#endif
#ifdef FBCON_HAS_CFB16
- if (is_cfb16)
- return &fbcon_cfb16;
+ if (is_cfb16) {
+ disp->dispsw = fbcon_cfb16;
+ disp->dispsw_data = ...fbcon_cmap.cfb16; /* console palette */
+ } else
+#endif
+#ifdef FBCON_HAS_CFB24
+ if (is_cfb24) {
+ disp->dispsw = fbcon_cfb24;
+ disp->dispsw_data = ...fbcon_cmap.cfb24; /* console palette */
+ } else
#endif
#ifdef FBCON_HAS_CFB32
- if (is_cfb32)
- return &fbcon_cfb32;
+ if (is_cfb32) {
+ disp->dispsw = fbcon_cfb32;
+ disp->dispsw_data = ...fbcon_cmap.cfb32; /* console palette */
+ } else
#endif
- return NULL;
+ disp->dispsw = &fbcon_dummy;
+ restore_flags(flags);
}
@@ -278,27 +301,26 @@ struct fbgen_hwswitch xxx_switch = {
__initfunc(void xxxfb_init(void))
{
- struct fb_var_screeninfo var;
-
- fb_info.fbhw = &xxx_switch;
- fbhw->detect();
- strcpy(fb_info.modename, "XXX");
- fb_info.changevar = NULL;
- fb_info.node = -1;
- fb_info.fbops = &xxxfb_ops;
- fb_info.disp = disp;
- fb_info.switch_con = &xxxfb_switch;
- fb_info.updatevar = &xxxfb_update_var;
- fb_info.blank = &xxxfb_blank;
+ fb_info.gen.fbhw = &xxx_switch;
+ fb_info.gen.fbhw->detect();
+ strcpy(fb_info.gen.info.modename, "XXX");
+ fb_info.gen.info.changevar = NULL;
+ fb_info.gen.info.node = -1;
+ fb_info.gen.info.fbops = &xxxfb_ops;
+ fb_info.gen.info.disp = &disp;
+ fb_info.gen.info.switch_con = &xxxfb_switch;
+ fb_info.gen.info.updatevar = &xxxfb_update_var;
+ fb_info.gen.info.blank = &xxxfb_blank;
+ fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
/* 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);
- fbgen_set_disp(-1, &fb_info.gen.info);
+ fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
+ fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
+ fbgen_set_disp(-1, &fb_info.gen);
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);
+ printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node),
+ fb_info.gen.info.modename);
/* uncomment this if your driver cannot be unloaded */
/* MOD_INC_USE_COUNT; */
@@ -316,7 +338,7 @@ void xxxfb_cleanup(struct fb_info *info)
* clean up all instances.
*/
- unregister_framebuffer(&fb_info);
+ unregister_framebuffer(info);
/* ... */
}
diff --git a/drivers/video/tcxfb.c b/drivers/video/tcxfb.c
index 181b6c53e..90d6152fa 100644
--- a/drivers/video/tcxfb.c
+++ b/drivers/video/tcxfb.c
@@ -1,4 +1,4 @@
-/* $Id: tcxfb.c,v 1.1 1998/07/21 14:50:44 jj Exp $
+/* $Id: tcxfb.c,v 1.6 1998/09/04 15:43:46 jj Exp $
* tcxfb.c: TCX 24/8bit frame buffer driver
*
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -21,10 +21,10 @@
#include <linux/init.h>
#include <linux/selection.h>
-#include "sbusfb.h"
+#include <video/sbusfb.h>
#include <asm/io.h>
-#include "fbcon-cfb8.h"
+#include <video/fbcon-cfb8.h>
/* THC definitions */
#define TCX_THC_MISC_REV_SHIFT 16
@@ -102,7 +102,7 @@ static void tcx_switch_from_graph (struct fb_info_sbusfb *fb)
tcx_set_control_plane (fb);
}
-static void tcx_loadcmap (struct fb_info_sbusfb *fb, int index, int count)
+static void tcx_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
{
struct bt_regs *bt = fb->s.tcx.bt;
int i;
@@ -113,6 +113,7 @@ static void tcx_loadcmap (struct fb_info_sbusfb *fb, int index, int count)
bt->color_map = fb->color_map CM(i,1) << 24;
bt->color_map = fb->color_map CM(i,2) << 24;
}
+ bt->addr = 0;
}
static void tcx_restore_palette (struct fb_info_sbusfb *fb)
@@ -211,7 +212,7 @@ __initfunc(char *tcxfb_init(struct fb_info_sbusfb *fb))
struct display *disp = &fb->disp;
struct fbtype *type = &fb->type;
unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
- int lowdepth;
+ int lowdepth, i, j;
#ifndef FBCON_HAS_CFB8
return NULL;
@@ -265,10 +266,22 @@ __initfunc(char *tcxfb_init(struct fb_info_sbusfb *fb))
fb->blank = tcx_blank;
fb->unblank = tcx_unblank;
fb->reset = tcx_reset;
-
+
fb->physbase = 0;
+ for (i = 0; i < 13; i++) {
+ /* tcx_mmap_map has to be sorted by voff, while
+ order of phys registers from PROM differs a little
+ bit. Here is the correction */
+ switch (i) {
+ case 10: j = 12; break;
+ case 11:
+ case 12: j = i - 1; break;
+ default: j = i; break;
+ }
+ tcx_mmap_map[i].poff = fb->sbdp->reg_addrs[j].phys_addr;
+ }
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;
@@ -278,13 +291,13 @@ __initfunc(char *tcxfb_init(struct fb_info_sbusfb *fb))
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 d15d87a6b..201984959 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -15,7 +15,7 @@
/* KNOWN PROBLEMS/TO DO ===================================================== *
*
- * - How to set a single color register?
+ * - How to set a single color register on 24-plane cards?
*
* - Hardware cursor (useful for other graphics boards too)
*
@@ -38,9 +38,9 @@
#include <linux/selection.h>
#include <asm/io.h>
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb32.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb32.h>
/* TGA hardware description (minimal) */
@@ -242,6 +242,9 @@ static int currcon = 0;
static struct display disp;
static struct fb_info fb_info;
static struct { u_char red, green, blue, pad; } palette[256];
+#ifdef FBCON_HAS_CFB32
+static u32 fbcon_cfb32_cmap[16];
+#endif
static struct fb_fix_screeninfo fb_fix = { { "DEC TGA ", } };
static struct fb_var_screeninfo fb_var = { 0, };
@@ -404,13 +407,11 @@ static int tgafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
if (con == currcon) /* current console? */
- return fb_get_cmap(cmap, &fb_display[con].var, kspc, tgafb_getcolreg,
- info);
+ return fb_get_cmap(cmap, kspc, tgafb_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
- fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
- cmap, kspc ? 0 : 2);
+ fb_copy_cmap(fb_default_cmap(256), cmap, kspc ? 0 : 2);
return 0;
}
@@ -424,15 +425,14 @@ static int tgafb_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)))
+ if ((err = fb_alloc_cmap(&fb_display[con].cmap, 256, 0)))
return err;
}
if (con == currcon) { /* current console? */
- err = fb_set_cmap(cmap, &fb_display[con].var, kspc, tgafb_setcolreg,
- info);
+ err = fb_set_cmap(cmap, kspc, tgafb_setcolreg, info);
#if 1
- tga_update_palette();
+ if (tga_type != 0)
+ tga_update_palette();
#endif
return err;
} else
@@ -681,9 +681,9 @@ __initfunc(void tgafb_init(void))
TGA_WRITE_REG(temp & 0x000fffff, TGA_CURSOR_BASE_REG);
}
- /* finally, enable video scan & cursor
+ /* finally, enable video scan
(and pray for the monitor... :-) */
- TGA_WRITE_REG(0x05, TGA_VALID_REG); /* SCANNING and CURSOR */
+ TGA_WRITE_REG(0x01, TGA_VALID_REG); /* SCANNING */
fb_var.xres = fb_var.xres_virtual = 640;
fb_var.yres = fb_var.yres_virtual = 480;
@@ -748,10 +748,11 @@ __initfunc(void tgafb_init(void))
case 1: /* 24-plane */
case 3: /* 24plusZ */
disp.dispsw = &fbcon_cfb32;
+ disp.dispsw_data = &fbcon_cfb32_cmap;
break;
#endif
default:
- disp.dispsw = NULL;
+ disp.dispsw = &fbcon_dummy;
}
disp.scrollmode = SCROLL_YREDRAW;
@@ -764,6 +765,7 @@ __initfunc(void tgafb_init(void))
fb_info.switch_con = &tgafbcon_switch;
fb_info.updatevar = &tgafbcon_updatevar;
fb_info.blank = &tgafbcon_blank;
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
tgafb_set_var(&fb_var, -1, &fb_info);
@@ -779,8 +781,7 @@ static int tgafbcon_switch(int con, struct fb_info *info)
{
/* Do we have to save the colormap? */
if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
- tgafb_getcolreg, info);
+ fb_get_cmap(&fb_display[currcon].cmap, 1, tgafb_getcolreg, info);
currcon = con;
/* Install new colormap */
@@ -804,7 +805,13 @@ static int tgafbcon_updatevar(int con, struct fb_info *info)
static void tgafbcon_blank(int blank, struct fb_info *info)
{
- /* Nothing */
+ /* Should also do stuff here for vesa blanking -tor */
+
+ if (blank > 0) {
+ TGA_WRITE_REG(0x03, TGA_VALID_REG); /* SCANNING and BLANK */
+ } else {
+ TGA_WRITE_REG(0x01, TGA_VALID_REG); /* SCANNING */
+ }
}
/*
@@ -817,9 +824,10 @@ static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
{
if (regno > 255)
return 1;
- *red = palette[regno].red;
- *green = palette[regno].green;
- *blue = palette[regno].blue;
+ *red = (palette[regno].red<<8) | palette[regno].red;
+ *green = (palette[regno].green<<8) | palette[regno].green;
+ *blue = (palette[regno].blue<<8) | palette[regno].blue;
+ *transp = 0;
return 0;
}
@@ -835,6 +843,9 @@ static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
{
if (regno > 255)
return 1;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
palette[regno].red = red;
palette[regno].green = green;
palette[regno].blue = blue;
@@ -844,7 +855,14 @@ static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue;
#endif
- /* How to set a single color register?? */
+ if (tga_type == 0) { /* 8-plane */
+ BT485_WRITE(regno, BT485_ADDR_PAL_WRITE);
+ TGA_WRITE_REG(BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
+ TGA_WRITE_REG(red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+ TGA_WRITE_REG(green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+ TGA_WRITE_REG(blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+ }
+ /* How to set a single color register on 24-plane cards?? */
return 0;
}
@@ -852,31 +870,21 @@ static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
#if 1
/*
- * FIXME: since I don't know how to set a single arbitrary color register,
- * all color palette registers have to be updated
+ * FIXME: since I don't know how to set a single arbitrary color register
+ * on 24-plane cards, all color palette registers have to be updated
*/
static void tga_update_palette(void)
{
int i;
- if (tga_type == 0) { /* 8-plane */
- BT485_WRITE(0x00, BT485_ADDR_PAL_WRITE);
- TGA_WRITE_REG(BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
- for (i = 0; i < 256; i++) {
- TGA_WRITE_REG(palette[i].red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
- TGA_WRITE_REG(palette[i].green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
- TGA_WRITE_REG(palette[i].blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
- }
- } else {
- BT463_LOAD_ADDR(0x0000);
- TGA_WRITE_REG((BT463_PALETTE<<2), TGA_RAMDAC_REG);
+ BT463_LOAD_ADDR(0x0000);
+ TGA_WRITE_REG((BT463_PALETTE<<2), TGA_RAMDAC_REG);
- for (i = 0; i < 256; i++) {
- TGA_WRITE_REG(palette[i].red|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
- TGA_WRITE_REG(palette[i].green|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
- TGA_WRITE_REG(palette[i].blue|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
- }
+ for (i = 0; i < 256; i++) {
+ TGA_WRITE_REG(palette[i].red|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+ TGA_WRITE_REG(palette[i].green|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+ TGA_WRITE_REG(palette[i].blue|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
}
}
#endif
@@ -886,14 +894,12 @@ static void do_install_cmap(int con, struct fb_info *info)
if (con != currcon)
return;
if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
- tgafb_setcolreg, info);
+ fb_set_cmap(&fb_display[con].cmap, 1, tgafb_setcolreg, info);
else
- fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
- &fb_display[con].var, 1, tgafb_setcolreg,
- info);
+ fb_set_cmap(fb_default_cmap(256), 1, tgafb_setcolreg, info);
#if 1
- tga_update_palette();
+ if (tga_type != 0)
+ tga_update_palette();
#endif
}
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c
new file mode 100644
index 000000000..d7f2131de
--- /dev/null
+++ b/drivers/video/valkyriefb.c
@@ -0,0 +1,896 @@
+/*
+ * valkyriefb.c -- frame buffer device for the PowerMac 'valkyrie' display
+ *
+ * Created 8 August 1998 by Martin Costabel and Kevin Schoedel
+ *
+ * Vmode-switching changes and vmode 15/17 modifications created 29 August
+ * 1998 by Barry Nathan <barryn@pobox.com>.
+ *
+ * Derived directly from:
+ *
+ * controlfb.c -- frame buffer device for the PowerMac 'control' display
+ * Copyright (C) 1998 Dan Jacobowitz <dan@debian.org>
+ *
+ * pmc-valkyrie.c -- Console support for PowerMac "valkyrie" display adaptor.
+ * Copyright (C) 1997 Paul Mackerras.
+ *
+ * and indirectly:
+ *
+ * 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 <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/macmodes.h>
+
+#include "valkyriefb.h"
+
+static int can_soft_blank = 1;
+
+static int default_vmode = VMODE_NVRAM;
+static int default_cmode = CMODE_NVRAM;
+static char fontname[40] __initdata = { 0 };
+
+static int currcon = 0;
+static int switching = 0;
+
+struct fb_par_valkyrie {
+ int vmode, cmode;
+ int xres, yres;
+ int vxres, vyres;
+ int xoffset, yoffset;
+};
+
+struct fb_info_valkyrie {
+ struct fb_info info;
+ struct fb_fix_screeninfo fix;
+ struct fb_var_screeninfo var;
+ struct display disp;
+ struct fb_par_valkyrie par;
+ struct {
+ __u8 red, green, blue;
+ } palette[256];
+
+ struct cmap_regs *cmap_regs;
+ unsigned long cmap_regs_phys;
+
+ struct valkyrie_regs *valkyrie_regs;
+ unsigned long valkyrie_regs_phys;
+
+ __u8 *frame_buffer;
+ unsigned long frame_buffer_phys;
+
+ int sense;
+ unsigned long total_vram;
+#ifdef FBCON_HAS_CFB16
+ u16 fbcon_cfb16_cmap[16];
+#endif
+};
+
+/*
+ * Exported functions
+ */
+void valkyriefb_init(void);
+void valkyrie_of_init(struct device_node *dp);
+void valkyriefb_setup(char *options, int *ints);
+
+static int valkyrie_open(struct fb_info *info, int user);
+static int valkyrie_release(struct fb_info *info, int user);
+static int valkyrie_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info);
+static int valkyrie_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int valkyrie_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int valkyrie_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int valkyrie_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info);
+static int valkyrie_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info);
+static int valkyrie_ioctl(struct inode *inode, struct file *file, u_int cmd,
+ u_long arg, int con, struct fb_info *info);
+
+static int read_valkyrie_sense(struct fb_info_valkyrie *p);
+static inline int valkyrie_vram_reqd(int video_mode, int color_mode);
+static void set_valkyrie_clock(unsigned char *params);
+static void valkyrie_set_par(const struct fb_par_valkyrie *p, struct fb_info_valkyrie *info);
+static inline int valkyrie_par_to_var(struct fb_par_valkyrie *par, struct fb_var_screeninfo *var);
+static int valkyrie_var_to_par(struct fb_var_screeninfo *var,
+ struct fb_par_valkyrie *par, const struct fb_info *fb_info);
+
+static void valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p);
+static void valkyrie_par_to_display(struct fb_par_valkyrie *par,
+ struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p);
+static void valkyrie_init_display(struct display *disp);
+static void valkyrie_par_to_fix(struct fb_par_valkyrie *par, struct fb_fix_screeninfo *fix,
+ struct fb_info_valkyrie *p);
+static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p);
+
+static struct fb_ops valkyriefb_ops = {
+ valkyrie_open,
+ valkyrie_release,
+ valkyrie_get_fix,
+ valkyrie_get_var,
+ valkyrie_set_var,
+ valkyrie_get_cmap,
+ valkyrie_set_cmap,
+ valkyrie_pan_display,
+ valkyrie_ioctl
+};
+
+static int valkyriefb_getcolreg(u_int regno, u_int *red, u_int *green,
+ u_int *blue, u_int *transp, struct fb_info *info);
+static int valkyriefb_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 valkyrie_open(struct fb_info *info, int user)
+{
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int valkyrie_release(struct fb_info *info, int user)
+{
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static int valkyrie_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info)
+{
+ struct fb_info_valkyrie *cp = (struct fb_info_valkyrie *) info;
+
+ *fix = cp->fix;
+ return 0;
+}
+
+static int valkyrie_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ struct fb_info_valkyrie *cp = (struct fb_info_valkyrie *) info;
+
+ *var = cp->var;
+ return 0;
+}
+
+/* Sets everything according to var */
+static int valkyrie_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
+ struct display *disp;
+ struct fb_par_valkyrie par;
+ int depthchange, err;
+
+ disp = (con >= 0) ? &fb_display[con] : &p->disp;
+ if ((err = valkyrie_var_to_par(var, &par, info))) {
+ /* printk (KERN_ERR "Error in valkyrie_set_var, calling valkyrie_var_to_par: %d.\n", err); */
+ return err;
+ }
+
+ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) {
+ /* printk("Not activating, in valkyrie_set_var.\n"); */
+ valkyrie_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);
+ /* adding "&& !DIRTY(pixclock)" corrects vmode-switching problems */
+ if(!DIRTY(xres) && !DIRTY(yres) && !DIRTY(xres_virtual) &&
+ !DIRTY(yres_virtual) && !DIRTY(bits_per_pixel) && !DIRTY(pixclock)) {
+ valkyrie_par_to_var(&par, var);
+ p->var = disp->var = *var;
+ return 0;
+ }
+
+ p->par = par;
+ valkyrie_par_to_var(&par, var);
+ p->var = *var;
+ valkyrie_par_to_fix(&par, &p->fix, p);
+ valkyrie_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)
+ valkyrie_set_par(&par, 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 valkyrie_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 valkyrie_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ if (con == currcon) {
+ /* current console? */
+ return fb_get_cmap(cmap, kspc, valkyriefb_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 valkyrie_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, kspc, valkyriefb_setcolreg, info);
+ }
+ fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
+ return 0;
+}
+
+static int valkyrie_ioctl(struct inode *inode, struct file *file, u_int cmd,
+ u_long arg, int con, struct fb_info *info)
+{
+ return -EINVAL;
+}
+
+static int valkyriefb_switch(int con, struct fb_info *fb)
+{
+ struct fb_info_valkyrie *info = (struct fb_info_valkyrie *) fb;
+ struct fb_par_valkyrie par;
+
+ if (fb_display[currcon].cmap.len)
+ fb_get_cmap(&fb_display[currcon].cmap, 1, valkyriefb_getcolreg,
+ fb);
+ currcon = con;
+#if 1
+ valkyrie_var_to_par(&fb_display[currcon].var, &par, fb);
+ valkyrie_set_par(&par, info);
+ do_install_cmap(con, fb);
+#else
+ /* I see no reason not to do this. Minus info->changevar(). */
+ /* DOH. This makes valkyrie_set_var compare, you guessed it, */
+ /* fb_display[con].var (first param), and fb_display[con].var! */
+ /* Perhaps I just fixed that... */
+ switching = 1;
+ valkyrie_set_var(&fb_display[con].var, con, info);
+ switching = 0;
+#endif
+ return 0;
+}
+
+static int valkyriefb_updatevar(int con, struct fb_info *info)
+{
+ return 0;
+}
+
+static void valkyriefb_blank(int blank_mode, struct fb_info *info)
+{
+/*
+ * Blank the screen if blank_mode != 0, else unblank. If blank_mode == 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
+ */
+ struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
+ struct valkyrie_regvals *init;
+ unsigned char vmode;
+
+ if (p->disp.can_soft_blank
+ && ((vmode = p->par.vmode) > 0)
+ && (vmode <= VMODE_MAX)
+ && ((init = valkyrie_reg_init[vmode - 1]) != NULL)) {
+ if (blank_mode)
+ --blank_mode;
+ switch (blank_mode) {
+ default: /* unblank */
+ out_8(&p->valkyrie_regs->mode.r, init->mode);
+ break;
+ case VESA_VSYNC_SUSPEND:
+ case VESA_HSYNC_SUSPEND:
+ /*
+ * [kps] Value extracted from MacOS. I don't know
+ * whether this bit disables hsync or vsync, or
+ * whether the hardware can do the other as well.
+ */
+ out_8(&p->valkyrie_regs->mode.r, init->mode | 0x40);
+ break;
+ case VESA_POWERDOWN:
+ out_8(&p->valkyrie_regs->mode.r, 0x66);
+ break;
+ }
+ }
+}
+
+static int valkyriefb_getcolreg(u_int regno, u_int *red, u_int *green,
+ u_int *blue, u_int *transp, struct fb_info *info)
+{
+ struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
+
+ if (regno > 255)
+ return 1;
+ *red = (p->palette[regno].red<<8) | p->palette[regno].red;
+ *green = (p->palette[regno].green<<8) | p->palette[regno].green;
+ *blue = (p->palette[regno].blue<<8) | p->palette[regno].blue;
+
+ return 0;
+}
+
+static int valkyriefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
+{
+ struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
+ volatile struct cmap_regs *cmap_regs = p->cmap_regs;
+
+
+ if (regno > 255)
+ return 1;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ p->palette[regno].red = red;
+ p->palette[regno].green = green;
+ p->palette[regno].blue = blue;
+
+ /* tell clut which address to fill */
+ out_8(&p->cmap_regs->addr, regno);
+ udelay(1);
+ /* send one color channel at a time */
+ out_8(&cmap_regs->lut, red);
+ out_8(&cmap_regs->lut, green);
+ out_8(&cmap_regs->lut, blue);
+
+ if (regno < 16) {
+#ifdef FBCON_HAS_CFB16
+ p->fbcon_cfb16_cmap[regno] = (regno << 10) | (regno << 5) | regno;
+#endif
+ }
+
+ return 0;
+}
+
+static void do_install_cmap(int con, struct fb_info *info)
+{
+ if (con != currcon)
+ return;
+ if (fb_display[con].cmap.len) {
+ fb_set_cmap(&fb_display[con].cmap, 1, valkyriefb_setcolreg,
+ info);
+ }
+ else {
+ int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+ fb_set_cmap(fb_default_cmap(size), 1, valkyriefb_setcolreg,
+ info);
+ }
+}
+
+#ifdef CONFIG_FB_COMPAT_XPMAC
+extern struct vc_mode display_info;
+extern struct fb_info *console_fb_info;
+#endif /* CONFIG_FB_COMPAT_XPMAC */
+
+static int valkyrie_vram_reqd(int video_mode, int color_mode)
+{
+ int pitch;
+
+ if ((pitch = valkyrie_reg_init[video_mode-1]->pitch[color_mode]) == 0)
+ pitch = 2 * valkyrie_reg_init[video_mode-1]->pitch[0];
+ return valkyrie_reg_init[video_mode-1]->vres * pitch;
+}
+
+static void set_valkyrie_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_valkyrie(struct fb_info_valkyrie *p))
+{
+ struct fb_par_valkyrie *par = &p->par;
+ struct fb_var_screeninfo var;
+ int j, k;
+
+ p->sense = read_valkyrie_sense(p);
+ printk("Monitor sense value = 0x%x, ", p->sense);
+
+ /* Try to pick a video mode out of NVRAM if we have one. */
+ if (default_vmode == VMODE_NVRAM) {
+ default_vmode = nvram_read_byte(NV_VMODE);
+ if (default_vmode <= 0
+ || default_vmode > VMODE_MAX
+ || !valkyrie_reg_init[default_vmode - 1])
+ default_vmode = VMODE_CHOOSE;
+ }
+ if (default_vmode == VMODE_CHOOSE)
+ default_vmode = mac_map_monitor_sense(p->sense);
+ if (!valkyrie_reg_init[default_vmode - 1])
+ default_vmode = VMODE_640_480_67;
+ if (default_cmode == CMODE_NVRAM)
+ default_cmode = nvram_read_byte(NV_CMODE);
+
+ /*
+ * Reduce the pixel size if we don't have enough VRAM or bandwitdh.
+ */
+ if (default_cmode < CMODE_8
+ || default_cmode > CMODE_16
+ || valkyrie_reg_init[default_vmode-1]->pitch[default_cmode] == 0
+ || valkyrie_vram_reqd(default_vmode, default_cmode) > p->total_vram)
+ default_cmode = CMODE_8;
+
+ printk("using video mode %d and color mode %d.\n", default_vmode, default_cmode);
+
+ mac_vmode_to_var(default_vmode, default_cmode, &var);
+ if (valkyrie_var_to_par(&var, par, &p->info)) {
+ printk(KERN_ERR "valkyriefb: can't set default video mode\n");
+ return ;
+ }
+
+ valkyrie_init_fix(&p->fix, p);
+ valkyrie_par_to_fix(&p->par, &p->fix, p);
+ valkyrie_par_to_var(&p->par, &p->var);
+ valkyrie_init_display(&p->disp);
+ valkyrie_par_to_display(&p->par, &p->disp, &p->fix, p);
+ valkyrie_init_info(&p->info, p);
+
+ /* Initialize colormap */
+ for (j = 0; j < 16; j++) {
+ k = color_table[j];
+ p->palette[j].red = default_red[k];
+ p->palette[j].green = default_grn[k];
+ p->palette[j].blue = default_blu[k];
+ }
+
+ valkyrie_set_var (&var, -1, &p->info);
+
+ if (register_framebuffer(&p->info) < 0) {
+ kfree(p);
+ return;
+ }
+
+ printk("fb%d: valkyrie frame buffer device\n", GET_FB_IDX(p->info.node));
+}
+
+static void valkyrie_set_par(const struct fb_par_valkyrie *par,
+ struct fb_info_valkyrie *p)
+{
+ struct valkyrie_regvals *init;
+ volatile struct valkyrie_regs *valkyrie_regs = p->valkyrie_regs;
+ int vmode, cmode;
+
+ vmode = par->vmode;
+ cmode = par->cmode;
+
+ if (vmode <= 0
+ || vmode > VMODE_MAX
+ || (init = valkyrie_reg_init[vmode - 1]) == NULL)
+ panic("valkyrie: display mode %d not supported", vmode);
+
+ /* Reset the valkyrie */
+ out_8(&valkyrie_regs->status.r, 0);
+ udelay(100);
+
+ /* Initialize display timing registers */
+ out_8(&valkyrie_regs->mode.r, init->mode | 0x80);
+ out_8(&valkyrie_regs->depth.r, cmode + 3);
+ set_valkyrie_clock(init->clock_params);
+ udelay(100);
+
+ /* Turn on display */
+ out_8(&valkyrie_regs->mode.r, init->mode);
+
+#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_16) ? 16 : 8;
+ display_info.pitch = p->fix.line_length;
+ display_info.mode = vmode;
+ strncpy(display_info.name, "valkyrie",
+ sizeof(display_info.name));
+ display_info.fb_address = p->frame_buffer_phys + 0x1000;
+ display_info.cmap_adr_address = p->cmap_regs_phys;
+ display_info.cmap_data_address = p->cmap_regs_phys + 8;
+ display_info.disp_reg_address = p->valkyrie_regs_phys;
+ console_fb_info = &p->info;
+ }
+#endif /* CONFIG_FB_COMPAT_XPMAC */
+}
+
+__initfunc(void valkyriefb_init(void))
+{
+#ifndef CONFIG_FB_OF
+ struct device_node *dp;
+
+ dp = find_devices("valkyrie");
+ if (dp != 0)
+ valkyrie_of_init(dp);
+#endif /* CONFIG_FB_OF */
+}
+
+__initfunc(void valkyrie_of_init(struct device_node *dp))
+{
+ struct fb_info_valkyrie *p;
+ unsigned long addr, size;
+
+ if(dp->n_addrs != 1)
+ panic("expecting 1 address for valkyrie (got %d)", dp->n_addrs);
+
+ p = kmalloc(sizeof(*p), GFP_ATOMIC);
+ if (p == 0)
+ return;
+ memset(p, 0, sizeof(*p));
+
+ /* Map in frame buffer and registers */
+ addr = dp->addrs[0].address;
+ size = 4096;
+ p->frame_buffer_phys = addr;
+ p->frame_buffer = __ioremap(addr, 0x100000, _PAGE_WRITETHRU);
+ p->cmap_regs_phys = addr + 0x304000;
+ p->cmap_regs = ioremap(p->cmap_regs_phys, size);
+ p->valkyrie_regs_phys = addr + 0x30a000;
+ p->valkyrie_regs = ioremap(p->valkyrie_regs_phys, size);
+
+ /*
+ * kps: As far as I know, all Valkyries have fixed usable VRAM.
+ */
+ p->total_vram = 0x100000;
+
+ init_valkyrie(p);
+}
+
+/*
+ * Get the monitor sense value.
+ */
+static int read_valkyrie_sense(struct fb_info_valkyrie *p)
+{
+ int sense, in;
+
+ out_8(&p->valkyrie_regs->msense.r, 0); /* release all lines */
+ __delay(20000);
+ sense = ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x70) << 4;
+ /* drive each sense line low in turn and collect the other 2 */
+ out_8(&p->valkyrie_regs->msense.r, 4); /* drive A low */
+ __delay(20000);
+ sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x30);
+ out_8(&p->valkyrie_regs->msense.r, 2); /* drive B low */
+ __delay(20000);
+ sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x40) >> 3;
+ sense |= (in & 0x10) >> 2;
+ out_8(&p->valkyrie_regs->msense.r, 1); /* drive C low */
+ __delay(20000);
+ sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x60) >> 5;
+
+ out_8(&p->valkyrie_regs->msense.r, 7);
+
+ return sense;
+}
+
+/*
+ * This routine takes a user-supplied var,
+ * and picks the best vmode/cmode from it.
+ */
+static int valkyrie_var_to_par(struct fb_var_screeninfo *var,
+ struct fb_par_valkyrie *par, const struct fb_info *fb_info)
+
+/* [bkn] I did a major overhaul of this function.
+ *
+ * Much of the old code was "swiped by jonh from atyfb.c". Because
+ * macmodes has mac_var_to_vmode, I felt that it would be better to
+ * rework this function to use that, instead of reinventing the wheel to
+ * add support for vmode 17. This was reinforced by the fact that
+ * the previously swiped atyfb.c code is no longer there.
+ *
+ * So, I swiped and adapted platinum_var_to_par (from platinumfb.c), replacing
+ * most, but not all, of the old code in the process. One side benefit of
+ * swiping the platinumfb code is that we now have more comprehensible error
+ * messages when a vmode/cmode switch fails. (Most of the error messages are
+ * platinumfb.c, but I added two of my own, and I also changed some commas
+ * into colons to make the messages more consistent with other Linux error
+ * messages.) In addition, I think the new code *might* fix some vmode-
+ * switching oddities, but I'm not sure.
+ *
+ * There may be some more opportunities for cleanup in here, but this is a
+ * good start...
+ */
+
+{
+ int bpp = var->bits_per_pixel;
+ struct valkyrie_regvals *init;
+ struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) fb_info;
+
+ /* these are old variables that are no longer needed with my new code
+ [bkn]
+
+ int xres = var->xres;
+ int yres = var->yres;
+ */
+
+ /*
+ * 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.
+ */
+
+ if(mac_var_to_vmode(var, &par->vmode, &par->cmode) != 0) {
+ printk(KERN_ERR "valkyrie_var_to_par: mac_var_to_vmode unsuccessful.\n");
+ printk(KERN_ERR "valkyrie_var_to_par: var->xres = %d\n", var->xres);
+ printk(KERN_ERR "valkyrie_var_to_par: var->yres = %d\n", var->yres);
+ printk(KERN_ERR "valkyrie_var_to_par: var->xres_virtual = %d\n", var->xres_virtual);
+ printk(KERN_ERR "valkyrie_var_to_par: var->yres_virtual = %d\n", var->yres_virtual);
+ printk(KERN_ERR "valkyrie_var_to_par: var->bits_per_pixel = %d\n", var->bits_per_pixel);
+ printk(KERN_ERR "valkyrie_var_to_par: var->pixclock = %d\n", var->pixclock);
+ printk(KERN_ERR "valkyrie_var_to_par: var->vmode = %d\n", var->vmode);
+ return -EINVAL;
+ }
+
+ /* Check if we know about the wanted video mode */
+ if(!valkyrie_reg_init[par->vmode-1]) {
+ printk(KERN_ERR "valkyrie_var_to_par: vmode %d not valid.\n", par->vmode);
+ return -EINVAL;
+ }
+
+ par->xres = var->xres;
+ par->yres = var->yres;
+ par->xoffset = 0;
+ par->yoffset = 0;
+ par->vxres = par->xres;
+ par->vyres = par->yres;
+
+ if (var->xres_virtual > var->xres || var->yres_virtual > var->yres
+ || var->xoffset != 0 || var->yoffset != 0) {
+ return -EINVAL;
+ }
+
+ if (bpp <= 8)
+ par->cmode = CMODE_8;
+ else if (bpp <= 16)
+ par->cmode = CMODE_16;
+ else {
+ printk(KERN_ERR "valkyrie_var_to_par: cmode %d not supported.\n", par->cmode);
+ return -EINVAL;
+ }
+
+ init = valkyrie_reg_init[par->vmode-1];
+ if (init->pitch[par->cmode] == 0) {
+ printk(KERN_ERR "valkyrie_var_to_par: vmode %d does not support cmode %d.\n", par->vmode, par->cmode);
+ return -EINVAL;
+ }
+
+ if (valkyrie_vram_reqd(par->vmode, par->cmode) > p->total_vram) {
+ printk(KERN_ERR "valkyrie_var_to_par: not enough ram for vmode %d, cmode %d.\n", par->vmode, par->cmode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int valkyrie_par_to_var(struct fb_par_valkyrie *par, struct fb_var_screeninfo *var)
+{
+ return mac_vmode_to_var(par->vmode, par->cmode, var);
+}
+
+static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p)
+{
+ memset(fix, 0, sizeof(*fix));
+ strcpy(fix->id, "valkyrie");
+ fix->mmio_start = (char *)p->valkyrie_regs_phys;
+ fix->mmio_len = sizeof(struct valkyrie_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 above */
+static void valkyrie_par_to_fix(struct fb_par_valkyrie *par,
+ struct fb_fix_screeninfo *fix,
+ struct fb_info_valkyrie *p)
+{
+ fix->smem_start = (void *)(p->frame_buffer_phys + 0x1000);
+#if 1
+ fix->smem_len = valkyrie_vram_reqd(par->vmode, par->cmode);
+#else
+ fix->smem_len = p->total_vram;
+#endif
+ fix->visual = (par->cmode == CMODE_8) ?
+ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+ fix->line_length = par->vxres << par->cmode;
+ /* ywrapstep, xpanstep, ypanstep */
+}
+
+static void valkyrie_init_display(struct display *disp)
+{
+ memset(disp, 0, sizeof(*disp));
+ disp->type = /* fix->type */ FB_TYPE_PACKED_PIXELS;
+ disp->can_soft_blank = can_soft_blank;
+ disp->scrollmode = SCROLL_YREDRAW;
+}
+
+static void valkyrie_par_to_display(struct fb_par_valkyrie *par,
+ struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p)
+{
+ disp->var = p->var;
+ disp->screen_base = (char *) p->frame_buffer + 0x1000;
+ disp->visual = fix->visual;
+ disp->line_length = fix->line_length;
+
+ if(disp->scrollmode != SCROLL_YREDRAW) {
+ printk(KERN_ERR "Scroll mode not YREDRAW in valkyrie_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;
+ disp->dispsw_data = p->fbcon_cfb16_cmap;
+ break;
+#endif
+ default:
+ disp->dispsw = &fbcon_dummy;
+ break;
+ }
+}
+
+static void __init valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p)
+{
+ strcpy(info->modename, p->fix.id);
+ info->node = -1; /* ??? danj */
+ info->fbops = &valkyriefb_ops;
+ info->disp = &p->disp;
+ strcpy(info->fontname, fontname);
+ info->changevar = NULL;
+ info->switch_con = &valkyriefb_switch;
+ info->updatevar = &valkyriefb_updatevar;
+ info->blank = &valkyriefb_blank;
+ info->flags = FBINFO_FLAG_DEFAULT;
+}
+
+
+/*
+ * Parse user speficied options (`video=valkyriefb:')
+ */
+__initfunc(void valkyriefb_setup(char *options, int *ints))
+{
+ char *this_opt;
+
+ 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;
+ }
+ else if (!strncmp(this_opt, "vmode:", 6)) {
+ int vmode = simple_strtoul(this_opt+6, NULL, 0);
+ if (vmode > 0 && vmode <= VMODE_MAX)
+ default_vmode = vmode;
+ }
+ else if (!strncmp(this_opt, "cmode:", 6)) {
+ int depth = simple_strtoul(this_opt+6, NULL, 0);
+ switch (depth) {
+ case 8:
+ default_cmode = CMODE_8;
+ break;
+ case 15:
+ case 16:
+ default_cmode = CMODE_16;
+ break;
+ }
+ }
+ /* XXX - remove these options once blanking has been tested */
+ else if (!strncmp(this_opt, "noblank", 7)) {
+ can_soft_blank = 0;
+ }
+ else if (!strncmp(this_opt, "blank", 5)) {
+ can_soft_blank = 1;
+ }
+ }
+}
diff --git a/drivers/video/valkyriefb.h b/drivers/video/valkyriefb.h
new file mode 100644
index 000000000..ee246a4fc
--- /dev/null
+++ b/drivers/video/valkyriefb.h
@@ -0,0 +1,186 @@
+/*
+ * valkyriefb.h: Constants of all sorts for valkyriefb
+ *
+ * Created 8 August 1998 by Martin Costabel and Kevin Schoedel
+ *
+ * Vmode-switching changes and vmode 15/17 modifications created 29 August
+ * 1998 by Barry Nathan <barryn@pobox.com>.
+ *
+ * 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 directly on:
+ *
+ * controlfb.h: Constants of all sorts for controlfb
+ * Copyright (C) 1998 Daniel Jacobowitz <dan@debian.org>
+ *
+ * pmc-valkyrie.h: Console support for PowerMac "control" display adaptor.
+ * Copyright (C) 1997 Paul Mackerras.
+ *
+ * pmc-valkyrie.c: Console support for PowerMac "control" display adaptor.
+ * Copyright (C) 1997 Paul Mackerras.
+ *
+ * and indirectly from:
+ *
+ * pmc-control.h: Console support for PowerMac "control" display adaptor.
+ * Copyright (C) 1997 Paul Mackerras.
+ *
+ * pmc-control.c: Console support for PowerMac "control" display adaptor.
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * platinumfb.c: Console support for PowerMac "platinum" display adaptor.
+ * Copyright (C) 1998 Jon Howell
+ */
+
+/*
+ * Structure of the registers for the Valkyrie colormap registers.
+ */
+struct cmap_regs {
+ unsigned char addr;
+ char pad1[7];
+ unsigned char lut;
+};
+
+/*
+ * Structure of the registers for the "valkyrie" display adaptor.
+ */
+
+struct vpreg { /* padded register */
+ unsigned char r;
+ char pad[7];
+};
+
+
+struct valkyrie_regs {
+ struct vpreg mode;
+ struct vpreg depth;
+ struct vpreg status;
+ struct vpreg reg3;
+ struct vpreg intr;
+ struct vpreg reg5;
+ struct vpreg intr_enb;
+ struct vpreg msense;
+};
+
+/*
+ * Register initialization tables for the valkyrie display.
+ *
+ * Dot clock rate is
+ * 3.9064MHz * 2**clock_params[2] * clock_params[1] / clock_params[0].
+ */
+struct valkyrie_regvals {
+ unsigned char mode;
+ unsigned char clock_params[3];
+ int pitch[2]; /* bytes/line, indexed by color_mode */
+ int hres;
+ int vres;
+};
+
+/* Register values for 1024x768, 75Hz mode (17) */
+/* I'm not sure which mode this is (16 or 17), so I'm defining it as 17,
+ * since the equivalent mode in controlfb (which I adapted this from) is
+ * also 17. Just because MacOS can't do this on Valkyrie doesn't mean we
+ * can't! :)
+ *
+ * I was going to use 12, 31, 3, which I found by myself, but instead I'm
+ * using 11, 28, 3 like controlfb, for consistency's sake.
+ */
+
+static struct valkyrie_regvals valkyrie_reg_init_17 = {
+ 15,
+ { 11, 28, 3 }, /* pixel clock = 79.55MHz for V=74.50Hz */
+ { 1024, 0 },
+ 1024, 768
+};
+
+/* Register values for 1024x768, 72Hz mode (15) */
+/* This used to be 12, 30, 3 for pixel clock = 78.12MHz for V=72.12Hz, but
+ * that didn't match MacOS in the same video mode on this chip, and it also
+ * caused the 15" Apple Studio Display to not work in this mode. While this
+ * mode still doesn't match MacOS exactly (as far as I can tell), it's a lot
+ * closer now, and it works with the Apple Studio Display.
+ *
+ * Yes, even though MacOS calls it "72Hz", in reality it's about 70Hz.
+ */
+static struct valkyrie_regvals valkyrie_reg_init_15 = {
+ 15,
+ { 12, 29, 3 }, /* pixel clock = 75.52MHz for V=69.71Hz? */
+ /* I interpolated the V=69.71 from the vmode 14 and old 15
+ * numbers. Is this result correct?
+ */
+ { 1024, 0 },
+ 1024, 768
+};
+
+/* Register values for 1024x768, 60Hz mode (14) */
+static struct valkyrie_regvals valkyrie_reg_init_14 = {
+ 14,
+ { 15, 31, 3 }, /* pixel clock = 64.58MHz for V=59.62Hz */
+ { 1024, 0 },
+ 1024, 768
+};
+
+/* Register values for 832x624, 75Hz mode (13) */
+static struct valkyrie_regvals valkyrie_reg_init_13 = {
+ 9,
+ { 23, 42, 3 }, /* pixel clock = 57.07MHz for V=74.27Hz */
+ { 832, 0 },
+ 832, 624
+};
+
+/* Register values for 800x600, 72Hz mode (11) */
+static struct valkyrie_regvals valkyrie_reg_init_11 = {
+ 13,
+ { 17, 27, 3 }, /* pixel clock = 49.63MHz for V=71.66Hz */
+ { 800, 0 },
+ 800, 600
+};
+
+/* Register values for 800x600, 60Hz mode (10) */
+static struct valkyrie_regvals valkyrie_reg_init_10 = {
+ 12,
+ { 20, 53, 2 }, /* pixel clock = 41.41MHz for V=59.78Hz */
+ { 800, 1600 },
+ 800, 600
+};
+
+/* Register values for 640x480, 67Hz mode (6) */
+static struct valkyrie_regvals valkyrie_reg_init_6 = {
+ 6,
+ { 14, 27, 2 }, /* pixel clock = 30.13MHz for V=66.43Hz */
+ { 640, 1280 },
+ 640, 480
+};
+
+/* Register values for 640x480, 60Hz mode (5) */
+static struct valkyrie_regvals valkyrie_reg_init_5 = {
+ 11,
+ { 23, 37, 2 }, /* pixel clock = 25.14MHz for V=59.85Hz */
+ { 640, 1280 },
+ 640, 480
+};
+
+static struct valkyrie_regvals *valkyrie_reg_init[VMODE_MAX] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &valkyrie_reg_init_5,
+ &valkyrie_reg_init_6,
+ NULL,
+ NULL,
+ NULL,
+ &valkyrie_reg_init_10,
+ &valkyrie_reg_init_11,
+ NULL,
+ &valkyrie_reg_init_13,
+ &valkyrie_reg_init_14,
+ &valkyrie_reg_init_15,
+ NULL,
+ &valkyrie_reg_init_17,
+ NULL,
+ NULL,
+ NULL
+};
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index cf1534a9a..cbad38a82 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -4,9 +4,9 @@
* 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>
+ * (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
*
- */
+ */
#include <linux/module.h>
#include <linux/kernel.h>
@@ -21,13 +21,16 @@
#include <linux/selection.h>
#include <linux/ioport.h>
#include <linux/init.h>
+#include <linux/config.h>
#include <asm/io.h>
+#include <asm/mtrr.h>
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-#include "fbcon-cfb32.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
#define dac_reg (0x3c8)
#define dac_val (0x3c9)
@@ -47,6 +50,7 @@ char *video_vbase; /* mapped */
int video_bpp;
int video_width;
int video_height;
+int video_height_virtual;
int video_type = FB_TYPE_PACKED_PIXELS;
int video_visual;
int video_linelength;
@@ -75,19 +79,29 @@ static struct fb_var_screeninfo vesafb_defined = {
static struct display disp;
static struct fb_info fb_info;
-static struct { u_char red, green, blue, pad; } palette[256];
+static struct { u_short blue, green, red, pad; } palette[256];
+static union {
+#ifdef FBCON_HAS_CFB16
+ u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+ u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u32 cfb32[16];
+#endif
+} fbcon_cmap;
-static int inverse = 0;
+static int inverse = 0;
+static int currcon = 0;
-static int currcon = 0;
+static int pmi_setpal = 0; /* pmi for palette changes ??? */
+static int ypan = 0;
+static int ywrap = 0;
+static unsigned short *pmi_base = 0;
+static void (*pmi_start)(void);
+static void (*pmi_pal)(void);
-/* --------------------------------------------------------------------- */
-/* speed up scrolling */
-
-#define USE_REDRAW 1
-#define USE_MEMMOVE 2
-
-static int vesafb_scroll = USE_REDRAW;
static struct display_switch vesafb_sw;
/* --------------------------------------------------------------------- */
@@ -111,8 +125,39 @@ static int vesafb_release(struct fb_info *info, int user)
return(0);
}
-static int fb_update_var(int con, struct fb_info *info)
+static int vesafb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
{
+ int offset;
+
+ if (!ypan && !ywrap)
+ return -EINVAL;
+ if (var->xoffset)
+ return -EINVAL;
+ if (ypan && var->yoffset+var->yres > var->yres_virtual)
+ return -EINVAL;
+ if (ywrap && var->yoffset > var->yres_virtual)
+ return -EINVAL;
+
+ offset = (var->yoffset * video_linelength + var->xoffset) / 4;
+
+ __asm__ __volatile__(
+ "call *(%%edi)"
+ : /* no return value */
+ : "a" (0x4f07), /* EAX */
+ "b" (0), /* EBX */
+ "c" (offset), /* ECX */
+ "d" (offset >> 16), /* EDX */
+ "D" (&pmi_start)); /* EDI */
+ return 0;
+}
+
+static int vesafb_update_var(int con, struct fb_info *info)
+{
+ if (con == currcon && (ywrap || ypan)) {
+ struct fb_var_screeninfo *var = &fb_display[currcon].var;
+ return vesafb_pan_display(var,con,info);
+ }
return 0;
}
@@ -126,9 +171,9 @@ static int vesafb_get_fix(struct fb_fix_screeninfo *fix, int con,
fix->smem_len=video_size;
fix->type = video_type;
fix->visual = video_visual;
- fix->xpanstep=0;
- fix->ypanstep=0;
- fix->ywrapstep=0;
+ fix->xpanstep = 0;
+ fix->ypanstep = (ywrap || ypan) ? 1 : 0;
+ fix->ywrapstep = ywrap ? 1 : 0;
fix->line_length=video_linelength;
return 0;
}
@@ -179,28 +224,66 @@ static void vesafb_set_disp(int con)
case 15:
case 16:
sw = &fbcon_cfb16;
+ display->dispsw_data = fbcon_cmap.cfb16;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ sw = &fbcon_cfb24;
+ display->dispsw_data = fbcon_cmap.cfb24;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
sw = &fbcon_cfb32;
+ display->dispsw_data = fbcon_cmap.cfb32;
break;
#endif
default:
+ sw = &fbcon_dummy;
return;
}
memcpy(&vesafb_sw, sw, sizeof(*sw));
display->dispsw = &vesafb_sw;
- if (vesafb_scroll == USE_REDRAW) {
+ if (!ypan && !ywrap) {
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)
+ struct fb_info *info)
{
- memcpy(var, &vesafb_defined, sizeof(struct fb_var_screeninfo));
+
+ if (var->xres != vesafb_defined.xres ||
+ var->yres != vesafb_defined.yres ||
+ var->xres_virtual != vesafb_defined.xres_virtual ||
+ var->yres_virtual > video_height_virtual ||
+ var->yres_virtual < video_height ||
+ var->xoffset ||
+ var->bits_per_pixel != vesafb_defined.bits_per_pixel ||
+ var->nonstd)
+ return -EINVAL;
+
+ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
+ return 0;
+
+ if (ypan || ywrap) {
+ if (vesafb_defined.yres_virtual != var->yres_virtual) {
+ vesafb_defined.yres_virtual = var->yres_virtual;
+ if (con != -1) {
+ fb_display[con].var = vesafb_defined;
+ info->changevar(con);
+ }
+ }
+
+ if (var->yoffset != vesafb_defined.yoffset)
+ return vesafb_pan_display(var,con,info);
+ return 0;
+ }
+
+ if (var->yoffset)
+ return -EINVAL;
return 0;
}
@@ -219,9 +302,41 @@ static int vesa_getcolreg(unsigned regno, unsigned *red, unsigned *green,
*red = palette[regno].red;
*green = palette[regno].green;
*blue = palette[regno].blue;
+ *transp = 0;
return 0;
}
+#ifdef FBCON_HAS_CFB8
+
+static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
+{
+ struct { u_char blue, green, red, pad; } entry;
+
+ if (pmi_setpal) {
+ entry.red = red >> 10;
+ entry.green = green >> 10;
+ entry.blue = blue >> 10;
+ entry.pad = 0;
+ __asm__ __volatile__(
+ "call *(%%esi)"
+ : /* no return value */
+ : "a" (0x4f09), /* EAX */
+ "b" (0), /* EBX */
+ "c" (1), /* ECX */
+ "d" (regno), /* EDX */
+ "D" (&entry), /* EDI */
+ "S" (&pmi_pal)); /* ESI */
+ } else {
+ /* without protected mode interface, try VGA registers... */
+ outb_p(regno, dac_reg);
+ outb_p(red >> 10, dac_val);
+ outb_p(green >> 10, dac_val);
+ outb_p(blue >> 10, dac_val);
+ }
+}
+
+#endif
+
static int vesa_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *fb_info)
@@ -235,7 +350,7 @@ static int vesa_setcolreg(unsigned regno, unsigned red, unsigned green,
if (regno >= video_cmap_len)
return 1;
-
+
palette[regno].red = red;
palette[regno].green = green;
palette[regno].blue = blue;
@@ -243,28 +358,44 @@ static int vesa_setcolreg(unsigned regno, unsigned red, unsigned green,
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);
+ vesa_setpalette(regno,red,green,blue);
break;
#endif
#ifdef FBCON_HAS_CFB16
case 15:
case 16:
- fbcon_cfb16_cmap[regno] =
- (red << vesafb_defined.red.offset) | (green << 5) | blue;
+ if (vesafb_defined.red.offset == 10) {
+ /* 1:5:5:5 */
+ fbcon_cmap.cfb16[regno] =
+ ((red & 0xf800) >> 1) |
+ ((green & 0xf800) >> 6) |
+ ((blue & 0xf800) >> 11);
+ } else {
+ /* 0:5:6:5 */
+ fbcon_cmap.cfb16[regno] =
+ ((red & 0xf800) ) |
+ ((green & 0xfc00) >> 5) |
+ ((blue & 0xf800) >> 11);
+ }
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
- /* FIXME: todo */
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ fbcon_cmap.cfb24[regno] =
+ (red << vesafb_defined.red.offset) |
+ (green << vesafb_defined.green.offset) |
+ (blue << vesafb_defined.blue.offset);
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
- fbcon_cfb32_cmap[regno] =
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ fbcon_cmap.cfb32[regno] =
(red << vesafb_defined.red.offset) |
(green << vesafb_defined.green.offset) |
(blue << vesafb_defined.blue.offset);
@@ -279,11 +410,9 @@ 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);
+ fb_set_cmap(&fb_display[con].cmap, 1, vesa_setcolreg, info);
else
- fb_set_cmap(fb_default_cmap(video_cmap_len),
- &fb_display[con].var, 1, vesa_setcolreg,
+ fb_set_cmap(fb_default_cmap(video_cmap_len), 1, vesa_setcolreg,
info);
}
@@ -291,7 +420,7 @@ 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);
+ return fb_get_cmap(cmap, 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
@@ -311,20 +440,13 @@ static int vesafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return err;
}
if (con == currcon) /* current console? */
- return fb_set_cmap(cmap, &fb_display[con].var, kspc, vesa_setcolreg, info);
+ return fb_set_cmap(cmap, 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,
+static int vesafb_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg, int con,
struct fb_info *info)
{
@@ -355,14 +477,18 @@ void vesafb_setup(char *options, int *ints)
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;
+ ywrap=0,ypan=0;
+ else if (! strcmp(this_opt, "ypan"))
+ ywrap=0,ypan=1;
+ else if (! strcmp(this_opt, "ywrap"))
+ ywrap=1,ypan=0;
+ else if (! strcmp(this_opt, "vgapal"))
+ pmi_setpal=0;
+ else if (! strcmp(this_opt, "pmipal"))
+ pmi_setpal=1;
else if (!strncmp(this_opt, "font:", 5))
strcpy(fb_info.fontname, this_opt+5);
}
@@ -372,13 +498,14 @@ 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);
+ fb_get_cmap(&fb_display[currcon].cmap, 1, vesa_getcolreg,
+ info);
currcon = con;
/* Install new colormap */
do_install_cmap(con, info);
- return 0;
+ vesafb_update_var(con,info);
+ return 1;
}
/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
@@ -400,24 +527,72 @@ __initfunc(void vesafb_init(void))
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_size = screen_info.lfb_size * 65536;
video_visual = (video_bpp == 8) ?
- FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
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");
-
+ printk("vesafb: framebuffer at 0x%p, mapped to 0x%p, size %dk\n",
+ video_base, video_vbase, video_size/1024);
+ printk("vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
+ video_width, video_height, video_bpp, video_linelength, screen_info.pages);
+
+ if (screen_info.vesapm_seg) {
+ printk("vesafb: protected mode interface info at %04x:%04x\n",
+ screen_info.vesapm_seg,screen_info.vesapm_off);
+ }
+
+ if (screen_info.vesapm_seg < 0xc000)
+ ywrap = ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */
+
+ if (ypan || ywrap || pmi_setpal) {
+ pmi_base = (unsigned short*)(__PAGE_OFFSET+((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
+ pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
+ pmi_pal = (void*)((char*)pmi_base + pmi_base[2]);
+ printk("vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal);
+ if (pmi_base[3]) {
+ printk("vesafb: pmi: ports = ");
+ for (i = pmi_base[3]/2; pmi_base[i] != 0xffff; i++)
+ printk("%x ",pmi_base[i]);
+ printk("\n");
+ if (pmi_base[i] != 0xffff) {
+ /*
+ * memory areas not supported (yet?)
+ *
+ * Rules are: we have to set up a descriptor for the requested
+ * memory area and pass it in the ES register to the BIOS function.
+ */
+ printk("vesafb: can't handle memory requests, pmi disabled\n");
+ ywrap = ypan = pmi_setpal = 0;
+ }
+ }
+ }
+
vesafb_defined.xres=video_width;
vesafb_defined.yres=video_height;
vesafb_defined.xres_virtual=video_width;
- vesafb_defined.yres_virtual=video_height;
+ vesafb_defined.yres_virtual=video_size / video_linelength;
vesafb_defined.bits_per_pixel=video_bpp;
+ if ((ypan || ywrap) && vesafb_defined.yres_virtual > video_height) {
+ printk("vesafb: scrolling: %s using protected mode interface, yres_virtual=%d\n",
+ ywrap ? "ywrap" : "ypan",vesafb_defined.yres_virtual);
+ } else {
+ printk("vesafb: scrolling: redraw\n");
+ vesafb_defined.yres_virtual = video_height;
+ ypan = ywrap = 0;
+ }
+ video_height_virtual = vesafb_defined.yres_virtual;
+
+ /* some dummy values for timing to make fbset happy */
+ vesafb_defined.pixclock = 10000000 / video_width * 1000 / video_height;
+ vesafb_defined.left_margin = (video_width / 8) & 0xf8;
+ vesafb_defined.right_margin = 32;
+ vesafb_defined.upper_margin = 16;
+ vesafb_defined.lower_margin = 4;
+ vesafb_defined.hsync_len = (video_width / 8) & 0xf8;
+ vesafb_defined.vsync_len = 4;
+
if (video_bpp > 8) {
vesafb_defined.red.offset = screen_info.red_pos;
vesafb_defined.red.length = screen_info.red_size;
@@ -451,6 +626,9 @@ __initfunc(void vesafb_init(void))
video_cmap_len = 256;
}
request_region(0x3c0, 32, "vga+");
+#ifdef CONFIG_MTRR
+ mtrr_add((unsigned long)video_base, video_size, MTRR_TYPE_WRCOMB, 1);
+#endif
strcpy(fb_info.modename, "VESA VGA");
fb_info.changevar = NULL;
@@ -458,8 +636,9 @@ __initfunc(void vesafb_init(void))
fb_info.fbops = &vesafb_ops;
fb_info.disp=&disp;
fb_info.switch_con=&vesafb_switch;
- fb_info.updatevar=&fb_update_var;
+ fb_info.updatevar=&vesafb_update_var;
fb_info.blank=&vesafb_blank;
+ fb_info.flags=FBINFO_FLAG_DEFAULT;
vesafb_set_disp(-1);
if (register_framebuffer(&fb_info)<0)
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index f2bc39cd0..ccc5e2a27 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -22,13 +22,14 @@
#include <linux/fb.h>
#include <linux/init.h>
-#include "fbcon-mfb.h"
-#include "fbcon-cfb2.h"
-#include "fbcon-cfb4.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-#include "fbcon-cfb24.h"
-#include "fbcon-cfb32.h"
+#include <video/fbcon.h>
+#include <video/fbcon-mfb.h>
+#include <video/fbcon-cfb2.h>
+#include <video/fbcon-cfb4.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
#define arraysize(x) (sizeof(x)/sizeof(*(x)))
@@ -49,6 +50,17 @@ static int currcon = 0;
static struct display disp;
static struct fb_info fb_info;
static struct { u_char red, green, blue, pad; } palette[256];
+static union {
+#ifdef FBCON_HAS_CFB16
+ u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+ u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u32 cfb32[16];
+#endif
+} fbcon_cmap;
static char vfb_name[16] = "Virtual FB";
static struct fb_var_screeninfo vfb_default = {
@@ -282,20 +294,23 @@ static int vfb_set_var(struct fb_var_screeninfo *var, int con,
#ifdef FBCON_HAS_CFB16
case 16:
display->dispsw = &fbcon_cfb16;
+ display->dispsw_data = fbcon_cmap.cfb16;
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
display->dispsw = &fbcon_cfb24;
+ display->dispsw_data = fbcon_cmap.cfb24;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
display->dispsw = &fbcon_cfb32;
+ display->dispsw_data = fbcon_cmap.cfb32;
break;
#endif
default:
- display->dispsw = NULL;
+ display->dispsw = &fbcon_dummy;
break;
}
if (fb_info.changevar)
@@ -349,8 +364,7 @@ static int vfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
if (con == currcon) /* current console? */
- return fb_get_cmap(cmap, &fb_display[con].var, kspc, vfb_getcolreg,
- info);
+ return fb_get_cmap(cmap, kspc, vfb_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
@@ -374,8 +388,7 @@ static int vfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return err;
}
if (con == currcon) /* current console? */
- return fb_set_cmap(cmap, &fb_display[con].var, kspc, vfb_setcolreg,
- info);
+ return fb_set_cmap(cmap, kspc, vfb_setcolreg, info);
else
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
@@ -432,6 +445,7 @@ __initfunc(void vfb_init(void))
fb_info.switch_con = &vfbcon_switch;
fb_info.updatevar = &vfbcon_updatevar;
fb_info.blank = &vfbcon_blank;
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
vfb_set_var(&vfb_default, -1, &fb_info);
@@ -449,8 +463,7 @@ static int vfbcon_switch(int con, struct fb_info *info)
{
/* Do we have to save the colormap? */
if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
- vfb_getcolreg, info);
+ fb_get_cmap(&fb_display[currcon].cmap, 1, vfb_getcolreg, info);
currcon = con;
/* Install new colormap */
@@ -579,9 +592,10 @@ static int vfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
{
if (regno > 255)
return 1;
- *red = palette[regno].red;
- *green = palette[regno].green;
- *blue = palette[regno].blue;
+ *red = (palette[regno].red<<8) | palette[regno].red;
+ *green = (palette[regno].green<<8) | palette[regno].green;
+ *blue = (palette[regno].blue<<8) | palette[regno].blue;
+ *transp = 0;
return 0;
}
@@ -597,6 +611,9 @@ static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
{
if (regno > 255)
return 1;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
palette[regno].red = red;
palette[regno].green = green;
palette[regno].blue = blue;
@@ -609,11 +626,10 @@ static void do_install_cmap(int con, struct fb_info *info)
if (con != currcon)
return;
if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
- vfb_setcolreg, info);
+ fb_set_cmap(&fb_display[con].cmap, 1, vfb_setcolreg, info);
else
- fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
- &fb_display[con].var, 1, vfb_setcolreg, info);
+ fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), 1,
+ vfb_setcolreg, info);
}
diff --git a/drivers/video/vgacon.c b/drivers/video/vgacon.c
index a464d389a..3f76e591a 100644
--- a/drivers/video/vgacon.c
+++ b/drivers/video/vgacon.c
@@ -64,8 +64,6 @@
*/
#undef TRIDENT_GLITCH
-#undef VGA_CAN_DO_64KB
-
#define dac_reg 0x3c8
#define dac_val 0x3c9
#define attrib_port 0x3c0
@@ -115,6 +113,7 @@ static int vga_palette_blanked;
static int vga_is_gfx;
static int vga_512_chars;
static int vga_video_font_height;
+static unsigned int vga_rolled_over = 0;
void no_scroll(char *str, int *ints)
@@ -190,7 +189,7 @@ __initfunc(static const char *vgacon_startup(void))
display_desc = "*MDA";
request_region(0x3b0,12,"mda");
request_region(0x3bf, 1,"mda");
- vga_video_font_height = 16;
+ vga_video_font_height = 14;
}
}
else /* If not, it is color. */
@@ -453,9 +452,8 @@ static int vgacon_switch(struct vc_data *c)
*/
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);
+ if (!vga_is_gfx)
+ scr_memcpyw_to((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, c->vc_screenbuf_size);
return 0; /* Redrawing not needed */
}
@@ -474,8 +472,7 @@ static void vga_set_palette(struct vc_data *c, unsigned char *table)
static int vgacon_set_palette(struct vc_data *c, unsigned char *table)
{
#ifdef CAN_LOAD_PALETTE
-
- if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked)
+ if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked || !CON_IS_VISIBLE(c))
return -EINVAL;
vga_set_palette(c, table);
return 0;
@@ -637,10 +634,11 @@ static int vgacon_blank(struct vc_data *c, int blank)
vga_palette_blanked = 1;
return 0;
}
- scr_memsetw((void *)vga_vram_base, BLANK, vc_cons[0].d->vc_screenbuf_size);
+ vgacon_set_origin(c);
+ scr_memsetw((void *)vga_vram_base, BLANK, c->vc_screenbuf_size);
return 1;
case -1: /* Entering graphic mode */
- scr_memsetw((void *)vga_vram_base, BLANK, vc_cons[0].d->vc_screenbuf_size);
+ scr_memsetw((void *)vga_vram_base, BLANK, c->vc_screenbuf_size);
vga_is_gfx = 1;
return 1;
default: /* VESA blanking */
@@ -899,14 +897,24 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines)
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)
+ int vram_size = vga_vram_end - vga_vram_base;
+ int margin = c->vc_size_row * 4;
+ int ul, we, p, st;
+
+ if (vga_rolled_over > (c->vc_scr_end - vga_vram_base) + margin) {
+ ul = c->vc_scr_end - vga_vram_base;
+ we = vga_rolled_over + c->vc_size_row;
+ } else {
+ ul = 0;
+ we = vram_size;
+ }
+ p = (c->vc_visible_origin - vga_vram_base - ul + we) % we + lines * c->vc_size_row;
+ st = (c->vc_origin - vga_vram_base - ul + we) % we;
+ if (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;
+ if (p > st - margin)
+ p = st;
+ c->vc_visible_origin = vga_vram_base + (p + ul) % we;
}
vga_set_mem_top(c);
return 1;
@@ -919,6 +927,7 @@ static int vgacon_set_origin(struct vc_data *c)
return 0;
c->vc_origin = c->vc_visible_origin = vga_vram_base;
vga_set_mem_top(c);
+ vga_rolled_over = 0;
return 1;
}
@@ -935,9 +944,8 @@ static void vgacon_save_screen(struct vc_data *c)
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);
+ if (!vga_is_gfx)
+ 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)
@@ -962,6 +970,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
(u16 *)(oldo + delta),
c->vc_screenbuf_size - delta);
c->vc_origin = vga_vram_base;
+ vga_rolled_over = oldo - 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);
@@ -971,6 +980,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
(u16 *)oldo,
c->vc_screenbuf_size - delta);
c->vc_origin = vga_vram_end - c->vc_screenbuf_size;
+ vga_rolled_over = 0;
} else
c->vc_origin -= delta;
c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size;
diff --git a/drivers/video/vgafb.c b/drivers/video/vgafb.c
deleted file mode 100644
index c8fc4c9a0..000000000
--- a/drivers/video/vgafb.c
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
- * 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 927fbb46d..59d16e90b 100644
--- a/drivers/video/virgefb.c
+++ b/drivers/video/virgefb.c
@@ -33,10 +33,10 @@
#include <asm/pgtable.h>
#include <asm/amigahw.h>
-#include "s3blit.h"
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
+#include <video/s3blit.h>
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
#ifdef VIRGEFBDEBUG
@@ -147,11 +147,13 @@ static char virgefb_name[16] = "Cybervision/3D";
static unsigned int CyberKey = 0;
-static unsigned char Cyber_colour_table [256][4];
+static unsigned char Cyber_colour_table [256][3];
static unsigned long CyberMem;
static unsigned long CyberSize;
static volatile char *CyberRegs;
static volatile unsigned long CyberVGARegs; /* ++Andre: for CV64/3D, see macros at the beginning */
+static unsigned long CyberMem_phys;
+static unsigned long CyberRegs_phys;
/*
@@ -208,6 +210,13 @@ static struct fb_videomode virgefb_predefined[] __initdata = {
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
}
+ }, {
+ "1024x768-16", { /* Cybervision 16 bpp */
+ 1024, 768, 1024, 768, 0, 0, 16, 0,
+ {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
+ 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
+ }
}
};
@@ -323,7 +332,6 @@ static int Cyber_init(void)
Cyber_colour_table [i][0] = i;
Cyber_colour_table [i][1] = i;
Cyber_colour_table [i][2] = i;
- Cyber_colour_table [i][3] = 0;
}
/*
@@ -372,9 +380,9 @@ static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, virgefb_name);
- fix->smem_start = (char *)CyberMem;
+ fix->smem_start = (char*) CyberMem_phys;
fix->smem_len = CyberSize;
- fix->mmio_start = (char *)CyberRegs;
+ fix->mmio_start = (char*) CyberRegs_phys;
fix->mmio_len = 0x10000; /* TODO: verify this for the CV64/3D */
fix->type = FB_TYPE_PACKED_PIXELS;
@@ -382,7 +390,7 @@ static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
if (par->bpp == 8)
fix->visual = FB_VISUAL_PSEUDOCOLOR;
else
- fix->visual = FB_VISUAL_DIRECTCOLOR;
+ fix->visual = FB_VISUAL_TRUECOLOR;
fix->xpanstep = 0;
fix->ypanstep = 0;
@@ -445,7 +453,7 @@ static int Cyber_encode_var(struct fb_var_screeninfo *var,
if (par->bpp == 8) {
var->red.offset = 0;
- var->red.length = 8;
+ var->red.length = 6;
var->red.msb_right = 0;
var->blue = var->green = var->red;
} else {
@@ -511,14 +519,17 @@ static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
*/
vgawb_3d(0x3c8, (unsigned char) regno);
- Cyber_colour_table [regno][0] = red & 0xff;
- Cyber_colour_table [regno][1] = green & 0xff;
- Cyber_colour_table [regno][2] = blue & 0xff;
- Cyber_colour_table [regno][3] = transp;
+ red >>= 10;
+ green >>= 10;
+ blue >>= 10;
- vgawb_3d(0x3c9, ((red & 0xff) >> 2));
- vgawb_3d(0x3c9, ((green & 0xff) >> 2));
- vgawb_3d(0x3c9, ((blue & 0xff) >> 2));
+ Cyber_colour_table [regno][0] = red;
+ Cyber_colour_table [regno][1] = green;
+ Cyber_colour_table [regno][2] = blue;
+
+ vgawb_3d(0x3c9, red);
+ vgawb_3d(0x3c9, green);
+ vgawb_3d(0x3c9, blue);
return (0);
}
@@ -532,12 +543,17 @@ static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info)
{
+ int t;
+
if (regno >= 256)
return (1);
- *red = Cyber_colour_table [regno][0];
- *green = Cyber_colour_table [regno][1];
- *blue = Cyber_colour_table [regno][2];
- *transp = Cyber_colour_table [regno][3];
+ t = Cyber_colour_table [regno][0];
+ *red = (t<<10) | (t<<4) | (t>>2);
+ t = Cyber_colour_table [regno][1];
+ *green = (t<<10) | (t<<4) | (t>>2);
+ t = Cyber_colour_table [regno][2];
+ *blue = (t<<10) | (t<<4) | (t>>2);
+ *transp = 0;
return (0);
}
@@ -565,9 +581,9 @@ void Cyber_blank(int blank)
for (i = 0; i < 256; i++)
{
vgawb_3d(0x3c8, (unsigned char) i);
- vgawb_3d(0x3c9, Cyber_colour_table[i][0] >> 2);
- vgawb_3d(0x3c9, Cyber_colour_table[i][1] >> 2);
- vgawb_3d(0x3c9, Cyber_colour_table[i][2] >> 2);
+ vgawb_3d(0x3c9, Cyber_colour_table[i][0]);
+ vgawb_3d(0x3c9, Cyber_colour_table[i][1]);
+ vgawb_3d(0x3c9, Cyber_colour_table[i][2]);
}
}
}
@@ -752,11 +768,10 @@ static void do_install_cmap(int con, struct fb_info *info)
if (con != currcon)
return;
if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
- fbhw->setcolreg, info);
+ fb_set_cmap(&fb_display[con].cmap, 1, fbhw->setcolreg, info);
else
fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
- &fb_display[con].var, 1, fbhw->setcolreg, info);
+ 1, fbhw->setcolreg, info);
}
@@ -837,7 +852,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 = fix.smem_start;
+ display->screen_base = (char*) CyberMem;
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
@@ -861,7 +876,7 @@ static void virgefb_set_disp(int con, struct fb_info *info)
break;
#endif
default:
- display->dispsw = NULL;
+ display->dispsw = &fbcon_dummy;
break;
}
}
@@ -910,8 +925,7 @@ static int virgefb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
if (con == currcon) /* current console? */
- return(fb_get_cmap(cmap, &fb_display[con].var,
- kspc, fbhw->getcolreg, info));
+ return(fb_get_cmap(cmap, kspc, fbhw->getcolreg, info));
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
@@ -936,8 +950,7 @@ static int virgefb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return(err);
}
if (con == currcon) /* current console? */
- return(fb_set_cmap(cmap, &fb_display[con].var,
- kspc, fbhw->setcolreg, info));
+ return(fb_set_cmap(cmap, kspc, fbhw->setcolreg, info));
else
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return(0);
@@ -1029,7 +1042,8 @@ __initfunc(void virgefb_init(void))
* Ok we got the board running in Z2 space.
*/
- CyberMem = ZTWO_VADDR(board_addr);
+ CyberMem_phys = board_addr;
+ CyberMem = ZTWO_VADDR(CyberMem_phys);
printk("CV3D detected running in Z2 mode ... not yet supported!\n");
return;
}
@@ -1037,10 +1051,13 @@ __initfunc(void virgefb_init(void))
{
CyberVGARegs = kernel_map(board_addr +0x0c000000, 0x00010000,
KERNELMAP_NOCACHE_SER, NULL);
- CyberRegs = (char *)kernel_map(board_addr +0x05000000,
+
+ CyberRegs_phys = board_addr + 0x05000000;
+ CyberMem_phys = board_addr + 0x04800000;
+ CyberRegs = (char *)kernel_map(CyberRegs_phys,
0x00010000,
KERNELMAP_NOCACHE_SER, NULL);
- CyberMem = kernel_map(board_addr + 0x04800000, 0x00400000,
+ CyberMem = kernel_map(CyberMem_phys, 0x00400000,
KERNELMAP_NOCACHE_SER, NULL);
printk("CV3D detected running in Z3 mode\n");
}
@@ -1055,6 +1072,7 @@ __initfunc(void virgefb_init(void))
fb_info.switch_con = &Cyberfb_switch;
fb_info.updatevar = &Cyberfb_updatevar;
fb_info.blank = &Cyberfb_blank;
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
fbhw->init();
fbhw->decode_var(&virgefb_default, &par);
@@ -1080,8 +1098,8 @@ static int Cyberfb_switch(int con, struct fb_info *info)
{
/* Do we have to save the colormap? */
if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
- fbhw->getcolreg, info);
+ fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg,
+ info);
do_fb_set_var(&fb_display[con].var, 1);
currcon = con;
@@ -1143,9 +1161,9 @@ static void fbcon_virge8_bmove(struct display *p, int sy, int sx, int dy,
int dx, int height, int width)
{
sx *= 8; dx *= 8; width *= 8;
- Cyber3D_BitBLT((u_short)sx, (u_short)(sy*p->fontheight), (u_short)dx,
- (u_short)(dy*p->fontheight), (u_short)width,
- (u_short)(height*p->fontheight));
+ Cyber3D_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
+ (u_short)(dy*fontheight(p)), (u_short)width,
+ (u_short)(height*fontheight(p)));
}
static void fbcon_virge8_clear(struct vc_data *conp, struct display *p, int sy,
@@ -1155,8 +1173,8 @@ static void fbcon_virge8_clear(struct vc_data *conp, struct display *p, int sy,
sx *= 8; width *= 8;
bg = attr_bgcol_ec(p,conp);
- Cyber3D_RectFill((u_short)sx, (u_short)(sy*p->fontheight),
- (u_short)width, (u_short)(height*p->fontheight),
+ Cyber3D_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
+ (u_short)width, (u_short)(height*fontheight(p)),
(u_short)bg);
}