Commit 6bd20e27 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://fbdev.bkbits.net:8080/fbdev-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents d236fbb8 7a356301
...@@ -236,25 +236,25 @@ if [ "$CONFIG_FB" = "y" ]; then ...@@ -236,25 +236,25 @@ if [ "$CONFIG_FB" = "y" ]; then
if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_AMIGA" = "y" -o \ if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_AMIGA" = "y" -o \
"$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
"$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_RETINAZ3" = "y" -o \ "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_RETINAZ3" = "y" -o \
"$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_TX3912" = "y" -o \ "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_BWTWO" = "y" -o "$CONFIG_FB_CLGEN" = "y" ]; then "$CONFIG_FB_BWTWO" = "y" ]; then
define_tristate CONFIG_FBCON_MFB y define_tristate CONFIG_FBCON_MFB y
else else
if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_AMIGA" = "m" -o \ if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_AMIGA" = "m" -o \
"$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
"$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_RETINAZ3" = "m" -o \ "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_RETINAZ3" = "m" -o \
"$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_TX3912" = "m" -o \ "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_BWTWO" = "m" -o "$CONFIG_FB_CLGEN" = "m" ]; then "$CONFIG_FB_BWTWO" = "m" ]; then
define_tristate CONFIG_FBCON_MFB m define_tristate CONFIG_FBCON_MFB m
fi fi
fi fi
if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
"$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_TX3912" = "y" ]; then "$CONFIG_FB_SA1100" = "y" ]; then
define_tristate CONFIG_FBCON_CFB2 y define_tristate CONFIG_FBCON_CFB2 y
define_tristate CONFIG_FBCON_CFB4 y define_tristate CONFIG_FBCON_CFB4 y
else else
if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_MAC" = "m" -o \ if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_MAC" = "m" -o \
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_TX3912" = "m" ]; then "$CONFIG_FB_SA1100" = "m" ]; then
define_tristate CONFIG_FBCON_CFB2 m define_tristate CONFIG_FBCON_CFB2 m
define_tristate CONFIG_FBCON_CFB4 m define_tristate CONFIG_FBCON_CFB4 m
fi fi
...@@ -262,7 +262,7 @@ if [ "$CONFIG_FB" = "y" ]; then ...@@ -262,7 +262,7 @@ if [ "$CONFIG_FB" = "y" ]; then
if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_ATARI" = "y" -o \ if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_ATARI" = "y" -o \
"$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
"$CONFIG_FB_OF" = "y" -o "$CONFIG_FB_TGA" = "y" -o \ "$CONFIG_FB_OF" = "y" -o "$CONFIG_FB_TGA" = "y" -o \
"$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_PM3" = "y" -o \ "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_TCX" = "y" -o "$CONFIG_FB_CGTHREE" = "y" -o \ "$CONFIG_FB_TCX" = "y" -o "$CONFIG_FB_CGTHREE" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_TRIDENT" = "y" -o \ "$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_TRIDENT" = "y" -o \
...@@ -273,15 +273,13 @@ if [ "$CONFIG_FB" = "y" ]; then ...@@ -273,15 +273,13 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_P9100" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \ "$CONFIG_FB_P9100" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
"$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \ "$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \
"$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \ "$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \
"$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_SIS" = "y" -o \ "$CONFIG_FB_SA1100" = "y" ]; then
"$CONFIG_FB_PMAG_BA" = "y" -o "$CONFIG_FB_PMAGB_B" = "y" -o \
"$CONFIG_FB_MAXINE" = "y" -o "$CONFIG_FB_TX3912" = "y" ]; then
define_tristate CONFIG_FBCON_CFB8 y define_tristate CONFIG_FBCON_CFB8 y
else else
if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \ if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
"$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_MAC" = "m" -o \ "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_MAC" = "m" -o \
"$CONFIG_FB_OF" = "m" -o "$CONFIG_FB_TGA" = "m" -o \ "$CONFIG_FB_OF" = "m" -o "$CONFIG_FB_TGA" = "m" -o \
"$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_PM3" = "m" -o \ "$CONFIG_FB_SIS" = "m" -o "$CONFIG_FB_PM3" = "m" -o \
"$CONFIG_FB_TCX" = "m" -o "$CONFIG_FB_CGTHREE" = "m" -o \ "$CONFIG_FB_TCX" = "m" -o "$CONFIG_FB_CGTHREE" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_TRIDENT" = "m" -o \ "$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_TRIDENT" = "m" -o \
...@@ -290,16 +288,14 @@ if [ "$CONFIG_FB" = "y" ]; then ...@@ -290,16 +288,14 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \ "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
"$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" -o \ "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
"$CONFIG_FB_P9100" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \ "$CONFIG_FB_P9100" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_TX3912" = "m" -o \ "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \ "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \
"$CONFIG_FB_PMAG_BA" = "m" -o "$CONFIG_FB_PMAGB_B" = "m" -o \ "$CONFIG_FB_SA1100" = "m" ]; then
"$CONFIG_FB_MAXINE" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_SIS" = "m" ]; then
define_tristate CONFIG_FBCON_CFB8 m define_tristate CONFIG_FBCON_CFB8 m
fi fi
fi fi
if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \ if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \
"$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" -o \ "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_PVR2" = "y" -o \
"$CONFIG_FB_TRIDENT" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \ "$CONFIG_FB_TRIDENT" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \
"$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \ "$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
...@@ -309,12 +305,11 @@ if [ "$CONFIG_FB" = "y" ]; then ...@@ -309,12 +305,11 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \ "$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \
"$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \ "$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
"$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_PM3" = "y" -o \ "$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \ "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" ]; then
"$CONFIG_FB_PVR2" = "y" ]; then
define_tristate CONFIG_FBCON_CFB16 y define_tristate CONFIG_FBCON_CFB16 y
else else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \ if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
"$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_NEOMAGIC" = "m" -o \ "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_PVR2" = "m" -o \
"$CONFIG_FB_TRIDENT" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \ "$CONFIG_FB_TRIDENT" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \
"$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_PM3" = "m" -o \ "$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_PM3" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \ "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
...@@ -324,8 +319,7 @@ if [ "$CONFIG_FB" = "y" ]; then ...@@ -324,8 +319,7 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_SGIVW" = "m" -o \ "$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_SGIVW" = "m" -o \
"$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \ "$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_SIS" = "m" -o \ "$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \ "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" ]; then
"$CONFIG_FB_PVR2" = "m" ]; then
define_tristate CONFIG_FBCON_CFB16 m define_tristate CONFIG_FBCON_CFB16 m
fi fi
fi fi
...@@ -374,7 +368,9 @@ if [ "$CONFIG_FB" = "y" ]; then ...@@ -374,7 +368,9 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_HP300" = "y" -o "$CONFIG_FB_Q40" = "y" -o \ "$CONFIG_FB_HP300" = "y" -o "$CONFIG_FB_Q40" = "y" -o \
"$CONFIG_FB_ANAKIN" = "y" -o "$CONFIG_FB_G364" = "y" -o \ "$CONFIG_FB_ANAKIN" = "y" -o "$CONFIG_FB_G364" = "y" -o \
"$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \ "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_CLPS711X" = "y" -o \
"$CONFIG_FB_3DFX" = "y" ]; then "$CONFIG_FB_PMAG_BA" = "y" -o "$CONFIG_FB_PMAGB_B" = "y" -o \
"$CONFIG_FB_3DFX" = "y" -o "$CONFIG_FB_TX3912" = "y" -o \
"$CONFIG_FB_MAXINE" = "y" -o "$CONFIG_FB_APOLLO" = "y" ]; then
define_tristate CONFIG_FBCON_ACCEL y define_tristate CONFIG_FBCON_ACCEL y
else else
if [ "$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_HIT" = "m" -o \ if [ "$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_HIT" = "m" -o \
......
...@@ -7,13 +7,13 @@ mod-subdirs := matrox ...@@ -7,13 +7,13 @@ mod-subdirs := matrox
# All of the (potential) objects that export symbols. # All of the (potential) objects that export symbols.
# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
export-objs := fbmem.o fbcmap.o fbcon.o fbmon.o modedb.o \ export-objs := fbmem.o fbcmap.o fbcon.o fbmon.o modedb.o \
fbcon-afb.o fbcon-ilbm.o fbcon-accel.o \ fbcon-afb.o fbcon-ilbm.o fbcon-accel.o \
fbcon-vga.o fbcon-iplan2p2.o fbcon-iplan2p4.o \ fbcon-vga.o fbcon-iplan2p2.o fbcon-iplan2p4.o \
fbcon-iplan2p8.o fbcon-vga-planes.o fbcon-cfb16.o \ fbcon-iplan2p8.o fbcon-vga-planes.o fbcon-cfb16.o \
fbcon-cfb2.o fbcon-cfb24.o fbcon-cfb32.o fbcon-cfb4.o \ fbcon-cfb2.o fbcon-cfb24.o fbcon-cfb32.o fbcon-cfb4.o \
fbcon-cfb8.o fbcon-mac.o fbcon-mfb.o \ fbcon-cfb8.o fbcon-mac.o fbcon-mfb.o \
cyber2000fb.o sa1100fb.o fbcon-hga.o fbgen.o cyber2000fb.o sa1100fb.o fbcon-hga.o fbgen.o
# Each configuration option enables a list of files. # Each configuration option enables a list of files.
...@@ -43,18 +43,18 @@ obj-$(CONFIG_FB_ACORN) += acornfb.o ...@@ -43,18 +43,18 @@ obj-$(CONFIG_FB_ACORN) += acornfb.o
obj-$(CONFIG_FB_AMIGA) += amifb.o obj-$(CONFIG_FB_AMIGA) += amifb.o
obj-$(CONFIG_FB_PM2) += pm2fb.o obj-$(CONFIG_FB_PM2) += pm2fb.o
obj-$(CONFIG_FB_PM3) += pm3fb.o obj-$(CONFIG_FB_PM3) += pm3fb.o
obj-$(CONFIG_FB_APOLLO) += dnfb.o obj-$(CONFIG_FB_APOLLO) += dnfb.o cfbfillrect.o cfbimgblt.o
obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_ATARI) += atafb.o obj-$(CONFIG_FB_ATARI) += atafb.o
obj-$(CONFIG_FB_ATY128) += aty128fb.o obj-$(CONFIG_FB_ATY128) += aty128fb.o
obj-$(CONFIG_FB_RADEON) += radeonfb.o obj-$(CONFIG_FB_RADEON) += radeonfb.o
obj-$(CONFIG_FB_NEOMAGIC) += neofb.o obj-$(CONFIG_FB_NEOMAGIC) += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_IGA) += igafb.o obj-$(CONFIG_FB_IGA) += igafb.o
obj-$(CONFIG_FB_CONTROL) += controlfb.o obj-$(CONFIG_FB_CONTROL) += controlfb.o
obj-$(CONFIG_FB_PLATINUM) += platinumfb.o obj-$(CONFIG_FB_PLATINUM) += platinumfb.o
obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o
obj-$(CONFIG_FB_CT65550) += chipsfb.o obj-$(CONFIG_FB_CT65550) += chipsfb.o
obj-$(CONFIG_FB_ANAKIN) += anakinfb.o obj-$(CONFIG_FB_ANAKIN) += anakinfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_CYBER) += cyberfb.o obj-$(CONFIG_FB_CYBER) += cyberfb.o
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
...@@ -83,10 +83,10 @@ obj-$(CONFIG_FB_CGFOURTEEN) += cgfourteenfb.o sbusfb.o ...@@ -83,10 +83,10 @@ obj-$(CONFIG_FB_CGFOURTEEN) += cgfourteenfb.o sbusfb.o
obj-$(CONFIG_FB_P9100) += p9100fb.o sbusfb.o obj-$(CONFIG_FB_P9100) += p9100fb.o sbusfb.o
obj-$(CONFIG_FB_LEO) += leofb.o sbusfb.o obj-$(CONFIG_FB_LEO) += leofb.o sbusfb.o
obj-$(CONFIG_FB_STI) += stifb.o sticore.o obj-$(CONFIG_FB_STI) += stifb.o sticore.o
obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_MAXINE) += maxinefb.o obj-$(CONFIG_FB_MAXINE) += maxinefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_TX3912) += tx3912fb.o obj-$(CONFIG_FB_TX3912) += tx3912fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_MATROX) += matrox/ obj-$(CONFIG_FB_MATROX) += matrox/
obj-$(CONFIG_FB_RIVA) += riva/ obj-$(CONFIG_FB_RIVA) += riva/
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include <asm/io.h> #include <asm/io.h>
#include <video/fbcon.h> #include <video/fbcon.h>
#include <video/fbcon-cfb16.h>
static u32 colreg[16]; static u32 colreg[16];
static struct fb_info fb_info; static struct fb_info fb_info;
...@@ -84,7 +83,8 @@ anakinfb_init(void) ...@@ -84,7 +83,8 @@ anakinfb_init(void)
memset(&display, 0, sizeof(struct display)); memset(&display, 0, sizeof(struct display));
strcpy(fb_info.modename, anakinfb_fix.id); strcpy(fb_info.modename, anakinfb_fix.id);
fb_info.node = fb_info.currcon = -1; fb_info.node = NODEV;
fb_info.currcon = -1;
fb_info.flags = FBINFO_FLAG_DEFAULT; fb_info.flags = FBINFO_FLAG_DEFAULT;
fb_info.fbops = &anakinfb_ops; fb_info.fbops = &anakinfb_ops;
fb_info.var = anakinfb_var; fb_info.var = anakinfb_var;
......
...@@ -1659,7 +1659,7 @@ aty128_init(struct fb_info_aty128 *info, const char *name) ...@@ -1659,7 +1659,7 @@ aty128_init(struct fb_info_aty128 *info, const char *name)
{ {
struct fb_var_screeninfo var; struct fb_var_screeninfo var;
u32 dac; u32 dac;
int j, k; int j, k, size;
u8 chip_rev; u8 chip_rev;
const struct aty128_chip_info *aci = &aty128_pci_probe_list[0]; const struct aty128_chip_info *aci = &aty128_pci_probe_list[0];
char *video_card = "Rage128"; char *video_card = "Rage128";
...@@ -1772,6 +1772,9 @@ aty128_init(struct fb_info_aty128 *info, const char *name) ...@@ -1772,6 +1772,9 @@ aty128_init(struct fb_info_aty128 *info, const char *name)
board_list = aty128_board_list_add(board_list, info); board_list = aty128_board_list_add(board_list, info);
size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 32;
fb_alloc_cmap(info->fb_info.cmap, size, 0);
if (register_framebuffer(&info->fb_info) < 0) if (register_framebuffer(&info->fb_info) < 0)
return 0; return 0;
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area)
{ {
int x2, y2, lineincr, shift, shift_right, shift_left, old_dx, old_dy; int x2, y2, lineincr, shift, shift_right, shift_left, old_dx, old_dy;
int n, j, linesize = p->fix.line_length, bpl = sizeof(unsigned long); int j, linesize = p->fix.line_length, bpl = sizeof(unsigned long);
unsigned long start_index, end_index, start_mask, end_mask, last; unsigned long start_index, end_index, start_mask, end_mask, last;
unsigned long *dst = NULL, *src = NULL; unsigned long *dst = NULL, *src = NULL;
char *src1, *dst1; char *src1, *dst1;
...@@ -102,7 +102,7 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area) ...@@ -102,7 +102,7 @@ void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area)
end_mask = -1 << ((bpl - end_index) << 3); end_mask = -1 << ((bpl - end_index) << 3);
n -= end_index; n -= end_index;
} }
n = n / bpl; n /= bpl;
if (n <= 0) { if (n <= 0) {
if (start_mask) { if (start_mask) {
......
...@@ -107,12 +107,11 @@ void cfb_imageblit(struct fb_info *p, struct fb_image *image) ...@@ -107,12 +107,11 @@ void cfb_imageblit(struct fb_info *p, struct fb_image *image)
dst++; dst++;
} }
if (n) { if (n) {
end_mask = 0;
for (j = n; j > 0; j--) { for (j = n; j > 0; j--) {
end_mask = 0;
if (test_bit(l, src)) if (test_bit(l, src))
end_mask |= (tmp >> (p->var.bits_per_pixel*(k-1))); end_mask |= (tmp >> (p->var.bits_per_pixel*(j-1)));
l--; l--;
if (l < 0) { l = 7; src++; } if (l < 0) { l = 7; src++; }
} }
...@@ -125,9 +124,6 @@ void cfb_imageblit(struct fb_info *p, struct fb_image *image) ...@@ -125,9 +124,6 @@ void cfb_imageblit(struct fb_info *p, struct fb_image *image)
} else { } else {
/* Draw the penguin */ /* Draw the penguin */
n = ((image->width * p->var.bits_per_pixel) >> 3); n = ((image->width * p->var.bits_per_pixel) >> 3);
//shift = ((unsigned long) dst1 & (bpl -1));
end_mask = 0; end_mask = 0;
// n = n/bpl;
} }
} }
...@@ -203,6 +203,9 @@ static struct fb_ops clps7111fb_ops = { ...@@ -203,6 +203,9 @@ static struct fb_ops clps7111fb_ops = {
fb_get_cmap: gen_get_cmap, fb_get_cmap: gen_get_cmap,
fb_setcolreg: clps7111fb_setcolreg, fb_setcolreg: clps7111fb_setcolreg,
fb_blank: clps7111fb_blank, fb_blank: clps7111fb_blank,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
}; };
static int static int
......
...@@ -1729,8 +1729,9 @@ static int cyberpro_pci_resume(struct pci_dev *dev) ...@@ -1729,8 +1729,9 @@ static int cyberpro_pci_resume(struct pci_dev *dev)
} }
static struct pci_device_id cyberpro_pci_table[] __devinitdata = { static struct pci_device_id cyberpro_pci_table[] __devinitdata = {
{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682, // Not yet
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_IGA_1682 }, // { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
// PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_IGA_1682 },
{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000, { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2000 }, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2000 },
{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010, { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010,
......
#ifndef _DN_ACCEL_H_
#define _DN_ACCEL_H_
#include <linux/fb.h>
void dn_bitblt(struct display *p,int x_src,int y_src, int x_dest, int y_dest,
int x_count, int y_count);
#endif
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <asm/apollohw.h>
#include <linux/fb.h>
#include <linux/module.h>
#include <video/fbcon.h>
#include <video/fbcon-mfb.h>
#include "dn_accel.h"
/* apollo video HW definitions */
/*
* Control Registers. IOBASE + $x
*
* Note: these are the Memory/IO BASE definitions for a mono card set to the
* alternate address
*
* Control 3A and 3B serve identical functions except that 3A
* deals with control 1 and 3b deals with Color LUT reg.
*/
#define AP_IOBASE 0x3d0 /* Base address of 1 plane board. */
#define AP_STATUS isaIO2mem(AP_IOBASE+0) /* Status register. Read */
#define AP_WRITE_ENABLE isaIO2mem(AP_IOBASE+0) /* Write Enable Register Write */
#define AP_DEVICE_ID isaIO2mem(AP_IOBASE+1) /* Device ID Register. Read */
#define AP_ROP_1 isaIO2mem(AP_IOBASE+2) /* Raster Operation reg. Write Word */
#define AP_DIAG_MEM_REQ isaIO2mem(AP_IOBASE+4) /* Diagnostic Memory Request. Write Word */
#define AP_CONTROL_0 isaIO2mem(AP_IOBASE+8) /* Control Register 0. Read/Write */
#define AP_CONTROL_1 isaIO2mem(AP_IOBASE+0xa) /* Control Register 1. Read/Write */
#define AP_CONTROL_2 isaIO2mem(AP_IOBASE+0xc) /* Control Register 2. Read/Write */
#define AP_CONTROL_3A isaIO2mem(AP_IOBASE+0xe) /* Control Register 3a. Read/Write */
#define AP_LUT_RED isaIO2mem(AP_IOBASE+9) /* Red Lookup Table register. Write */
#define AP_LUT_GREEN isaIO2mem(AP_IOBASE+0xb) /* Green Lookup Table register. Write */
#define AP_LUT_BLUE isaIO2mem(AP_IOBASE+0xd) /* Blue Lookup Table register. Write */
#define AP_AD_CHANNEL isaIO2mem(AP_IOBASE+0xf) /* A/D Result/Channel register. Read/Write */
#define FRAME_BUFFER_START 0x0A0000
#define FRAME_BUFFER_LEN 0x20000
/* CREG 0 */
#define VECTOR_MODE 0x40 /* 010x.xxxx */
#define DBLT_MODE 0x80 /* 100x.xxxx */
#define NORMAL_MODE 0xE0 /* 111x.xxxx */
#define SHIFT_BITS 0x1F /* xxx1.1111 */
/* other bits are Shift value */
/* CREG 1 */
#define AD_BLT 0x80 /* 1xxx.xxxx */
#define ROP_EN 0x10 /* xxx1.xxxx */
#define DST_EQ_SRC 0x00 /* xxx0.xxxx */
#define nRESET_SYNC 0x08 /* xxxx.1xxx */
#define SYNC_ENAB 0x02 /* xxxx.xx1x */
#define BLANK_DISP 0x00 /* xxxx.xxx0 */
#define ENAB_DISP 0x01 /* xxxx.xxx1 */
#define NORM_CREG1 (nRESET_SYNC | SYNC_ENAB | ENAB_DISP) /* no reset sync */
/* CREG 2B */
/*
* Following 3 defines are common to 1, 4 and 8 plane.
*/
#define S_DATA_1s 0x00 /* 00xx.xxxx */ /* set source to all 1's -- vector drawing */
#define S_DATA_PIX 0x40 /* 01xx.xxxx */ /* takes source from ls-bits and replicates over 16 bits */
#define S_DATA_PLN 0xC0 /* 11xx.xxxx */ /* normal, each data access =16-bits in
one plane of image mem */
/* CREG 3A/CREG 3B */
# define RESET_CREG 0x80 /* 1000.0000 */
/* ROP REG - all one nibble */
/* ********* NOTE : this is used r0,r1,r2,r3 *********** */
#define ROP(r2,r3,r0,r1) ( (U_SHORT)((r0)|((r1)<<4)|((r2)<<8)|((r3)<<12)) )
#define DEST_ZERO 0x0
#define SRC_AND_DEST 0x1
#define SRC_AND_nDEST 0x2
#define SRC 0x3
#define nSRC_AND_DEST 0x4
#define DEST 0x5
#define SRC_XOR_DEST 0x6
#define SRC_OR_DEST 0x7
#define SRC_NOR_DEST 0x8
#define SRC_XNOR_DEST 0x9
#define nDEST 0xA
#define SRC_OR_nDEST 0xB
#define nSRC 0xC
#define nSRC_OR_DEST 0xD
#define SRC_NAND_DEST 0xE
#define DEST_ONE 0xF
#define SWAP(A) ((A>>8) | ((A&0xff) <<8))
/* frame buffer operations */
static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int dn_fb_set_var(struct fb_var_screeninfo *var, int isactive,
struct fb_info *info);
static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
struct fb_info *info);
static int dn_fb_blank(int blank,struct fb_info *info);
static int dnfbcon_switch(int con,struct fb_info *info);
static int dnfbcon_updatevar(int con,struct fb_info *info);
static void dn_fb_set_disp(int con,struct fb_info *info);
static struct display disp[MAX_NR_CONSOLES];
static struct fb_info fb_info;
static struct fb_ops dn_fb_ops = {
owner: THIS_MODULE,
fb_get_fix: dn_fb_get_fix,
fb_get_var: dn_fb_get_var,
fb_set_var: dn_fb_set_var,
fb_get_cmap: dn_fb_get_cmap,
fb_set_cmap: gen_set_cmap,
fb_blank: dn_fb_blank,
};
#define NUM_TOTAL_MODES 1
struct fb_var_screeninfo dn_fb_predefined[] = {
{ 0, },
};
static char dn_fb_name[]="Apollo ";
/* accel stuff */
#define USE_DN_ACCEL
static struct display_switch dispsw_apollofb;
static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info) {
strcpy(fix->id,"Apollo Color4");
fix->smem_start=(FRAME_BUFFER_START+IO_BASE);
fix->smem_len=FRAME_BUFFER_LEN;
fix->type=FB_TYPE_PACKED_PIXELS;
fix->type_aux=0;
fix->visual=FB_VISUAL_MONO10;
fix->xpanstep=0;
fix->ypanstep=0;
fix->ywrapstep=0;
fix->line_length=128;
return 0;
}
static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info) {
var->xres=1024;
var->yres=800;
var->xres_virtual=1024;
var->yres_virtual=1024;
var->xoffset=0;
var->yoffset=0;
var->bits_per_pixel=1;
var->grayscale=0;
var->nonstd=0;
var->activate=0;
var->height=-1;
var->width=-1;
var->pixclock=0;
var->left_margin=0;
var->right_margin=0;
var->hsync_len=0;
var->vsync_len=0;
var->sync=0;
var->vmode=FB_VMODE_NONINTERLACED;
return 0;
}
static int dn_fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info) {
printk("fb_set_var\n");
if(var->xres!=1024)
return -EINVAL;
if(var->yres!=800)
return -EINVAL;
if(var->xres_virtual!=1024)
return -EINVAL;
if(var->yres_virtual!=1024)
return -EINVAL;
if(var->xoffset!=0)
return -EINVAL;
if(var->yoffset!=0)
return -EINVAL;
if(var->bits_per_pixel!=1)
return -EINVAL;
if(var->grayscale!=0)
return -EINVAL;
if(var->nonstd!=0)
return -EINVAL;
if(var->activate!=0)
return -EINVAL;
if(var->pixclock!=0)
return -EINVAL;
if(var->left_margin!=0)
return -EINVAL;
if(var->right_margin!=0)
return -EINVAL;
if(var->hsync_len!=0)
return -EINVAL;
if(var->vsync_len!=0)
return -EINVAL;
if(var->sync!=0)
return -EINVAL;
if(var->vmode!=FB_VMODE_NONINTERLACED)
return -EINVAL;
return 0;
}
static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
struct fb_info *info) {
printk("get cmap not supported\n");
return -EINVAL;
}
static void dn_fb_set_disp(int con, struct fb_info *info) {
struct fb_fix_screeninfo fix;
struct display *display;
dn_fb_get_fix(&fix,con, info);
if (con>=0)
display=&fb_display[con];
else
display=&disp[0];
if(con==-1)
con=0;
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
display->ypanstep = fix.ypanstep;
display->ywrapstep = fix.ywrapstep;
display->can_soft_blank = 1;
display->inverse = 0;
display->line_length = fix.line_length;
display->scrollmode = SCROLL_YREDRAW;
#ifdef FBCON_HAS_MFB
display->dispsw = &fbcon_mfb;
#else
display->dispsw=&fbcon_dummy;
#endif
}
unsigned long dnfb_init(unsigned long mem_start) {
int err;
printk("dn_fb_init\n");
fb_info.changevar=NULL;
strcpy(&fb_info.modename[0],dn_fb_name);
fb_info.fontname[0]=0;
fb_info.disp=disp;
fb_info.switch_con=&dnfbcon_switch;
fb_info.updatevar=&dnfbcon_updatevar;
fb_info.node = NODEV;
fb_info.fbops = &dn_fb_ops;
fb_info.screen_base = (u_char *)fix.smem_start;
printk("screenbase: %lx\n",fix.smem_start);
fb_info.currcon = -1;
fb_info.flags = FBINFO_FLAG_DEFAULT;
dn_fb_get_var(&disp[0].var,0, &fb_info);
dn_fb_set_disp(-1, &fb_info);
printk("dn_fb_init: register\n");
err=register_framebuffer(&fb_info);
if(err < 0) {
panic("unable to register apollo frame buffer\n");
}
/* now we have registered we can safely setup the hardware */
outb(RESET_CREG, AP_CONTROL_3A);
outb(NORMAL_MODE, AP_CONTROL_0);
outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1);
outb(S_DATA_PLN, AP_CONTROL_2);
outw(SWAP(0x3), AP_ROP_1);
printk("apollo frame buffer alive and kicking !\n");
return mem_start;
}
static int dnfbcon_switch(int con, struct fb_info *info) {
info->currcon = con;
return 0;
}
static int dnfbcon_updatevar(int con, struct fb_info *info) {
return 0;
}
static int dn_fb_blank(int blank, struct fb_info *info)
{
if (blank)
outb(0x0, AP_CONTROL_3A);
else
outb(0x1, AP_CONTROL_3A);
return 0;
}
void dn_bitblt(struct display *p,int x_src,int y_src, int x_dest, int y_dest,
int x_count, int y_count) {
int incr,y_delta,pre_read=0,x_end,x_word_count;
ushort *src,dummy;
uint start_mask,end_mask,dest;
short i,j;
incr=(y_dest<=y_src) ? 1 : -1 ;
src=(ushort *)(p->fb_info.screen_base+ y_src*p->next_line+(x_src >> 4));
dest=y_dest*(p->next_line >> 1)+(x_dest >> 4);
if(incr>0) {
y_delta=(p->next_line*8)-x_src-x_count;
x_end=x_dest+x_count-1;
x_word_count=(x_end>>4) - (x_dest >> 4) + 1;
start_mask=0xffff0000 >> (x_dest & 0xf);
end_mask=0x7ffff >> (x_end & 0xf);
outb((((x_dest & 0xf) - (x_src &0xf)) % 16)|(0x4 << 5),AP_CONTROL_0);
if((x_dest & 0xf) < (x_src & 0xf))
pre_read=1;
}
else {
y_delta=-((p->next_line*8)-x_src-x_count);
x_end=x_dest-x_count+1;
x_word_count=(x_dest>>4) - (x_end >> 4) + 1;
start_mask=0x7ffff >> (x_dest & 0xf);
end_mask=0xffff0000 >> (x_end & 0xf);
outb(((-((x_src & 0xf) - (x_dest &0xf))) % 16)|(0x4 << 5),AP_CONTROL_0);
if((x_dest & 0xf) > (x_src & 0xf))
pre_read=1;
}
for(i=0;i<y_count;i++) {
if(pre_read) {
dummy=*src;
src+=incr;
}
if(x_word_count) {
outb(start_mask,AP_WRITE_ENABLE);
*src=dest;
src+=incr;
dest+=incr;
outb(0,AP_WRITE_ENABLE);
for(j=1;j<(x_word_count-1);j++) {
*src=dest;
src+=incr;
dest+=incr;
}
outb(start_mask,AP_WRITE_ENABLE);
*src=dest;
dest+=incr;
src+=incr;
}
else {
outb(start_mask | end_mask, AP_WRITE_ENABLE);
*src=dest;
dest+=incr;
src+=incr;
}
src+=(y_delta/16);
dest+=(y_delta/16);
}
outb(NORMAL_MODE,AP_CONTROL_0);
}
static void bmove_apollofb(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
int fontheight,fontwidth;
fontheight=fontheight(p);
fontwidth=fontwidth(p);
#ifdef USE_DN_ACCEL
dn_bitblt(p,sx,sy*fontheight,dx,dy*fontheight,width*fontwidth,
height*fontheight);
#else
u_char *src, *dest;
u_int rows;
if (sx == 0 && dx == 0 && width == p->next_line) {
src = p->fb_info.screen_base+sy*fontheight*width;
dest = p->fb_info.screen_base+dy*fontheight*width;
mymemmove(dest, src, height*fontheight*width);
} else if (dy <= sy) {
src = p->fb_info.screen_base+sy*fontheight*p->next_line+sx;
dest = p->fb_info.screen_base+dy*fontheight*p->next_line+dx;
for (rows = height*fontheight; rows--;) {
mymemmove(dest, src, width);
src += p->next_line;
dest += p->next_line;
}
} else {
src = p->fb_info.screen_base+((sy+height)*fontheight-1)*p->next_line+sx;
dest = p->fb_info.screen_base+((dy+height)*fontheight-1)*p->next_line+dx;
for (rows = height*fontheight; rows--;) {
mymemmove(dest, src, width);
src -= p->next_line;
dest -= p->next_line;
}
}
#endif
}
static void clear_apollofb(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width)
{
fbcon_mfb_clear(conp,p,sy,sx,height,width);
}
static void putc_apollofb(struct vc_data *conp, struct display *p, int c, int yy,
int xx)
{
fbcon_mfb_putc(conp,p,c,yy,xx);
}
static void putcs_apollofb(struct vc_data *conp, struct display *p, const unsigned short *s,
int count, int yy, int xx)
{
fbcon_mfb_putcs(conp,p,s,count,yy,xx);
}
static void rev_char_apollofb(struct display *p, int xx, int yy)
{
fbcon_mfb_revc(p,xx,yy);
}
static struct display_switch dispsw_apollofb = {
setup: fbcon_mfb_setup,
bmove: bmove_apollofb,
clear: clear_apollofb,
putc: putc_apollofb,
putcs: putcs_apollofb,
revc: rev_char_apollofb,
fontwidthmask: FONTWIDTH(8)
};
MODULE_LICENSE("GPL");
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <asm/apollohw.h>
#include <linux/fb.h>
#include <linux/module.h>
#include "dn_accel.h"
#include "fbcon.h"
#include "fbcon-mfb.h"
/* apollo video HW definitions */
/*
* Control Registers. IOBASE + $x
*
* Note: these are the Memory/IO BASE definitions for a mono card set to the
* alternate address
*
* Control 3A and 3B serve identical functions except that 3A
* deals with control 1 and 3b deals with Color LUT reg.
*/
#define AP_IOBASE 0x3d0 /* Base address of 1 plane board. */
#define AP_STATUS isaIO2mem(AP_IOBASE+0) /* Status register. Read */
#define AP_WRITE_ENABLE isaIO2mem(AP_IOBASE+0) /* Write Enable Register Write */
#define AP_DEVICE_ID isaIO2mem(AP_IOBASE+1) /* Device ID Register. Read */
#define AP_ROP_0 isaIO2mem(AP_IOBASE+2) /* Raster Operation reg. Write Word */
#define AP_ROP_1 isaIO2mem(AP_IOBASE+4) /* Raster Operation reg. Write Word */
#define AP_DIAG_MEM_REQ isaIO2mem(AP_IOBASE+6) /* Diagnostic Memory Request. Write Word */
#define AP_CONTROL_0 isaIO2mem(AP_IOBASE+8) /* Control Register 0. Read/Write */
#define AP_LUT_DATA isaIO2mem(AP_IOBASE+9) /* Control Register 0. Read/Write */
#define AP_CONTROL_1 isaIO2mem(AP_IOBASE+0xa) /* Control Register 1. Read/Write */
#define AP_LUT_CONTROL isaIO2mem(AP_IOBASE+0xb) /* Control Register 1. Read/Write */
#define AP_CONTROL_2A isaIO2mem(AP_IOBASE+0xc) /* Control Register 2. Read/Write */
#define AP_CONTROL_2B isaIO2mem(AP_IOBASE+0xd) /* Control Register 2. Read/Write */
#define AP_CONTROL_3A isaIO2mem(AP_IOBASE+0xe) /* Control Register 3a. Read/Write */
#define AP_CONTROL_3B isaIO2mem(AP_IOBASE+0xf) /* Control Register 3a. Read/Write */
#define FRAME_BUFFER_START 0x0A0000
#define FRAME_BUFFER_LEN 0x20000
/* CREG 0 */
#define VECTOR_MODE 0x40 /* 010x.xxxx */
#define DBLT_MODE 0x80 /* 100x.xxxx */
#define NORMAL_MODE 0xE0 /* 111x.xxxx */
#define SHIFT_BITS 0x1F /* xxx1.1111 */
/* other bits are Shift value */
/* CREG 1 */
#define AD_BLT 0x80 /* 1xxx.xxxx */
#define ROP_EN 0x10 /* xxx1.xxxx */
#define DST_EQ_SRC 0x00 /* xxx0.xxxx */
#define nRESET_SYNC 0x08 /* xxxx.1xxx */
#define SYNC_ENAB 0x02 /* xxxx.xx1x */
#define BLANK_DISP 0x00 /* xxxx.xxx0 */
#define ENAB_DISP 0x01 /* xxxx.xxx1 */
#define NORM_CREG1 (nRESET_SYNC | SYNC_ENAB | ENAB_DISP) /* no reset sync */
/* CREG 2B */
/*
* Following 3 defines are common to 1, 4 and 8 plane.
*/
#define S_DATA_1s 0x00 /* 00xx.xxxx */ /* set source to all 1's -- vector drawing */
#define S_DATA_PIX 0x40 /* 01xx.xxxx */ /* takes source from ls-bits and replicates over 16 bits */
#define S_DATA_PLN 0xC0 /* 11xx.xxxx */ /* normal, each data access =16-bits in
one plane of image mem */
/* CREG 3A/CREG 3B */
# define RESET_CREG 0x80 /* 1000.0000 */
/* ROP REG - all one nibble */
/* ********* NOTE : this is used r0,r1,r2,r3 *********** */
#define ROP(r2,r3,r0,r1) ( (U_SHORT)((r0)|((r1)<<4)|((r2)<<8)|((r3)<<12)) )
#define DEST_ZERO 0x0
#define SRC_AND_DEST 0x1
#define SRC_AND_nDEST 0x2
#define SRC 0x3
#define nSRC_AND_DEST 0x4
#define DEST 0x5
#define SRC_XOR_DEST 0x6
#define SRC_OR_DEST 0x7
#define SRC_NOR_DEST 0x8
#define SRC_XNOR_DEST 0x9
#define nDEST 0xA
#define SRC_OR_nDEST 0xB
#define nSRC 0xC
#define nSRC_OR_DEST 0xD
#define SRC_NAND_DEST 0xE
#define DEST_ONE 0xF
#define SWAP(A) ((A>>8) | ((A&0xff) <<8))
/* frame buffer operations */
static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int dn_fb_set_var(struct fb_var_screeninfo *var, int isactive,
struct fb_info *info);
static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
struct fb_info *info);
static int dn_fb_blank(int blank,struct fb_info *info);
static int dnfbcon_switch(int con,struct fb_info *info);
static int dnfbcon_updatevar(int con,struct fb_info *info);
static void dn_fb_set_disp(int con,struct fb_info *info);
static struct display disp[MAX_NR_CONSOLES];
static struct fb_info fb_info;
static struct fb_ops dn_fb_ops = {
owner: THIS_MODULE,
fb_get_fix: dn_fb_get_fix,
fb_get_var: dn_fb_get_var,
fb_set_var: dn_fb_set_var,
fb_get_cmap: dn_fb_get_cmap,
fb_set_cmap: gen_set_cmap,
fb_blank: dn_fb_blank,
};
#define NUM_TOTAL_MODES 1
struct fb_var_screeninfo dn_fb_predefined[] = {
{ 0, },
};
static char dn_fb_name[]="Apollo ";
/* accel stuff */
#define USE_DN_ACCEL
static struct display_switch dispsw_apollofb;
static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info) {
strcpy(fix->id,"Apollo Color8");
fix->smem_start=(char*)(FRAME_BUFFER_START+IO_BASE);
fix->smem_len=FRAME_BUFFER_LEN;
fix->type=FB_TYPE_PACKED_PIXELS;
fix->type_aux=0;
fix->visual=FB_VISUAL_MONO10;
fix->xpanstep=0;
fix->ypanstep=0;
fix->ywrapstep=0;
fix->line_length=128;
return 0;
}
static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info) {
var->xres=1024;
var->yres=800;
var->xres_virtual=1024;
var->yres_virtual=1024;
var->xoffset=0;
var->yoffset=0;
var->bits_per_pixel=1;
var->grayscale=0;
var->nonstd=0;
var->activate=0;
var->height=-1;
var->width=-1;
var->pixclock=0;
var->left_margin=0;
var->right_margin=0;
var->hsync_len=0;
var->vsync_len=0;
var->sync=0;
var->vmode=FB_VMODE_NONINTERLACED;
return 0;
}
static int dn_fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info) {
printk("fb_set_var\n");
if(var->xres!=1024)
return -EINVAL;
if(var->yres!=800)
return -EINVAL;
if(var->xres_virtual!=1024)
return -EINVAL;
if(var->yres_virtual!=1024)
return -EINVAL;
if(var->xoffset!=0)
return -EINVAL;
if(var->yoffset!=0)
return -EINVAL;
if(var->bits_per_pixel!=1)
return -EINVAL;
if(var->grayscale!=0)
return -EINVAL;
if(var->nonstd!=0)
return -EINVAL;
if(var->activate!=0)
return -EINVAL;
if(var->pixclock!=0)
return -EINVAL;
if(var->left_margin!=0)
return -EINVAL;
if(var->right_margin!=0)
return -EINVAL;
if(var->hsync_len!=0)
return -EINVAL;
if(var->vsync_len!=0)
return -EINVAL;
if(var->sync!=0)
return -EINVAL;
if(var->vmode!=FB_VMODE_NONINTERLACED)
return -EINVAL;
return 0;
}
static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
struct fb_info *info) {
printk("get cmap not supported\n");
return -EINVAL;
}
static void dn_fb_set_disp(int con, struct fb_info *info) {
struct fb_fix_screeninfo fix;
dn_fb_get_fix(&fix,con, info);
if(con==-1)
con=0;
disp[con].visual = fix.visual;
disp[con].type = fix.type;
disp[con].type_aux = fix.type_aux;
disp[con].ypanstep = fix.ypanstep;
disp[con].ywrapstep = fix.ywrapstep;
disp[con].can_soft_blank = 1;
disp[con].inverse = 0;
disp[con].line_length = fix.line_length;
disp[con].dispsw = &dispsw_apollofb;
}
unsigned long dn_fb_init(unsigned long mem_start) {
int err;
printk("dn_fb_init\n");
fb_info.changevar=NULL;
strcpy(&fb_info.modename[0],dn_fb_name);
fb_info.fontname[0]=0;
fb_info.disp=disp;
fb_info.switch_con=&dnfbcon_switch;
fb_info.updatevar=&dnfbcon_updatevar;
fb_info.node = NODEV;
fb_info.currcon = -1;
fb_info.fbops = &dn_fb_ops;
printk("screenbase: %p\n",fix.smem_start);
printk("dn_fb_init: register\n");
err=register_framebuffer(&fb_info);
if(err < 0) {
panic("unable to register apollo frame buffer\n");
}
/* now we have registered we can safely setup the hardware */
outb(RESET_CREG, AP_CONTROL_3A);
outb(RESET_CREG, AP_CONTROL_3B);
outw(0x0, AP_WRITE_ENABLE);
outb(NORMAL_MODE, AP_CONTROL_0);
outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1);
outb(0, AP_CONTROL_2A);
outb(S_DATA_PLN, AP_CONTROL_2B);
outw(SWAP(0x3), AP_ROP_1);
printk("apollo frame buffer alive and kicking !\n");
dn_fb_get_var(&disp[0].var,0, &fb_info);
dn_fb_set_disp(-1, &fb_info);
fb_info.screen_base = (u_char *)fix.smem_start;
return mem_start;
}
static int dnfbcon_switch(int con, struct fb_info *info) {
info->currcon = con;
return 0;
}
static int dnfbcon_updatevar(int con, struct fb_info *info) {
return 0;
}
static int dn_fb_blank(int blank, struct fb_info *info)
{
if (blank)
outb(0x0, AP_CONTROL_3A);
else
outb(0x1, AP_CONTROL_3A);
return 0;
}
void dn_bitblt(struct display *p,int x_src,int y_src, int x_dest, int y_dest,
int x_count, int y_count) {
int incr,y_delta,pre_read=0,x_end,x_word_count;
ushort *src,dummy;
uint start_mask,end_mask,dest;
short i,j;
incr=(y_dest<=y_src) ? 1 : -1 ;
src=(ushort *)(p->fb_info.screen_base+ y_src*p->next_line+(x_src >> 4));
dest=y_dest*(p->next_line >> 1)+(x_dest >> 4);
if(incr>0) {
y_delta=(p->next_line*8)-x_src-x_count;
x_end=x_dest+x_count-1;
x_word_count=(x_end>>4) - (x_dest >> 4) + 1;
start_mask=0xffff0000 >> (x_dest & 0xf);
end_mask=0x7ffff >> (x_end & 0xf);
outb((((x_dest & 0xf) - (x_src &0xf)) % 16)|(0x4 << 5),AP_CONTROL_0);
if((x_dest & 0xf) < (x_src & 0xf))
pre_read=1;
}
else {
y_delta=-((p->next_line*8)-x_src-x_count);
x_end=x_dest-x_count+1;
x_word_count=(x_dest>>4) - (x_end >> 4) + 1;
start_mask=0x7ffff >> (x_dest & 0xf);
end_mask=0xffff0000 >> (x_end & 0xf);
outb(((-((x_src & 0xf) - (x_dest &0xf))) % 16)|(0x4 << 5),AP_CONTROL_0);
if((x_dest & 0xf) > (x_src & 0xf))
pre_read=1;
}
for(i=0;i<y_count;i++) {
if(pre_read) {
dummy=*src;
src+=incr;
}
if(x_word_count) {
outb(start_mask,AP_WRITE_ENABLE);
*src=dest;
src+=incr;
dest+=incr;
outb(0,AP_WRITE_ENABLE);
for(j=1;j<(x_word_count-1);j++) {
*src=dest;
src+=incr;
dest+=incr;
}
outb(start_mask,AP_WRITE_ENABLE);
*src=dest;
dest+=incr;
src+=incr;
}
else {
outb(start_mask | end_mask, AP_WRITE_ENABLE);
*src=dest;
dest+=incr;
src+=incr;
}
src+=(y_delta/16);
dest+=(y_delta/16);
}
outb(NORMAL_MODE,AP_CONTROL_0);
}
static void bmove_apollofb(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
#ifdef USE_DN_ACCEL
dn_bitblt(p,sx,sy*p->fontheight,dx,dy*p->fontheight,width*p->fontwidth,
height*p->fontheight);
#else
u_char *src, *dest;
u_int rows;
if (sx == 0 && dx == 0 && width == p->next_line) {
src = p->fb_info.screen_base+sy*p->fontheight*width;
dest = p->fb_info.screen_base+dy*p->fontheight*width;
mymemmove(dest, src, height*p->fontheight*width);
} else if (dy <= sy) {
src = p->fb_info.screen_base+sy*p->fontheight*p->next_line+sx;
dest = p->fb_info.screen_base+dy*p->fontheight*p->next_line+dx;
for (rows = height*p->fontheight; rows--;) {
mymemmove(dest, src, width);
src += p->next_line;
dest += p->next_line;
}
} else {
src = p->fb_info.screen_base+((sy+height)*p->fontheight-1)*p->next_line+sx;
dest = p->fb_info.screen_base+((dy+height)*p->fontheight-1)*p->next_line+dx;
for (rows = height*p->fontheight; rows--;) {
mymemmove(dest, src, width);
src -= p->next_line;
dest -= p->next_line;
}
}
#endif
}
static void clear_apollofb(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width)
{
u_char *dest;
u_int rows;
dest = p->fb_info.screen_base+sy*p->fontheight*p->next_line+sx;
if (sx == 0 && width == p->next_line)
if (attr_reverse(p,conp))
mymemset(dest, height*p->fontheight*width);
else
mymemclear(dest, height*p->fontheight*width);
else
for (rows = height*p->fontheight; rows--; dest += p->next_line)
if (attr_reverse(p,conp))
mymemset(dest, width);
else
mymemclear_small(dest, width);
}
static void putc_apollofb(struct vc_data *conp, struct display *p, int c, int yy,
int xx)
{
u_char *dest, *cdat;
u_int rows, bold, revs, underl;
u_char d;
c &= 0xff;
dest = p->fb_info.screen_base+yy*p->fontheight*p->next_line+xx;
cdat = p->fontdata+c*p->fontheight;
bold = attr_bold(p,conp);
revs = attr_reverse(p,conp);
underl = attr_underline(p,conp);
for (rows = p->fontheight; rows--; dest += p->next_line) {
d = *cdat++;
if (underl && !rows)
d = 0xff;
else if (bold)
d |= d>>1;
if (revs)
d = ~d;
*dest = d;
}
}
static void putcs_apollofb(struct vc_data *conp, struct display *p, const char *s,
int count, int yy, int xx)
{
u_char *dest, *dest0, *cdat;
u_int rows, bold, revs, underl;
u_char c, d;
dest0 = p->fb_info.screen_base+yy*p->fontheight*p->next_line+xx;
bold = attr_bold(p,conp);
revs = attr_reverse(p,conp);
underl = attr_underline(p,conp);
while (count--) {
c = scr_readw(s++);
dest = dest0++;
cdat = p->fontdata+c*p->fontheight;
for (rows = p->fontheight; rows--; dest += p->next_line) {
d = *cdat++;
if (underl && !rows)
d = 0xff;
else if (bold)
d |= d>>1;
if (revs)
d = ~d;
*dest = d;
}
}
}
static void rev_char_apollofb(struct display *p, int xx, int yy)
{
u_char *dest;
u_int rows;
dest = p->fb_info.screen_base+yy*p->fontheight*p->next_line+xx;
for (rows = p->fontheight; rows--; dest += p->next_line)
*dest = ~*dest;
}
static struct display_switch dispsw_apollofb = {
setup: fbcon_mfb_setup,
bmove: bmove_apollofb,
clear: clear_apollofb,
putc: putc_apollofb,
putcs: putcs_apollofb,
revc: rev_char_apollofb,
fontwidthmask: FONTWIDTH(8)
};
MODULE_LICENSE("GPL");
...@@ -14,9 +14,8 @@ ...@@ -14,9 +14,8 @@
#include <asm/apollohw.h> #include <asm/apollohw.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/module.h> #include <linux/module.h>
#include "dn_accel.h"
#include <video/fbcon.h> #include <video/fbcon.h>
#include <video/fbcon-mfb.h>
/* apollo video HW definitions */ /* apollo video HW definitions */
...@@ -30,45 +29,45 @@ ...@@ -30,45 +29,45 @@
* deals with control 1 and 3b deals with Color LUT reg. * deals with control 1 and 3b deals with Color LUT reg.
*/ */
#define AP_IOBASE 0x3b0 /* Base address of 1 plane board. */ #define AP_IOBASE 0x3b0 /* Base address of 1 plane board. */
#define AP_STATUS isaIO2mem(AP_IOBASE+0) /* Status register. Read */ #define AP_STATUS isaIO2mem(AP_IOBASE+0) /* Status register. Read */
#define AP_WRITE_ENABLE isaIO2mem(AP_IOBASE+0) /* Write Enable Register Write */ #define AP_WRITE_ENABLE isaIO2mem(AP_IOBASE+0) /* Write Enable Register Write */
#define AP_DEVICE_ID isaIO2mem(AP_IOBASE+1) /* Device ID Register. Read */ #define AP_DEVICE_ID isaIO2mem(AP_IOBASE+1) /* Device ID Register. Read */
#define AP_ROP_1 isaIO2mem(AP_IOBASE+2) /* Raster Operation reg. Write Word */ #define AP_ROP_1 isaIO2mem(AP_IOBASE+2) /* Raster Operation reg. Write Word */
#define AP_DIAG_MEM_REQ isaIO2mem(AP_IOBASE+4) /* Diagnostic Memory Request. Write Word */ #define AP_DIAG_MEM_REQ isaIO2mem(AP_IOBASE+4) /* Diagnostic Memory Request. Write Word */
#define AP_CONTROL_0 isaIO2mem(AP_IOBASE+8) /* Control Register 0. Read/Write */ #define AP_CONTROL_0 isaIO2mem(AP_IOBASE+8) /* Control Register 0. Read/Write */
#define AP_CONTROL_1 isaIO2mem(AP_IOBASE+0xa) /* Control Register 1. Read/Write */ #define AP_CONTROL_1 isaIO2mem(AP_IOBASE+0xa) /* Control Register 1. Read/Write */
#define AP_CONTROL_3A isaIO2mem(AP_IOBASE+0xe) /* Control Register 3a. Read/Write */ #define AP_CONTROL_3A isaIO2mem(AP_IOBASE+0xe) /* Control Register 3a. Read/Write */
#define AP_CONTROL_2 isaIO2mem(AP_IOBASE+0xc) /* Control Register 2. Read/Write */ #define AP_CONTROL_2 isaIO2mem(AP_IOBASE+0xc) /* Control Register 2. Read/Write */
#define FRAME_BUFFER_START 0x0FA0000 #define FRAME_BUFFER_START 0x0FA0000
#define FRAME_BUFFER_LEN 0x40000 #define FRAME_BUFFER_LEN 0x40000
/* CREG 0 */ /* CREG 0 */
#define VECTOR_MODE 0x40 /* 010x.xxxx */ #define VECTOR_MODE 0x40 /* 010x.xxxx */
#define DBLT_MODE 0x80 /* 100x.xxxx */ #define DBLT_MODE 0x80 /* 100x.xxxx */
#define NORMAL_MODE 0xE0 /* 111x.xxxx */ #define NORMAL_MODE 0xE0 /* 111x.xxxx */
#define SHIFT_BITS 0x1F /* xxx1.1111 */ #define SHIFT_BITS 0x1F /* xxx1.1111 */
/* other bits are Shift value */ /* other bits are Shift value */
/* CREG 1 */ /* CREG 1 */
#define AD_BLT 0x80 /* 1xxx.xxxx */ #define AD_BLT 0x80 /* 1xxx.xxxx */
#define NORMAL 0x80 /* 1xxx.xxxx */ /* What is happening here ?? */ #define NORMAL 0x80 /* 1xxx.xxxx */ /* What is happening here ?? */
#define INVERSE 0x00 /* 0xxx.xxxx */ /* Clearing this reverses the screen */ #define INVERSE 0x00 /* 0xxx.xxxx */ /* Clearing this reverses the screen */
#define PIX_BLT 0x00 /* 0xxx.xxxx */ #define PIX_BLT 0x00 /* 0xxx.xxxx */
#define AD_HIBIT 0x40 /* xIxx.xxxx */ #define AD_HIBIT 0x40 /* xIxx.xxxx */
#define ROP_EN 0x10 /* xxx1.xxxx */ #define ROP_EN 0x10 /* xxx1.xxxx */
#define DST_EQ_SRC 0x00 /* xxx0.xxxx */ #define DST_EQ_SRC 0x00 /* xxx0.xxxx */
#define nRESET_SYNC 0x08 /* xxxx.1xxx */ #define nRESET_SYNC 0x08 /* xxxx.1xxx */
#define SYNC_ENAB 0x02 /* xxxx.xx1x */ #define SYNC_ENAB 0x02 /* xxxx.xx1x */
#define BLANK_DISP 0x00 /* xxxx.xxx0 */ #define BLANK_DISP 0x00 /* xxxx.xxx0 */
#define ENAB_DISP 0x01 /* xxxx.xxx1 */ #define ENAB_DISP 0x01 /* xxxx.xxx1 */
#define NORM_CREG1 (nRESET_SYNC | SYNC_ENAB | ENAB_DISP) /* no reset sync */ #define NORM_CREG1 (nRESET_SYNC | SYNC_ENAB | ENAB_DISP) /* no reset sync */
/* CREG 2 */ /* CREG 2 */
...@@ -76,13 +75,13 @@ ...@@ -76,13 +75,13 @@
* Following 3 defines are common to 1, 4 and 8 plane. * Following 3 defines are common to 1, 4 and 8 plane.
*/ */
#define S_DATA_1s 0x00 /* 00xx.xxxx */ /* set source to all 1's -- vector drawing */ #define S_DATA_1s 0x00 /* 00xx.xxxx */ /* set source to all 1's -- vector drawing */
#define S_DATA_PIX 0x40 /* 01xx.xxxx */ /* takes source from ls-bits and replicates over 16 bits */ #define S_DATA_PIX 0x40 /* 01xx.xxxx */ /* takes source from ls-bits and replicates over 16 bits */
#define S_DATA_PLN 0xC0 /* 11xx.xxxx */ /* normal, each data access =16-bits in #define S_DATA_PLN 0xC0 /* 11xx.xxxx */ /* normal, each data access =16-bits in
one plane of image mem */ one plane of image mem */
/* CREG 3A/CREG 3B */ /* CREG 3A/CREG 3B */
# define RESET_CREG 0x80 /* 1000.0000 */ # define RESET_CREG 0x80 /* 1000.0000 */
/* ROP REG - all one nibble */ /* ROP REG - all one nibble */
/* ********* NOTE : this is used r0,r1,r2,r3 *********** */ /* ********* NOTE : this is used r0,r1,r2,r3 *********** */
...@@ -111,385 +110,169 @@ ...@@ -111,385 +110,169 @@
#define outw(a,d) *(unsigned short *)a=d #define outw(a,d) *(unsigned short *)a=d
#endif #endif
static struct fb_info fb_info;
static struct display disp;
/* frame buffer operations */ /* frame buffer operations */
static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con, static int dn_fb_blank(int blank, struct fb_info *info);
struct fb_info *info); static void dnfb_copyarea(struct fb_info *info, struct fb_copyarea *area);
static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int dn_fb_set_var(struct fb_var_screeninfo *var, int isactive,
struct fb_info *info);
static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
struct fb_info *info);
static int dn_fb_blank(int blank,struct fb_info *info);
static int dnfbcon_switch(int con,struct fb_info *info);
static int dnfbcon_updatevar(int con,struct fb_info *info);
static void dn_fb_set_disp(int con,struct fb_info *info);
static struct display disp[MAX_NR_CONSOLES];
static struct fb_info fb_info;
static struct fb_ops dn_fb_ops = { static struct fb_ops dn_fb_ops = {
owner: THIS_MODULE, owner: THIS_MODULE,
fb_get_fix: dn_fb_get_fix, fb_get_fix: gen_get_fix,
fb_get_var: dn_fb_get_var, fb_get_var: gen_get_var,
fb_set_var: dn_fb_set_var, fb_set_var: gen_set_var,
fb_get_cmap: dn_fb_get_cmap, fb_get_cmap: gen_get_cmap,
fb_set_cmap: gen_set_cmap, fb_set_cmap: gen_set_cmap,
fb_blank: dn_fb_blank, fb_blank: dnfb_blank,
fb_fillrect: cfb_fillrect,
fb_copyarea: dnfb_copyarea,
fb_imageblit: cfb_imageblit,
}; };
#define NUM_TOTAL_MODES 1 struct fb_var_screeninfo dnfb_var __initdata = {
struct fb_var_screeninfo dn_fb_predefined[] = { xres: 1280,
yres: 1024,
{ 0, }, xres_virtual: 2048,
yres_virtual: 1024,
bits_per_pixel: 1,
height: -1,
width: -1,
vmode: FB_VMODE_NONINTERLACED,
}; };
static char dn_fb_name[]="Apollo "; static struct fb_fix_screeninfo dnfb_fix __initdata = {
id: "Apollo Mono",
/* accel stuff */ smem_start: (FRAME_BUFFER_START + IO_BASE),
#define USE_DN_ACCEL smem_len: FRAME_BUFFER_LEN,
type: FB_TYPE_PACKED_PIXELS,
static struct display_switch dispsw_apollofb; visual: FB_VISUAL_MONO10,
line_length: 256,
static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con, };
struct fb_info *info) {
strcpy(fix->id,"Apollo Mono");
fix->smem_start=(FRAME_BUFFER_START+IO_BASE);
fix->smem_len=FRAME_BUFFER_LEN;
fix->type=FB_TYPE_PACKED_PIXELS;
fix->type_aux=0;
fix->visual=FB_VISUAL_MONO10;
fix->xpanstep=0;
fix->ypanstep=0;
fix->ywrapstep=0;
fix->line_length=256;
return 0;
}
static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info) {
var->xres=1280;
var->yres=1024;
var->xres_virtual=2048;
var->yres_virtual=1024;
var->xoffset=0;
var->yoffset=0;
var->bits_per_pixel=1;
var->grayscale=0;
var->nonstd=0;
var->activate=0;
var->height=-1;
var->width=-1;
var->pixclock=0;
var->left_margin=0;
var->right_margin=0;
var->hsync_len=0;
var->vsync_len=0;
var->sync=0;
var->vmode=FB_VMODE_NONINTERLACED;
return 0;
}
static int dn_fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info) {
printk("fb_set_var\n");
if(var->xres!=1280)
return -EINVAL;
if(var->yres!=1024)
return -EINVAL;
if(var->xres_virtual!=2048)
return -EINVAL;
if(var->yres_virtual!=1024)
return -EINVAL;
if(var->xoffset!=0)
return -EINVAL;
if(var->yoffset!=0)
return -EINVAL;
if(var->bits_per_pixel!=1)
return -EINVAL;
if(var->grayscale!=0)
return -EINVAL;
if(var->nonstd!=0)
return -EINVAL;
if(var->activate!=0)
return -EINVAL;
if(var->pixclock!=0)
return -EINVAL;
if(var->left_margin!=0)
return -EINVAL;
if(var->right_margin!=0)
return -EINVAL;
if(var->hsync_len!=0)
return -EINVAL;
if(var->vsync_len!=0)
return -EINVAL;
if(var->sync!=0)
return -EINVAL;
if(var->vmode!=FB_VMODE_NONINTERLACED)
return -EINVAL;
return 0;
}
static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
struct fb_info *info) {
printk("get cmap not supported\n");
return -EINVAL;
}
static void dn_fb_set_disp(int con, struct fb_info *info) {
struct fb_fix_screeninfo fix;
struct display *display;
dn_fb_get_fix(&fix,con, info);
if (con>=0)
display=&fb_display[con];
else
display=&disp[0];
if(con==-1)
con=0;
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
display->ypanstep = fix.ypanstep;
display->ywrapstep = fix.ywrapstep;
display->can_soft_blank = 1;
display->inverse = 0;
display->line_length = fix.line_length;
#ifdef FBCON_HAS_MFB
display->dispsw = &fbcon_mfb;
#else
display->dispsw=&fbcon_dummy;
#endif
}
unsigned long __init dnfb_init(unsigned long mem_start) {
int err;
fb_info.changevar=NULL;
strcpy(&fb_info.modename[0],dn_fb_name);
fb_info.fontname[0]=0;
fb_info.disp=disp;
fb_info.switch_con=&dnfbcon_switch;
fb_info.updatevar=&dnfbcon_updatevar;
fb_info.node = NODEV;
fb_info.fbops = &dn_fb_ops;
fb_info.currcon = -1;
dn_fb_get_var(&disp[0].var,0, &fb_info);
dn_fb_set_disp(-1, &fb_info);
fb_info.screen_base = (u_char *)fix.smem_start;
err=register_framebuffer(&fb_info);
if(err < 0) {
panic("unable to register apollo frame buffer\n");
}
/* now we have registered we can safely setup the hardware */
outb(RESET_CREG, AP_CONTROL_3A);
outw(0x0, AP_WRITE_ENABLE);
outb(NORMAL_MODE, AP_CONTROL_0);
outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1);
outb(S_DATA_PLN, AP_CONTROL_2);
outw(SWAP(0x3), AP_ROP_1);
printk("apollo frame buffer alive and kicking !\n");
return mem_start;
}
static int dnfbcon_switch(int con, struct fb_info *info) {
info->currcon = con;
return 0;
}
static int dnfbcon_updatevar(int con, struct fb_info *info) {
return 0;
}
static int dn_fb_blank(int blank, struct fb_info *info) static int dnfb_blank(int blank, struct fb_info *info)
{ {
if (blank) if (blank)
outb(0x0, AP_CONTROL_3A); outb(0x0, AP_CONTROL_3A);
else else
outb(0x1, AP_CONTROL_3A); outb(0x1, AP_CONTROL_3A);
return 0; return 0;
} }
void dn_bitblt(struct display *p,int x_src,int y_src, int x_dest, int y_dest, static
int x_count, int y_count) { void dnfb_copyarea(struct fb_info *info, struct fb_copyarea *area)
{
int incr,y_delta,pre_read=0,x_end,x_word_count;
ushort *src,dummy; int incr, y_delta, pre_read = 0, x_end, x_word_count;
uint start_mask,end_mask,dest; int x_count, y_count;
short i,j; ushort *src, dummy;
uint start_mask, end_mask, dest;
incr=(y_dest<=y_src) ? 1 : -1 ; short i, j;
src=(ushort *)(p->fb_info.screen_base+ y_src*p->next_line+(x_src >> 4)); incr = (area->dy <= area->sy) ? 1 : -1;
dest=y_dest*(p->next_line >> 1)+(x_dest >> 4);
src =
if(incr>0) { (ushort *) (info->screen_base + area->sy * info->fix.next_line +
y_delta=(p->next_line*8)-x_src-x_count; (area->sx >> 4));
x_end=x_dest+x_count-1; dest = area->dy * (info->fix.next_line >> 1) + (area->dx >> 4);
x_word_count=(x_end>>4) - (x_dest >> 4) + 1;
start_mask=0xffff0000 >> (x_dest & 0xf); if (incr > 0) {
end_mask=0x7ffff >> (x_end & 0xf); y_delta = (info->fix.next_line * 8) - area->sx - x_count;
outb((((x_dest & 0xf) - (x_src &0xf)) % 16)|(0x4 << 5),AP_CONTROL_0); x_end = area->dx + x_count - 1;
if((x_dest & 0xf) < (x_src & 0xf)) x_word_count = (x_end >> 4) - (area->dx >> 4) + 1;
pre_read=1; start_mask = 0xffff0000 >> (area->dx & 0xf);
} end_mask = 0x7ffff >> (x_end & 0xf);
else { outb((((area->dx & 0xf) - (area->sx & 0xf)) % 16) | (0x4 << 5),
y_delta=-((p->next_line*8)-x_src-x_count); AP_CONTROL_0);
x_end=x_dest-x_count+1; if ((area->dx & 0xf) < (area->sx & 0xf))
x_word_count=(x_dest>>4) - (x_end >> 4) + 1; pre_read = 1;
start_mask=0x7ffff >> (x_dest & 0xf); } else {
end_mask=0xffff0000 >> (x_end & 0xf); y_delta = -((info->fix.next_line * 8) - area->sx - x_count);
outb(((-((x_src & 0xf) - (x_dest &0xf))) % 16)|(0x4 << 5),AP_CONTROL_0); x_end = area->dx - x_count + 1;
if((x_dest & 0xf) > (x_src & 0xf)) x_word_count = (area->dx >> 4) - (x_end >> 4) + 1;
pre_read=1; start_mask = 0x7ffff >> (area->dx & 0xf);
end_mask = 0xffff0000 >> (x_end & 0xf);
outb(((-((area->sx & 0xf) - (area->dx & 0xf))) %
16) | (0x4 << 5), AP_CONTROL_0);
if ((area->dx & 0xf) > (area->sx & 0xf))
pre_read = 1;
} }
for(i=0;i<y_count;i++) { for (i = 0; i < y_count; i++) {
outb(0xc | (dest >> 16), AP_CONTROL_3A); outb(0xc | (dest >> 16), AP_CONTROL_3A);
if(pre_read) { if (pre_read) {
dummy=*src; dummy = *src;
src+=incr; src += incr;
} }
if(x_word_count) { if (x_word_count) {
outb(start_mask,AP_WRITE_ENABLE); outb(start_mask, AP_WRITE_ENABLE);
*src=dest; *src = dest;
src+=incr; src += incr;
dest+=incr; dest += incr;
outb(0,AP_WRITE_ENABLE); outb(0, AP_WRITE_ENABLE);
for(j=1;j<(x_word_count-1);j++) { for (j = 1; j < (x_word_count - 1); j++) {
*src=dest; *src = dest;
src+=incr; src += incr;
dest+=incr; dest += incr;
} }
outb(start_mask,AP_WRITE_ENABLE); outb(start_mask, AP_WRITE_ENABLE);
*src=dest; *src = dest;
dest+=incr; dest += incr;
src+=incr; src += incr;
} } else {
else {
outb(start_mask | end_mask, AP_WRITE_ENABLE); outb(start_mask | end_mask, AP_WRITE_ENABLE);
*src=dest; *src = dest;
dest+=incr; dest += incr;
src+=incr; src += incr;
} }
src+=(y_delta/16); src += (y_delta / 16);
dest+=(y_delta/16); dest += (y_delta / 16);
} }
outb(NORMAL_MODE,AP_CONTROL_0); outb(NORMAL_MODE, AP_CONTROL_0);
} }
static void bmove_apollofb(struct display *p, int sy, int sx, int dy, int dx,
int height, int width) unsigned long __init dnfb_init(unsigned long mem_start)
{ {
int err;
int fontheight,fontwidth; strcpy(&fb_info.modename, dnfb_fix);
fb_info.changevar = NULL;
fontheight=fontheight(p); fb_info.fontname[0] = 0;
fontwidth=fontwidth(p); fb_info.disp = &disp;
fb_info.switch_con = gen_switch;
#ifdef USE_DN_ACCEL fb_info.updatevar = gen_update_var;
dn_bitblt(p,sx,sy*fontheight,dx,dy*fontheight,width*fontwidth, fb_info.node = NODEV;
height*fontheight); fb_info.fbops = &dn_fb_ops;
#else fb_info.currcon = -1;
u_char *src, *dest; fb_info.fix = dnfb_fix;
u_int rows; fb_info.var = dnfb_var;
if (sx == 0 && dx == 0 && width == p->next_line) {
src = p->fb_info.screen_base+sy*fontheight*width;
dest = p->fb_info.screen_base+dy*fontheight*width;
mymemmove(dest, src, height*fontheight*width);
} else if (dy <= sy) {
src = p->fb_info.screen_base+sy*fontheight*next_line+sx;
dest = p->fb_info.screen_base+dy*fontheight*next_line+dx;
for (rows = height*fontheight; rows--;) {
mymemmove(dest, src, width);
src += p->next_line;
dest += p->next_line;
}
} else {
src = p->fb_info.screen_base+((sy+height)*fontheight-1)*p->next_line+sx;
dest = p->fb_info.screen_base+((dy+height)*fontheight-1)*p->next_line+dx;
for (rows = height*fontheight; rows--;) {
mymemmove(dest, src, width);
src -= p->next_line;
dest -= p->next_line;
}
}
#endif
}
static void clear_apollofb(struct vc_data *conp, struct display *p, int sy, int sx, fb_alloc_cmap(&fb_info.cmap, 2, 0);
int height, int width) gen_set_disp(-1, &fb_info);
{
fbcon_mfb_clear(conp,p,sy,sx,height,width);
}
static void putc_apollofb(struct vc_data *conp, struct display *p, int c, int yy, fb_info.screen_base = (u_char *) fb_info.fix.smem_start;
int xx)
{
fbcon_mfb_putc(conp,p,c,yy,xx);
}
static void putcs_apollofb(struct vc_data *conp, struct display *p, const char *s, err = register_framebuffer(&fb_info);
int count, int yy, int xx) if (err < 0)
{ panic("unable to register apollo frame buffer\n");
fbcon_mfb_putcs(conp,p,s,count,yy,xx);
}
static void rev_char_apollofb(struct display *p, int xx, int yy) /* now we have registered we can safely setup the hardware */
{ outb(RESET_CREG, AP_CONTROL_3A);
fbcon_mfb_revc(p,xx,yy); outw(0x0, AP_WRITE_ENABLE);
outb(NORMAL_MODE, AP_CONTROL_0);
outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1);
outb(S_DATA_PLN, AP_CONTROL_2);
outw(SWAP(0x3), AP_ROP_1);
printk("apollo frame buffer alive and kicking !\n");
return mem_start;
} }
static struct display_switch dispsw_apollofb = {
setup: fbcon_mfb_setup,
bmove: bmove_apollofb,
clear: clear_apollofb,
putc: putc_apollofb,
putcs: putcs_apollofb,
revc: rev_char_apollofb,
fontwidthmask: FONTWIDTH(8)
};
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -150,7 +150,7 @@ void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto) ...@@ -150,7 +150,7 @@ void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
else else
tooff = from->start-to->start; tooff = from->start-to->start;
size = to->len-tooff; size = to->len-tooff;
if (size > from->len-fromoff) if (size > (int) (from->len - fromoff))
size = from->len-fromoff; size = from->len-fromoff;
if (size <= 0) if (size <= 0)
return; return;
......
...@@ -132,6 +132,7 @@ extern int pmagbafb_init(void); ...@@ -132,6 +132,7 @@ extern int pmagbafb_init(void);
extern int pmagbbfb_init(void); extern int pmagbbfb_init(void);
extern void maxinefb_init(void); extern void maxinefb_init(void);
extern int tx3912fb_init(void); extern int tx3912fb_init(void);
extern int tx3912fb_setup(char*);
extern int radeonfb_init(void); extern int radeonfb_init(void);
extern int radeonfb_setup(char*); extern int radeonfb_setup(char*);
extern int e1355fb_init(void); extern int e1355fb_init(void);
...@@ -300,7 +301,7 @@ static struct { ...@@ -300,7 +301,7 @@ static struct {
{ "hitfb", hitfb_init, NULL }, { "hitfb", hitfb_init, NULL },
#endif #endif
#ifdef CONFIG_FB_TX3912 #ifdef CONFIG_FB_TX3912
{ "tx3912", tx3912fb_init, NULL }, { "tx3912", tx3912fb_init, tx3912fb_setup },
#endif #endif
#ifdef CONFIG_FB_E1355 #ifdef CONFIG_FB_E1355
{ "e1355fb", e1355fb_init, e1355fb_setup }, { "e1355fb", e1355fb_init, e1355fb_setup },
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
* *
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -42,48 +41,32 @@ ...@@ -42,48 +41,32 @@
/* whether are really running on a maxine, KM */ /* whether are really running on a maxine, KM */
#include <asm/bootinfo.h> #include <asm/bootinfo.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)))
static struct display disp;
static struct fb_info fb_info; static struct fb_info fb_info;
static struct display disp;
unsigned long fb_start, fb_size = 1024 * 768, fb_line_length = 1024;
unsigned long fb_regs;
unsigned char fb_bitmask;
static struct fb_var_screeninfo maxinefb_defined = { static struct fb_var_screeninfo maxinefb_defined = {
0, 0, 0, 0, /* W,H, W, H (virtual) load xres,xres_virtual */ xres: 1024,
0, 0, /* virtual -> visible no offset */ yres: 768,
0, /* depth -> load bits_per_pixel */ xres_virtual: 1024,
0, /* greyscale ? */ yres_virtual: 768,
{0, 0, 0}, /* R */ bits_per_pixel: 8,
{0, 0, 0}, /* G */ activate: FB_ACTIVATE_NOW,
{0, 0, 0}, /* B */ height: -1,
{0, 0, 0}, /* transparency */ width: -1,
0, /* standard pixel format */ vmode: FB_VMODE_NONINTERLACED,
FB_ACTIVATE_NOW,
274, 195, /* 14" monitor */
FB_ACCEL_NONE,
0L, 0L, 0L, 0L, 0L,
0L, 0L, 0, /* No sync info */
FB_VMODE_NONINTERLACED,
{0, 0, 0, 0, 0, 0}
};
struct maxinefb_par {
}; };
struct maxinefb_par current_par; static struct fb_fix_screeninfo maxinefb_fix = {
id: "Maxine onboard graphics 1024x768x8",
smem_len: (1024*768),
type: FB_TYPE_PACKED_PIXELS,
visual: FB_VISUAL_PSEUDOCOLOR,
line_length: 1024,
}
/* Reference to machine type set in arch/mips/dec/prom/identify.c, KM */ /* Reference to machine type set in arch/mips/dec/prom/identify.c, KM */
extern unsigned long mips_machtype; extern unsigned long mips_machtype;
/* Handle the funny Inmos RamDAC/video controller ... */ /* Handle the funny Inmos RamDAC/video controller ... */
void maxinefb_ims332_write_register(int regno, register unsigned int val) void maxinefb_ims332_write_register(int regno, register unsigned int val)
...@@ -109,212 +92,41 @@ unsigned int maxinefb_ims332_read_register(int regno) ...@@ -109,212 +92,41 @@ unsigned int maxinefb_ims332_read_register(int regno)
return (j & 0xffff) | ((k & 0xff00) << 8); return (j & 0xffff) | ((k & 0xff00) << 8);
} }
static void maxinefb_encode_var(struct fb_var_screeninfo *var,
struct maxinefb_par *par)
{
int i = 0;
var->xres = 1024;
var->yres = 768;
var->xres_virtual = 1024;
var->yres_virtual = 768;
var->xoffset = 0;
var->yoffset = 0;
var->bits_per_pixel = 8;
var->grayscale = 0;
var->transp.offset = 0;
var->transp.length = 0;
var->transp.msb_right = 0;
var->nonstd = 0;
var->activate = 1;
var->height = -1;
var->width = -1;
var->vmode = FB_VMODE_NONINTERLACED;
var->pixclock = 0;
var->sync = 0;
var->left_margin = 0;
var->right_margin = 0;
var->upper_margin = 0;
var->lower_margin = 0;
var->hsync_len = 0;
var->vsync_len = 0;
for (i = 0; i < arraysize(var->reserved); i++)
var->reserved[i] = 0;
}
static void maxinefb_get_par(struct maxinefb_par *par)
{
*par = current_par;
}
static int maxinefb_fb_update_var(int con, struct fb_info *info)
{
return 0;
}
static int maxinefb_do_fb_set_var(struct fb_var_screeninfo *var,
int isactive)
{
struct maxinefb_par par;
maxinefb_get_par(&par);
maxinefb_encode_var(var, &par);
return 0;
}
/* Get the palette */
static int maxinefb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
unsigned int i;
unsigned long hw_colorvalue = 0; /* raw color value from the register */
unsigned int length;
if (((cmap->start) + (cmap->len)) >= 256) {
length = 256 - (cmap->start);
} else {
length = cmap->len;
}
for (i = 0; i < length; i++) {
hw_colorvalue =
maxinefb_ims332_read_register(IMS332_REG_COLOR_PALETTE
+ cmap->start + i);
(cmap->red[i]) = ((hw_colorvalue & 0x0000ff));
(cmap->green[i]) = ((hw_colorvalue & 0x00ff00) >> 8);
(cmap->blue[i]) = ((hw_colorvalue & 0xff0000) >> 16);
}
return 0;
}
/* Set the palette */ /* Set the palette */
static int maxinefb_setcolreg(unsigned regno, unsigned red, unsigned green,
static int maxinefb_set_cmap(struct fb_cmap *cmap, int kspc, int con, unsigned blue, unsigned transp, struct fb_info *info)
struct fb_info *info)
{
unsigned int i;
unsigned long hw_colorvalue; /* value to be written into the palette reg. */
unsigned short cmap_red;
unsigned short cmap_green;
unsigned short cmap_blue;
unsigned int length;
hw_colorvalue = 0;
if (((cmap->start) + (cmap->len)) >= 256) {
length = 256 - (cmap->start);
} else {
length = cmap->len;
}
for (i = 0; i < length; i++) {
cmap_red = ((cmap->red[i]) >> 8); /* The cmap fields are 16 bits */
cmap_green = ((cmap->green[i]) >> 8); /* wide, but the harware colormap */
cmap_blue = ((cmap->blue[i]) >> 8); /* registers are only 8 bits wide */
hw_colorvalue =
(cmap_blue << 16) + (cmap_green << 8) + (cmap_red);
maxinefb_ims332_write_register(IMS332_REG_COLOR_PALETTE +
cmap->start + i,
hw_colorvalue);
}
return 0;
}
static int maxinefb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{ {
struct maxinefb_par par; /* value to be written into the palette reg. */
if (con == -1) { unsigned long hw_colorvalue = 0;
maxinefb_get_par(&par);
maxinefb_encode_var(var, &par);
} else
*var = fb_display[con].var;
return 0;
}
red >>= 8; /* The cmap fields are 16 bits */
green >>= 8; /* wide, but the harware colormap */
blue >>= 8; /* registers are only 8 bits wide */
static int maxinefb_set_var(struct fb_var_screeninfo *var, int con, hw_colorvalue = (blue << 16) + (green << 8) + (red);
struct fb_info *info)
{ maxinefb_ims332_write_register(IMS332_REG_COLOR_PALETTE + regno,
int err; hw_colorvalue);
if ((err = maxinefb_do_fb_set_var(var, 1)))
return err;
return 0; return 0;
} }
static void maxinefb_encode_fix(struct fb_fix_screeninfo *fix,
struct maxinefb_par *par)
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, "maxinefb");
/* fix->id is a char[16], so a maximum of 15 characters, KM */
fix->smem_start = (char *) fb_start; /* display memory base address, KM */
fix->smem_len = fb_size;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_PSEUDOCOLOR;
fix->xpanstep = 0;
fix->ypanstep = 0;
fix->ywrapstep = 0;
fix->line_length = fb_line_length;
}
static int maxinefb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
{
struct maxinefb_par par;
maxinefb_get_par(&par);
maxinefb_encode_fix(fix, &par);
return 0;
}
static int maxinefb_switch(int con, struct fb_info *info)
{
maxinefb_do_fb_set_var(&fb_display[con].var, 1);
info->currcon = con;
return 0;
}
static void maxinefb_set_disp(int con)
{
struct fb_fix_screeninfo fix;
struct display *display;
if (con >= 0)
display = &fb_display[con];
else
display = &disp; /* used during initialization */
maxinefb_get_fix(&fix, con, 0);
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
display->ypanstep = fix.ypanstep;
display->ywrapstep = fix.ywrapstep;
display->line_length = fix.line_length;
display->next_line = fix.line_length;
display->can_soft_blank = 0;
display->inverse = 0;
display->dispsw = &fbcon_cfb8;
}
static struct fb_ops maxinefb_ops = { static struct fb_ops maxinefb_ops = {
owner: THIS_MODULE, owner: THIS_MODULE,
fb_get_fix: maxinefb_get_fix, fb_get_fix: gen_get_fix,
fb_get_var: maxinefb_get_var, fb_get_var: gen_get_var,
fb_set_var: maxinefb_set_var, fb_set_var: gen_set_var,
fb_get_cmap: maxinefb_get_cmap, fb_get_cmap: gen_get_cmap,
fb_set_cmap: maxinefb_set_cmap, fb_set_cmap: gen_set_cmap,
fb_setcolreg: maxinefb_setcolreg,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
}; };
int __init maxinefb_init(void) int __init maxinefb_init(void)
{ {
volatile unsigned char *fboff; volatile unsigned char *fboff;
unsigned long fb_start;
int i; int i;
/* Validate we're on the proper machine type */ /* Validate we're on the proper machine type */
...@@ -332,6 +144,8 @@ int __init maxinefb_init(void) ...@@ -332,6 +144,8 @@ int __init maxinefb_init(void)
for (fboff = fb_start; fboff < fb_start + 0x1ffff; fboff++) for (fboff = fb_start; fboff < fb_start + 0x1ffff; fboff++)
*fboff = 0x0; *fboff = 0x0;
maxinefb_fix.smem_start = fb_start;
/* erase hardware cursor */ /* erase hardware cursor */
for (i = 0; i < 512; i++) { for (i = 0; i < 512; i++) {
maxinefb_ims332_write_register(IMS332_REG_CURSOR_RAM + i, maxinefb_ims332_write_register(IMS332_REG_CURSOR_RAM + i,
...@@ -344,34 +158,26 @@ int __init maxinefb_init(void) ...@@ -344,34 +158,26 @@ int __init maxinefb_init(void)
*/ */
} }
/* Fill in the available video resolution */
maxinefb_defined.xres = 1024;
maxinefb_defined.yres = 768;
maxinefb_defined.xres_virtual = 1024;
maxinefb_defined.yres_virtual = 768;
maxinefb_defined.bits_per_pixel = 8;
/* Let there be consoles... */ /* Let there be consoles... */
strcpy(fb_info.modename, "Maxine onboard graphics 1024x768x8"); strcpy(fb_info.modename, "Maxine onboard graphics 1024x768x8");
/* fb_info.modename: maximum of 39 characters + trailing nullbyte, KM */
fb_info.changevar = NULL; fb_info.changevar = NULL;
fb_info.node = NODEV; fb_info.node = NODEV;
fb_info.fbops = &maxinefb_ops; fb_info.fbops = &maxinefb_ops;
fb_info.screen_base = (char *) fb_start; fb_info.screen_base = (char *) maxinefb_fix.smem_start;
fb_info.var = maxinefb_defined;
fb_info.fix = maxinefb_fix;
fb_info.disp = &disp; fb_info.disp = &disp;
fb_info.currcon = -1; fb_info.currcon = -1;
fb_info.switch_con = &maxinefb_switch; fb_info.switch_con = gen_switch;
fb_info.updatevar = &maxinefb_fb_update_var; fb_info.updatevar = gen_update_var;
fb_info.flags = FBINFO_FLAG_DEFAULT; fb_info.flags = FBINFO_FLAG_DEFAULT;
maxinefb_do_fb_set_var(&maxinefb_defined, 1);
maxinefb_get_var(&disp.var, -1, &fb_info); fb_alloc_cmap(&fb_info.cmap, 256, 0);
maxinefb_set_disp(-1); gen_set_disp(-1, &fb_info);
if (register_framebuffer(&fb_info) < 0) if (register_framebuffer(&fb_info) < 0)
return 1; return 1;
return 0; return 0;
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/* /*
* Permedia2 framebuffer driver. * Permedia2 framebuffer driver.
* Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) * Copyright (c) 1998-2000 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
* Copyright (c) 1999 Jakub Jelinek (jakub@redhat.com) * Copyright (c) 1999 Jakub Jelinek (jakub@redhat.com)
* Based on linux/drivers/video/skeletonfb.c by Geert Uytterhoeven. * Based on linux/drivers/video/skeletonfb.c by Geert Uytterhoeven.
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* $Id: pm2fb.c,v 1.163 1999/02/21 14:06:49 illo Exp $ * $Id: pm2fb.c,v 1.213 2000/09/19 01:03:19 illo Exp $
* --------------------------------------------------------------------------
* History:
* 1999/05/09 added Jim Hague's 'var' kernel option (thanks Jim!)
* 2002/04/23 Jim Hague <jim.hague@acm.org>
* * Integrated Illo's last changes, No changelist available.
* Major items: acceleration support, hardware cursor code
* (not yet enabled).
* * Fixed -vsync, added lowhsync/lowvsync overrides for use with
* XFree GLINT driver.
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
* TODO multiple boards support * TODO multiple boards support
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
...@@ -67,6 +76,9 @@ ...@@ -67,6 +76,9 @@
#define DPRINTK(a,b...) #define DPRINTK(a,b...)
#endif #endif
#define PICOS2KHZ(a) (1000000000UL/(a))
#define KHZ2PICOS(a) (1000000000UL/(a))
/* /*
* The _DEFINITIVE_ memory mapping/unmapping functions. * The _DEFINITIVE_ memory mapping/unmapping functions.
* This is due to the fact that they're changing soooo often... * This is due to the fact that they're changing soooo often...
...@@ -78,9 +90,15 @@ ...@@ -78,9 +90,15 @@
* The _DEFINITIVE_ memory i/o barrier functions. * The _DEFINITIVE_ memory i/o barrier functions.
* This is due to the fact that they're changing soooo often... * This is due to the fact that they're changing soooo often...
*/ */
#ifdef __mc68000__
#define DEFW()
#define DEFR()
#define DEFRW()
#else
#define DEFW() wmb() #define DEFW() wmb()
#define DEFR() rmb() #define DEFR() rmb()
#define DEFRW() mb() #define DEFRW() mb()
#endif
#ifndef MIN #ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b))
...@@ -90,6 +108,10 @@ ...@@ -90,6 +108,10 @@
#define MAX(a,b) ((a)>(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b))
#endif #endif
#define VIDEO_MASK 0x00011e7f /* r/w values for VIDEO_CONTROL */
#define PM2FF_ACCEL (1L<<0)
struct pm2fb_par { struct pm2fb_par {
u32 pixclock; /* pixclock in KHz */ u32 pixclock; /* pixclock in KHz */
u32 width; /* width of virtual screen */ u32 width; /* width of virtual screen */
...@@ -106,12 +128,17 @@ struct pm2fb_par { ...@@ -106,12 +128,17 @@ struct pm2fb_par {
u32 base; /* screen base (xoffset+yoffset) */ u32 base; /* screen base (xoffset+yoffset) */
u32 depth; /* screen depth (8, 16, 24 or 32) */ u32 depth; /* screen depth (8, 16, 24 or 32) */
u32 video; /* video control (hsync,vsync) */ u32 video; /* video control (hsync,vsync) */
u32 flags; /* internal flags (PM2FF_xxxx) */
}; };
#define OPTF_OLD_MEM (1L<<0) #define OPTF_OLD_MEM (1L<<0)
#define OPTF_YPAN (1L<<1) #define OPTF_YPAN (1L<<1)
#define OPTF_VIRTUAL (1L<<2) #define OPTF_VIRTUAL (1L<<2)
#define OPTF_USER (1L<<3) #define OPTF_USER (1L<<3)
#define OPTF_USER_VAR (1L<<4)
#define OPTF_LOW_HSYNC (1L<<5)
#define OPTF_LOW_VSYNC (1L<<6)
static struct { static struct {
char font[40]; char font[40];
u32 flags; u32 flags;
...@@ -126,70 +153,76 @@ static struct { ...@@ -126,70 +153,76 @@ static struct {
static char curblink __initdata = 1; static char curblink __initdata = 1;
static struct { static struct fb_var_screeninfo user_var __initdata={0,};
#define DEFAULT_USER_MODE 0
static const struct {
char name[16]; char name[16];
struct pm2fb_par par; struct pm2fb_par par;
} user_mode[] __initdata = { } user_mode[] __initdata = {
{"640x480-60", {"640x480-60",
{25174,640,480,4,28,40,199,9,11,45,524,80,0,8,121}}, {25174,640,480,4,28,40,199,9,11,45,524,80,0,8,121,PM2FF_ACCEL}},
{"640x480-72", {"640x480-72",
{31199,640,480,6,16,48,207,8,10,39,518,80,0,8,121}}, {31199,640,480,6,16,48,207,8,10,39,518,80,0,8,121,PM2FF_ACCEL}},
{"640x480-75", {"640x480-75",
{31499,640,480,4,20,50,209,0,3,20,499,80,0,8,121}}, {31499,640,480,4,20,50,209,0,3,20,499,80,0,8,121,PM2FF_ACCEL}},
{"640x480-90", {"640x480-90",
{39909,640,480,8,18,48,207,24,38,53,532,80,0,8,121}}, {39909,640,480,8,18,48,207,24,38,53,532,80,0,8,121,PM2FF_ACCEL}},
{"640x480-100", {"640x480-100",
{44899,640,480,8,40,52,211,21,33,51,530,80,0,8,121}}, {44899,640,480,8,40,52,211,21,33,51,530,80,0,8,121,PM2FF_ACCEL}},
{"800x600-56", {"800x600-56",
{35999,800,600,6,24,56,255,0,2,25,624,100,0,8,41}}, {35999,800,600,6,24,56,255,0,2,25,624,100,0,8,41,PM2FF_ACCEL}},
{"800x600-60", {"800x600-60",
{40000,800,600,10,42,64,263,0,4,28,627,100,0,8,41}}, {40000,800,600,10,42,64,263,0,4,28,627,100,0,8,41,PM2FF_ACCEL}},
{"800x600-70", {"800x600-70",
{44899,800,600,6,42,52,251,8,20,36,635,100,0,8,105}}, {44899,800,600,6,42,52,251,8,20,36,635,100,0,8,105,PM2FF_ACCEL}},
{"800x600-72", {"800x600-72",
{50000,800,600,14,44,60,259,36,42,66,665,100,0,8,41}}, {50000,800,600,14,44,60,259,36,42,66,665,100,0,8,41,PM2FF_ACCEL}},
{"800x600-75", {"800x600-75",
{49497,800,600,4,24,64,263,0,3,25,624,100,0,8,41}}, {49497,800,600,4,24,64,263,0,3,25,624,100,0,8,41,PM2FF_ACCEL}},
{"800x600-90", {"800x600-90",
{56637,800,600,2,18,48,247,7,18,35,634,100,0,8,41}}, {56637,800,600,2,18,48,247,7,18,35,634,100,0,8,41,PM2FF_ACCEL}},
{"800x600-100", {"800x600-100",
{67499,800,600,0,16,70,269,6,10,25,624,100,0,8,41}}, {67499,800,600,0,16,70,269,6,10,25,624,100,0,8,41,PM2FF_ACCEL}},
{"1024x768-60", {"1024x768-60",
{64998,1024,768,6,40,80,335,2,8,38,805,128,0,8,121}}, {64998,1024,768,6,40,80,335,2,8,38,805,128,0,8,121,PM2FF_ACCEL}},
{"1024x768-70", {"1024x768-70",
{74996,1024,768,6,40,76,331,2,8,38,805,128,0,8,121}}, {74996,1024,768,6,40,76,331,2,8,38,805,128,0,8,121,PM2FF_ACCEL}},
{"1024x768-72", {"1024x768-72",
{74996,1024,768,6,40,66,321,2,8,38,805,128,0,8,121}}, {74996,1024,768,6,40,66,321,2,8,38,805,128,0,8,121,PM2FF_ACCEL}},
{"1024x768-75", {"1024x768-75",
{78932,1024,768,4,28,72,327,0,3,32,799,128,0,8,41}}, {78932,1024,768,4,28,72,327,0,3,32,799,128,0,8,41,PM2FF_ACCEL}},
{"1024x768-90", {"1024x768-90",
{100000,1024,768,0,24,72,327,20,35,77,844,128,0,8,121}}, {100000,1024,768,0,24,72,327,20,35,77,844,128,0,8,121,PM2FF_ACCEL}},
{"1024x768-100", {"1024x768-100",
{109998,1024,768,0,22,92,347,0,7,24,791,128,0,8,121}}, {109998,1024,768,0,22,92,347,0,7,24,791,128,0,8,121,PM2FF_ACCEL}},
{"1024x768-illo", {"1024x768-illo",
{120322,1024,768,12,48,120,375,3,7,32,799,128,0,8,41}}, {120336,1024,768,12,48,120,375,3,7,32,799,128,0,8,41,PM2FF_ACCEL}},
{"1152x864-60", {"1152x864-60",
{80000,1152,864,16,44,76,363,5,10,52,915,144,0,8,41}}, {80000,1152,864,16,44,76,363,5,10,52,915,144,0,8,41,PM2FF_ACCEL}},
{"1152x864-70", {"1152x864-70",
{100000,1152,864,10,48,90,377,12,23,81,944,144,0,8,41}}, {100000,1152,864,10,48,90,377,12,23,81,944,144,0,8,41,PM2FF_ACCEL}},
{"1152x864-75", {"1152x864-75",
{109998,1152,864,6,42,78,365,44,52,138,1001,144,0,8,41}}, {109998,1152,864,6,42,78,365,44,52,138,1001,144,0,8,41,PM2FF_ACCEL}},
{"1152x864-80", {"1152x864-80",
{109998,1152,864,4,32,72,359,29,36,94,957,144,0,8,41}}, {109998,1152,864,4,32,72,359,29,36,94,957,144,0,8,41,PM2FF_ACCEL}},
{"1152x900-66-sun",
{92940,1152,900,16,80,176,751,1,5,37,936,288,0,16,121,PM2FF_ACCEL}},
{"1280x1024-60", {"1280x1024-60",
{107991,1280,1024,12,40,102,421,0,3,42,1065,160,0,8,41}}, {107991,1280,1024,12,40,102,421,0,3,42,1065,160,0,8,41,PM2FF_ACCEL}},
{"1280x1024-70", {"1280x1024-70",
{125992,1280,1024,20,48,102,421,0,5,42,1065,160,0,8,41}}, {125992,1280,1024,20,48,102,421,0,5,42,1065,160,0,8,41,PM2FF_ACCEL}},
{"1280x1024-74", {"1280x1024-74",
{134989,1280,1024,8,44,108,427,0,29,40,1063,160,0,8,41}}, {134989,1280,1024,8,44,108,427,0,29,40,1063,160,0,8,41,PM2FF_ACCEL}},
{"1280x1024-75", {"1280x1024-75",
{134989,1280,1024,4,40,102,421,0,3,42,1065,160,0,8,41}}, {134989,1280,1024,4,40,102,421,0,3,42,1065,160,0,8,41,PM2FF_ACCEL}},
{"1600x1200-60", {"1600x1200-60",
{155981,1600,1200,8,48,112,511,9,17,70,1269,200,0,8,121}}, {155981,1600,1200,8,48,112,511,9,17,70,1269,200,0,8,121,PM2FF_ACCEL}},
{"1600x1200-66", {"1600x1200-66",
{171998,1600,1200,10,44,120,519,2,5,53,1252,200,0,8,121}}, {171998,1600,1200,10,44,120,519,2,5,53,1252,200,0,8,121,PM2FF_ACCEL}},
{"1600x1200-76", {"1600x1200-76",
{197980,1600,1200,10,44,120,519,2,7,50,1249,200,0,8,121}}, {197980,1600,1200,10,44,120,519,2,7,50,1249,200,0,8,121,PM2FF_ACCEL}},
{"\0", }, {"\0", },
}; };
...@@ -225,7 +258,7 @@ static struct pm2fb_info { ...@@ -225,7 +258,7 @@ static struct pm2fb_info {
struct fb_info_gen gen; struct fb_info_gen gen;
int board; /* Permedia2 board index (see int board; /* Permedia2 board index (see
board_table[] below) */ board_table[] below) */
pm2type_t type; pm2type_t type; /* Permedia2 board type */
struct { struct {
unsigned long fb_base; /* physical framebuffer memory base */ unsigned long fb_base; /* physical framebuffer memory base */
u32 fb_size; /* framebuffer memory size */ u32 fb_size; /* framebuffer memory size */
...@@ -248,6 +281,7 @@ static struct pm2fb_info { ...@@ -248,6 +281,7 @@ static struct pm2fb_info {
} board_par; } board_par;
struct pm2fb_par current_par; /* displayed screen */ struct pm2fb_par current_par; /* displayed screen */
int current_par_valid; int current_par_valid;
int is_blank;
u32 memclock; /* memclock (set by the per-board u32 memclock; /* memclock (set by the per-board
init routine) */ init routine) */
struct display disp; struct display disp;
...@@ -360,9 +394,6 @@ static void pm2fb_set_par(const void* par, struct fb_info_gen* info); ...@@ -360,9 +394,6 @@ static void pm2fb_set_par(const void* par, struct fb_info_gen* info);
static int pm2fb_getcolreg(unsigned regno, static int pm2fb_getcolreg(unsigned regno,
unsigned* red, unsigned* green, unsigned* blue, unsigned* red, unsigned* green, unsigned* blue,
unsigned* transp, struct fb_info* info); unsigned* transp, struct fb_info* info);
static int pm2fb_setcolreg(unsigned regno,
unsigned red, unsigned green, unsigned blue,
unsigned transp, struct fb_info* info);
static int pm2fb_blank(int blank_mode, struct fb_info_gen* info); static int pm2fb_blank(int blank_mode, struct fb_info_gen* info);
static int pm2fb_pan_display(const struct fb_var_screeninfo* var, static int pm2fb_pan_display(const struct fb_var_screeninfo* var,
struct fb_info_gen* info); struct fb_info_gen* info);
...@@ -376,15 +407,20 @@ static struct fbgen_hwswitch pm2fb_hwswitch={ ...@@ -376,15 +407,20 @@ static struct fbgen_hwswitch pm2fb_hwswitch={
pm2fb_blank, pm2fb_set_disp pm2fb_blank, pm2fb_set_disp
}; };
static int pm2fb_setcolreg(unsigned regno,
unsigned red, unsigned green, unsigned blue,
unsigned transp, struct fb_info* info);
static struct fb_ops pm2fb_ops={ static struct fb_ops pm2fb_ops={
owner: THIS_MODULE, owner: THIS_MODULE,
fb_get_fix: fbgen_get_fix, fb_get_fix: fbgen_get_fix,
fb_get_var: fbgen_get_var, fb_get_var: fbgen_get_var,
fb_set_var: fbgen_set_var, fb_set_var: fbgen_set_var,
fb_get_cmap: fbgen_get_cmap, fb_get_cmap: fbgen_get_cmap,
fb_set_cmap: gen_set_cmap, fb_set_cmap: fbgen_set_cmap,
fb_setcolreg: pm2fb_setcolreg,
fb_pan_display: fbgen_pan_display, fb_pan_display: fbgen_pan_display,
fb_setcolreg: pm2fb_setcolreg,
fb_blank: fbgen_blank, fb_blank: fbgen_blank,
}; };
...@@ -394,12 +430,12 @@ static struct fb_ops pm2fb_ops={ ...@@ -394,12 +430,12 @@ static struct fb_ops pm2fb_ops={
inline static u32 RD32(unsigned char* base, s32 off) { inline static u32 RD32(unsigned char* base, s32 off) {
return readl(base+off); return fb_readl(base+off);
} }
inline static void WR32(unsigned char* base, s32 off, u32 v) { inline static void WR32(unsigned char* base, s32 off, u32 v) {
writel(v, base+off); fb_writel(v, base+off);
} }
inline static u32 pm2_RD(struct pm2fb_info* p, s32 off) { inline static u32 pm2_RD(struct pm2fb_info* p, s32 off) {
...@@ -520,7 +556,7 @@ static u32 from3264(u32 timing, int bpp, int is64) { ...@@ -520,7 +556,7 @@ static u32 from3264(u32 timing, int bpp, int is64) {
} }
static void pm2_mnp(u32 clk, unsigned char* mm, unsigned char* nn, static void pm2_mnp(u32 clk, unsigned char* mm, unsigned char* nn,
unsigned char* pp) { unsigned char* pp) {
unsigned char m; unsigned char m;
unsigned char n; unsigned char n;
unsigned char p; unsigned char p;
...@@ -608,7 +644,7 @@ static void pm2_set_pixclock(struct pm2fb_info* info, u32 clk) { ...@@ -608,7 +644,7 @@ static void pm2_set_pixclock(struct pm2fb_info* info, u32 clk) {
switch (info->type) { switch (info->type) {
case PM2_TYPE_PERMEDIA2: case PM2_TYPE_PERMEDIA2:
pm2_mnp(clk, &m, &n, &p); pm2_mnp(clk, &m, &n, &p);
WAIT_FIFO(info, 10); WAIT_FIFO(info, 8);
pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 0); pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 0);
DEFW(); DEFW();
pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A1, m); pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A1, m);
...@@ -618,13 +654,16 @@ static void pm2_set_pixclock(struct pm2fb_info* info, u32 clk) { ...@@ -618,13 +654,16 @@ static void pm2_set_pixclock(struct pm2fb_info* info, u32 clk) {
DEFW(); DEFW();
pm2_RDAC_RD(info, PM2I_RD_PIXEL_CLOCK_STATUS); pm2_RDAC_RD(info, PM2I_RD_PIXEL_CLOCK_STATUS);
DEFR(); DEFR();
for (i=256; i && for (i=256;
!(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--); i && !(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED);
i--)
;
break; break;
case PM2_TYPE_PERMEDIA2V: case PM2_TYPE_PERMEDIA2V:
pm2v_mnp(clk/2, &m, &n, &p); pm2v_mnp(clk/2, &m, &n, &p);
WAIT_FIFO(info, 8); WAIT_FIFO(info, 8);
pm2_WR(info, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CLK0_PRESCALE >> 8); pm2_WR(info, PM2VR_RD_INDEX_HIGH,
PM2VI_RD_CLK0_PRESCALE >> 8);
pm2v_RDAC_WR(info, PM2VI_RD_CLK0_PRESCALE, m); pm2v_RDAC_WR(info, PM2VI_RD_CLK0_PRESCALE, m);
pm2v_RDAC_WR(info, PM2VI_RD_CLK0_FEEDBACK, n); pm2v_RDAC_WR(info, PM2VI_RD_CLK0_FEEDBACK, n);
pm2v_RDAC_WR(info, PM2VI_RD_CLK0_POSTSCALE, p); pm2v_RDAC_WR(info, PM2VI_RD_CLK0_POSTSCALE, p);
...@@ -662,7 +701,7 @@ static void set_color(struct pm2fb_info* p, unsigned char regno, ...@@ -662,7 +701,7 @@ static void set_color(struct pm2fb_info* p, unsigned char regno,
static void set_aperture(struct pm2fb_info* i, struct pm2fb_par* p) { static void set_aperture(struct pm2fb_info* i, struct pm2fb_par* p) {
WAIT_FIFO(i, 2); WAIT_FIFO(i, 4);
#ifdef __LITTLE_ENDIAN #ifdef __LITTLE_ENDIAN
pm2_WR(i, PM2R_APERTURE_ONE, 0); pm2_WR(i, PM2R_APERTURE_ONE, 0);
pm2_WR(i, PM2R_APERTURE_TWO, 0); pm2_WR(i, PM2R_APERTURE_TWO, 0);
...@@ -685,13 +724,113 @@ static void set_aperture(struct pm2fb_info* i, struct pm2fb_par* p) { ...@@ -685,13 +724,113 @@ static void set_aperture(struct pm2fb_info* i, struct pm2fb_par* p) {
#endif #endif
} }
static void set_video(struct pm2fb_info* i, u32 video) {
u32 tmp;
u32 vsync;
vsync=video;
/*
* The hardware cursor needs +vsync to recognise vert retrace.
* We may not be using the hardware cursor, but the X Glint
* driver may well. So always set +hsync/+vsync and then set
* the RAMDAC to invert the sync if necessary.
*/
vsync&=~(PM2F_HSYNC_MASK|PM2F_VSYNC_MASK);
vsync|=PM2F_HSYNC_ACT_HIGH|PM2F_VSYNC_ACT_HIGH;
WAIT_FIFO(i, 5);
pm2_WR(i, PM2R_VIDEO_CONTROL, vsync);
switch (i->type) {
case PM2_TYPE_PERMEDIA2:
tmp = PM2F_RD_PALETTE_WIDTH_8;
if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
tmp |= 4; /* invert hsync */
if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
tmp |= 8; /* invert vsync */
pm2_RDAC_WR(i, PM2I_RD_MISC_CONTROL, tmp);
break;
case PM2_TYPE_PERMEDIA2V:
tmp = 0;
if ((video & PM2F_HSYNC_MASK) == PM2F_HSYNC_ACT_LOW)
tmp |= 1; /* invert hsync */
if ((video & PM2F_VSYNC_MASK) == PM2F_VSYNC_ACT_LOW)
tmp |= 4; /* invert vsync */
pm2v_RDAC_WR(i, PM2VI_RD_SYNC_CONTROL, tmp);
pm2v_RDAC_WR(i, PM2VI_RD_MISC_CONTROL, 1);
break;
}
}
static void get_screen(struct pm2fb_info* i, struct pm2fb_par* p) {
u32 clrmode;
u32 readpx;
u32 misc;
memset(p, 0, sizeof(struct pm2fb_par));
p->base=pm2_RD(i, PM2R_SCREEN_BASE);
p->video=pm2_RD(i, PM2R_VIDEO_CONTROL) & VIDEO_MASK;
switch (i->type) {
case PM2_TYPE_PERMEDIA2:
misc=pm2_RDAC_RD(i, PM2I_RD_MISC_CONTROL);
if ( misc & 4 )
/* Hsync is actually low */
p->video |= PM2F_HSYNC_ACT_LOW;
if ( misc & 8 )
/* Vsync is actually low */
p->video |= PM2F_VSYNC_ACT_LOW;
break;
case PM2_TYPE_PERMEDIA2V:
misc=pm2_RDAC_RD(i, PM2VI_RD_SYNC_CONTROL);
if ( misc & 1 )
/* Hsync is actually low */
p->video |= PM2F_HSYNC_ACT_LOW;
if ( misc & 4 )
/* Vsync is actually low */
p->video |= PM2F_VSYNC_ACT_LOW;
break;
}
p->width=pm2_RD(i, PM2R_SCREEN_SIZE) & 0xffff;
p->height=pm2_RD(i, PM2R_SCREEN_SIZE) >> 16;
p->htotal=pm2_RD(i, PM2R_H_TOTAL);
p->hsstart=pm2_RD(i, PM2R_HS_START);
p->hsend=pm2_RD(i, PM2R_HS_END);
p->hbend=pm2_RD(i, PM2R_HB_END);
p->vtotal=pm2_RD(i, PM2R_V_TOTAL);
p->vsstart=pm2_RD(i, PM2R_VS_START);
p->vsend=pm2_RD(i, PM2R_VS_END);
p->vbend=pm2_RD(i, PM2R_VB_END);
p->stride=pm2_RD(i, PM2R_SCREEN_STRIDE);
clrmode=pm2_RDAC_RD(i, PM2I_RD_COLOR_MODE);
readpx=pm2_RD(i, PM2R_FB_READ_PIXEL);
if (clrmode & PM2F_RD_GUI_ACTIVE) {
clrmode &= ~(PM2F_RD_COLOR_MODE_RGB|PM2F_RD_GUI_ACTIVE);
if (clrmode==0 && readpx==0)
p->depth=8;
else if (clrmode==(PM2F_RD_TRUECOLOR|0x06) && readpx==1)
p->depth=16;
else if (clrmode==(PM2F_RD_TRUECOLOR|0x08) && readpx==2)
p->depth=32;
else if (clrmode==(PM2F_RD_TRUECOLOR|0x09) && readpx==4)
p->depth=24;
}
/*
* Somehow I have to manage this unretrievable fields.
* To say the truth, 'flags' field ought to be somewhere else.
*/
if (i->current_par_valid) {
p->pixclock=i->current_par.pixclock;
p->flags=i->current_par.flags;
}
}
static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) { static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) {
u32 clrmode=0; u32 clrmode=PM2F_RD_COLOR_MODE_RGB;
u32 txtmap=0; u32 txtmap=0;
u32 pixsize=0; u32 pixsize=0;
u32 clrformat=0; u32 clrformat=0;
u32 xres; u32 xres;
u32 video, tmp;
if (i->type == PM2_TYPE_PERMEDIA2V) { if (i->type == PM2_TYPE_PERMEDIA2V) {
WAIT_FIFO(i, 1); WAIT_FIFO(i, 1);
...@@ -700,7 +839,7 @@ static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) { ...@@ -700,7 +839,7 @@ static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) {
xres=(p->width+31)&~31; xres=(p->width+31)&~31;
set_aperture(i, p); set_aperture(i, p);
DEFRW(); DEFRW();
WAIT_FIFO(i, 27); WAIT_FIFO(i, 19);
pm2_RDAC_WR(i, PM2I_RD_COLOR_KEY_CONTROL, p->depth==8?0: pm2_RDAC_WR(i, PM2I_RD_COLOR_KEY_CONTROL, p->depth==8?0:
PM2F_COLOR_KEY_TEST_OFF); PM2F_COLOR_KEY_TEST_OFF);
switch (p->depth) { switch (p->depth) {
...@@ -710,28 +849,29 @@ static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) { ...@@ -710,28 +849,29 @@ static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) {
break; break;
case 16: case 16:
pm2_WR(i, PM2R_FB_READ_PIXEL, 1); pm2_WR(i, PM2R_FB_READ_PIXEL, 1);
clrmode=PM2F_RD_TRUECOLOR|0x06; clrmode|=PM2F_RD_TRUECOLOR|0x06;
txtmap=PM2F_TEXTEL_SIZE_16; txtmap=PM2F_TEXTEL_SIZE_16;
pixsize=1; pixsize=1;
clrformat=0x70; clrformat=0x70;
break; break;
case 32: case 32:
pm2_WR(i, PM2R_FB_READ_PIXEL, 2); pm2_WR(i, PM2R_FB_READ_PIXEL, 2);
clrmode=PM2F_RD_TRUECOLOR|0x08; clrmode|=PM2F_RD_TRUECOLOR|0x08;
txtmap=PM2F_TEXTEL_SIZE_32; txtmap=PM2F_TEXTEL_SIZE_32;
pixsize=2; pixsize=2;
clrformat=0x20; clrformat=0x20;
break; break;
case 24: case 24:
pm2_WR(i, PM2R_FB_READ_PIXEL, 4); pm2_WR(i, PM2R_FB_READ_PIXEL, 4);
clrmode=PM2F_RD_TRUECOLOR|0x09; clrmode|=PM2F_RD_TRUECOLOR|0x09;
#ifndef PM2FB_BE_APERTURE
clrmode&=~PM2F_RD_COLOR_MODE_RGB;
#endif
txtmap=PM2F_TEXTEL_SIZE_24; txtmap=PM2F_TEXTEL_SIZE_24;
pixsize=4; pixsize=4;
clrformat=0x20; clrformat=0x20;
break; break;
} }
pm2_WR(i, PM2R_SCREEN_SIZE, (p->height<<16)|p->width);
pm2_WR(i, PM2R_SCISSOR_MODE, PM2F_SCREEN_SCISSOR_ENABLE);
pm2_WR(i, PM2R_FB_WRITE_MODE, PM2F_FB_WRITE_ENABLE); pm2_WR(i, PM2R_FB_WRITE_MODE, PM2F_FB_WRITE_ENABLE);
pm2_WR(i, PM2R_FB_READ_MODE, partprod(xres)); pm2_WR(i, PM2R_FB_READ_MODE, partprod(xres));
pm2_WR(i, PM2R_LB_READ_MODE, partprod(xres)); pm2_WR(i, PM2R_LB_READ_MODE, partprod(xres));
...@@ -747,36 +887,34 @@ static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) { ...@@ -747,36 +887,34 @@ static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) {
pm2_WR(i, PM2R_VB_END, p->vbend); pm2_WR(i, PM2R_VB_END, p->vbend);
pm2_WR(i, PM2R_SCREEN_STRIDE, p->stride); pm2_WR(i, PM2R_SCREEN_STRIDE, p->stride);
DEFW(); DEFW();
pm2_WR(i, PM2R_WINDOW_ORIGIN, 0);
pm2_WR(i, PM2R_SCREEN_SIZE, (p->height<<16)|p->width);
pm2_WR(i, PM2R_SCISSOR_MODE, PM2F_SCREEN_SCISSOR_ENABLE);
DEFW();
pm2_WR(i, PM2R_SCREEN_BASE, p->base); pm2_WR(i, PM2R_SCREEN_BASE, p->base);
/* HW cursor needs /VSYNC for recognizing vert retrace */ DEFW();
video=p->video & ~(PM2F_HSYNC_ACT_LOW|PM2F_VSYNC_ACT_LOW); set_video(i, p->video);
video|=PM2F_HSYNC_ACT_HIGH|PM2F_VSYNC_ACT_HIGH; WAIT_FIFO(i, 4);
switch (i->type) { switch (i->type) {
case PM2_TYPE_PERMEDIA2: case PM2_TYPE_PERMEDIA2:
tmp = PM2F_RD_PALETTE_WIDTH_8; pm2_RDAC_WR(i, PM2I_RD_COLOR_MODE, PM2F_RD_COLOR_MODE_RGB|
pm2_RDAC_WR(i, PM2I_RD_COLOR_MODE, PM2F_RD_COLOR_MODE_RGB| PM2F_RD_GUI_ACTIVE|clrmode);
PM2F_RD_GUI_ACTIVE|clrmode); break;
if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW) case PM2_TYPE_PERMEDIA2V:
tmp |= 4; /* invert hsync */ pm2v_RDAC_WR(i, PM2VI_RD_PIXEL_SIZE, pixsize);
if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW) pm2v_RDAC_WR(i, PM2VI_RD_COLOR_FORMAT, clrformat);
tmp |= 8; /* invert vsync */ break;
pm2_RDAC_WR(i, PM2I_RD_MISC_CONTROL, tmp);
break;
case PM2_TYPE_PERMEDIA2V:
tmp = 0;
pm2v_RDAC_WR(i, PM2VI_RD_PIXEL_SIZE, pixsize);
pm2v_RDAC_WR(i, PM2VI_RD_COLOR_FORMAT, clrformat);
if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW)
tmp |= 1; /* invert hsync */
if ((p->video & PM2F_HSYNC_ACT_LOW) == PM2F_HSYNC_ACT_LOW)
tmp |= 4; /* invert vsync */
pm2v_RDAC_WR(i, PM2VI_RD_SYNC_CONTROL, tmp);
pm2v_RDAC_WR(i, PM2VI_RD_MISC_CONTROL, 1);
break;
} }
pm2_WR(i, PM2R_VIDEO_CONTROL, video);
pm2_set_pixclock(i, p->pixclock); pm2_set_pixclock(i, p->pixclock);
}; }
static int screen_is_valid(struct pm2fb_info* i) {
struct pm2fb_par actual;
get_screen(i, &actual);
return i->current_par_valid &&
!memcmp(&actual, &i->current_par, sizeof(struct pm2fb_par));
}
/* /*
* copy with packed pixels (8/16bpp only). * copy with packed pixels (8/16bpp only).
...@@ -788,11 +926,10 @@ static void pm2fb_pp_copy(struct pm2fb_info* i, s32 xsrc, s32 ysrc, ...@@ -788,11 +926,10 @@ static void pm2fb_pp_copy(struct pm2fb_info* i, s32 xsrc, s32 ysrc,
if (!w || !h) if (!w || !h)
return; return;
WAIT_FIFO(i, 7); WAIT_FIFO(i, 6);
pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE| pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE|
PM2F_CONFIG_FB_PACKED_DATA| PM2F_CONFIG_FB_PACKED_DATA|
PM2F_CONFIG_FB_READ_SOURCE_ENABLE); PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0);
pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16| pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16|
((xsrc-x)&0xfff)); ((xsrc-x)&0xfff));
offset=(x&0x3)-(xsrc&0x3); offset=(x&0x3)-(xsrc&0x3);
...@@ -816,10 +953,9 @@ static void pm2fb_block_op(struct pm2fb_info* i, int copy, ...@@ -816,10 +953,9 @@ static void pm2fb_block_op(struct pm2fb_info* i, int copy,
if (!w || !h) if (!w || !h)
return; return;
WAIT_FIFO(i, 6); WAIT_FIFO(i, 5);
pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE| pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE|
PM2F_CONFIG_FB_READ_SOURCE_ENABLE); (copy?PM2F_CONFIG_FB_READ_SOURCE_ENABLE:0));
pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0);
if (copy) if (copy)
pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16| pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16|
((xsrc-x)&0xfff)); ((xsrc-x)&0xfff));
...@@ -839,37 +975,24 @@ static void pm2fb_block_op(struct pm2fb_info* i, int copy, ...@@ -839,37 +975,24 @@ static void pm2fb_block_op(struct pm2fb_info* i, int copy,
* Begin of generic initialization functions * Begin of generic initialization functions
***************************************************************************/ ***************************************************************************/
static void pm2fb_reset(struct pm2fb_info* p) { static void reset_units(struct pm2fb_info* p) {
if (p->type == PM2_TYPE_PERMEDIA2V) WAIT_FIFO(p, 52);
pm2_WR(p, PM2VR_RD_INDEX_HIGH, 0);
pm2_WR(p, PM2R_RESET_STATUS, 0);
DEFRW();
while (pm2_RD(p, PM2R_RESET_STATUS)&PM2F_BEING_RESET);
DEFRW();
#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
DPRINTK("FIFO disconnect enabled\n");
pm2_WR(p, PM2R_FIFO_DISCON, 1);
DEFRW();
#endif
if (board_table[p->board].init)
board_table[p->board].init(p);
WAIT_FIFO(p, 48);
pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG)& pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG)&
~(PM2F_VGA_ENABLE|PM2F_VGA_FIXED)); ~(PM2F_VGA_ENABLE|PM2F_VGA_FIXED));
pm2_WR(p, PM2R_BYPASS_WRITE_MASK, ~(0L)); pm2_WR(p, PM2R_BYPASS_WRITE_MASK, ~(0L));
pm2_WR(p, PM2R_FRAMEBUFFER_WRITE_MASK, ~(0L)); pm2_WR(p, PM2R_FRAMEBUFFER_WRITE_MASK, ~(0L));
pm2_WR(p, PM2R_FIFO_CONTROL, 0); pm2_WR(p, PM2R_FIFO_CONTROL, 0);
pm2_WR(p, PM2R_FILTER_MODE, PM2F_SYNCHRONIZATION);
pm2_WR(p, PM2R_APERTURE_ONE, 0); pm2_WR(p, PM2R_APERTURE_ONE, 0);
pm2_WR(p, PM2R_APERTURE_TWO, 0); pm2_WR(p, PM2R_APERTURE_TWO, 0);
pm2_WR(p, PM2R_RASTERIZER_MODE, 0);
pm2_WR(p, PM2R_DELTA_MODE, PM2F_DELTA_ORDER_RGB);
pm2_WR(p, PM2R_LB_READ_FORMAT, 0); pm2_WR(p, PM2R_LB_READ_FORMAT, 0);
pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0); pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0);
pm2_WR(p, PM2R_LB_READ_MODE, 0); pm2_WR(p, PM2R_LB_READ_MODE, 0);
pm2_WR(p, PM2R_LB_SOURCE_OFFSET, 0); pm2_WR(p, PM2R_LB_SOURCE_OFFSET, 0);
pm2_WR(p, PM2R_FB_SOURCE_OFFSET, 0); pm2_WR(p, PM2R_FB_SOURCE_OFFSET, 0);
pm2_WR(p, PM2R_FB_PIXEL_OFFSET, 0); pm2_WR(p, PM2R_FB_PIXEL_OFFSET, 0);
pm2_WR(p, PM2R_WINDOW_ORIGIN, 0);
pm2_WR(p, PM2R_FB_WINDOW_BASE, 0); pm2_WR(p, PM2R_FB_WINDOW_BASE, 0);
pm2_WR(p, PM2R_LB_WINDOW_BASE, 0); pm2_WR(p, PM2R_LB_WINDOW_BASE, 0);
pm2_WR(p, PM2R_FB_SOFT_WRITE_MASK, ~(0L)); pm2_WR(p, PM2R_FB_SOFT_WRITE_MASK, ~(0L));
...@@ -890,6 +1013,7 @@ static void pm2fb_reset(struct pm2fb_info* p) { ...@@ -890,6 +1013,7 @@ static void pm2fb_reset(struct pm2fb_info* p) {
pm2_WR(p, PM2R_LOGICAL_OP_MODE, 0); pm2_WR(p, PM2R_LOGICAL_OP_MODE, 0);
pm2_WR(p, PM2R_STATISTICS_MODE, 0); pm2_WR(p, PM2R_STATISTICS_MODE, 0);
pm2_WR(p, PM2R_SCISSOR_MODE, 0); pm2_WR(p, PM2R_SCISSOR_MODE, 0);
pm2_WR(p, PM2R_FILTER_MODE, PM2F_SYNCHRONIZATION);
switch (p->type) { switch (p->type) {
case PM2_TYPE_PERMEDIA2: case PM2_TYPE_PERMEDIA2:
pm2_RDAC_WR(p, PM2I_RD_MODE_CONTROL, 0); /* no overlay */ pm2_RDAC_WR(p, PM2I_RD_MODE_CONTROL, 0); /* no overlay */
...@@ -905,12 +1029,30 @@ static void pm2fb_reset(struct pm2fb_info* p) { ...@@ -905,12 +1029,30 @@ static void pm2fb_reset(struct pm2fb_info* p) {
pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0); pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0);
pm2_RDAC_WR(p, PM2I_RD_GREEN_KEY, 0); pm2_RDAC_WR(p, PM2I_RD_GREEN_KEY, 0);
pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0); pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0);
}
static void pm2fb_reset(struct pm2fb_info* p) {
if (p->type == PM2_TYPE_PERMEDIA2V)
pm2_WR(p, PM2VR_RD_INDEX_HIGH, 0);
pm2_WR(p, PM2R_RESET_STATUS, 0);
DEFRW();
while (pm2_RD(p, PM2R_RESET_STATUS)&PM2F_BEING_RESET);
DEFRW();
#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
DPRINTK("FIFO disconnect enabled\n");
pm2_WR(p, PM2R_FIFO_DISCON, 1);
DEFRW();
#endif
if (board_table[p->board].init)
board_table[p->board].init(p);
reset_units(p);
clear_palette(p); clear_palette(p);
if (p->memclock) if (p->memclock)
pm2_set_memclock(p, p->memclock); pm2_set_memclock(p, p->memclock);
} }
static int __init pm2fb_conf(struct pm2fb_info* p){ static int __init pm2fb_conf(struct pm2fb_info* p) {
for (p->board=0; board_table[p->board].detect && for (p->board=0; board_table[p->board].detect &&
!(board_table[p->board].detect(p)); p->board++); !(board_table[p->board].detect(p)); p->board++);
...@@ -921,9 +1063,9 @@ static int __init pm2fb_conf(struct pm2fb_info* p){ ...@@ -921,9 +1063,9 @@ static int __init pm2fb_conf(struct pm2fb_info* p){
DPRINTK("found board: %s\n", board_table[p->board].name); DPRINTK("found board: %s\n", board_table[p->board].name);
p->regions.p_fb=p->regions.fb_base; p->regions.p_fb=p->regions.fb_base;
if (!request_mem_region(p->regions.p_fb, p->regions.fb_size, if (!request_mem_region((unsigned long )p->regions.p_fb,
"pm2fb")) { p->regions.fb_size, "pm2fb")) {
printk (KERN_ERR "pm2fb: cannot reserve fb memory, abort\n"); printk (KERN_ERR "pm2fb: cannot reserve fb memory, abort.\n");
return 0; return 0;
} }
p->regions.v_fb=MMAP(p->regions.p_fb, p->regions.fb_size); p->regions.v_fb=MMAP(p->regions.p_fb, p->regions.fb_size);
...@@ -933,8 +1075,9 @@ static int __init pm2fb_conf(struct pm2fb_info* p){ ...@@ -933,8 +1075,9 @@ static int __init pm2fb_conf(struct pm2fb_info* p){
#else #else
p->regions.p_regs=p->regions.rg_base+PM2_REGS_SIZE; p->regions.p_regs=p->regions.rg_base+PM2_REGS_SIZE;
#endif #endif
if (!request_mem_region(p->regions.p_regs, PM2_REGS_SIZE, "pm2fb")) { if (!request_mem_region((unsigned long )p->regions.p_regs,
printk (KERN_ERR "pm2fb: cannot reserve mmio memory, abort\n"); PM2_REGS_SIZE, "pm2fb")) {
printk (KERN_ERR "pm2fb: cannot reserve mmio memory, abort.\n");
UNMAP(p->regions.v_fb, p->regions.fb_size); UNMAP(p->regions.v_fb, p->regions.fb_size);
return 0; return 0;
} }
...@@ -994,7 +1137,7 @@ static int __init cvppc_detect(struct pm2fb_info* p) { ...@@ -994,7 +1137,7 @@ static int __init cvppc_detect(struct pm2fb_info* p) {
if (!cvppc_PCI_init(&p->board_par.cvppc)) if (!cvppc_PCI_init(&p->board_par.cvppc))
return 0; return 0;
p->type = PM2_TYPE_PERMEDIA2; p->type=PM2_TYPE_PERMEDIA2;
p->regions.fb_base=CVPPC_FB_APERTURE_ONE; p->regions.fb_base=CVPPC_FB_APERTURE_ONE;
p->regions.fb_size=CVPPC_FB_SIZE; p->regions.fb_size=CVPPC_FB_SIZE;
p->regions.rg_base=CVPPC_REGS_REGION; p->regions.rg_base=CVPPC_REGS_REGION;
...@@ -1024,10 +1167,13 @@ struct { ...@@ -1024,10 +1167,13 @@ struct {
char *name; char *name;
pm2type_t type; pm2type_t type;
} pm2pci_cards[] __initdata = { } pm2pci_cards[] __initdata = {
{ PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TVP4020, "Texas Instruments TVP4020", PM2_TYPE_PERMEDIA2 }, { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TVP4020,
{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2, "3dLabs Permedia 2", PM2_TYPE_PERMEDIA2 }, "Texas Instruments TVP4020", PM2_TYPE_PERMEDIA2 },
{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V, "3dLabs Permedia 2v", PM2_TYPE_PERMEDIA2V }, { PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2,
{ 0, 0 } "3dLabs Permedia 2", PM2_TYPE_PERMEDIA2 },
{ PCI_VENDOR_ID_3DLABS, PCI_DEVICE_ID_3DLABS_PERMEDIA2V,
"3dLabs Permedia 2v", PM2_TYPE_PERMEDIA2V },
{ 0, 0 }
}; };
static int __init pm2pci_detect(struct pm2fb_info* p) { static int __init pm2pci_detect(struct pm2fb_info* p) {
...@@ -1072,19 +1218,24 @@ static int __init pm2pci_detect(struct pm2fb_info* p) { ...@@ -1072,19 +1218,24 @@ static int __init pm2pci_detect(struct pm2fb_info* p) {
p->regions.fb_base= pci->dev->resource[1].start; p->regions.fb_base= pci->dev->resource[1].start;
pcp = pci->dev->sysdata; pcp = pci->dev->sysdata;
/* If the user has not asked for a particular mode, lets guess */ /* If the user has not asked for a particular mode, lets guess */
if (pcp->prom_node && !(pm2fb_options.flags & OPTF_USER)) { if (pcp->prom_node &&
!(pm2fb_options.flags & (OPTF_USER|OPTF_USER_VAR))) {
char timing[256], *q, *r; char timing[256], *q, *r;
unsigned long w, h; unsigned long w, h;
int i; int i;
prom_getstring(pcp->prom_node, "timing-numbers", timing, 256); prom_getstring(pcp->prom_node, "timing-numbers", timing, 256);
/* FIXME: Find out what the actual pixclock is and other values as well */ /* FIXME: Find out what the actual pixclock is
* and other values as well */
if (timing[0]) { if (timing[0]) {
w = simple_strtoul(timing, &q, 0); w = simple_strtoul(timing, &q, 0);
h = 0; h = 0;
if (q == timing) w = 0; if (q == timing) w = 0;
if (w) { if (w) {
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
for (r = q; *r && (*r < '0' || *r > '9'); r++); for (r = q;
*r && (*r < '0' || *r > '9');
r++)
;
simple_strtoul(r, &q, 0); simple_strtoul(r, &q, 0);
if (r == q) break; if (r == q) break;
} }
...@@ -1101,7 +1252,9 @@ static int __init pm2pci_detect(struct pm2fb_info* p) { ...@@ -1101,7 +1252,9 @@ static int __init pm2pci_detect(struct pm2fb_info* p) {
(w != user_mode[i].par.width || (w != user_mode[i].par.width ||
h != user_mode[i].par.height); i++); h != user_mode[i].par.height); i++);
if (user_mode[i].name[0]) if (user_mode[i].name[0])
memcpy(&p->current_par, &user_mode[i].par, sizeof(user_mode[i].par)); memcpy(&p->current_par,
&user_mode[i].par,
sizeof(user_mode[i].par));
} }
} }
} }
...@@ -1159,7 +1312,6 @@ static void pm2pci_init(struct pm2fb_info* p) { ...@@ -1159,7 +1312,6 @@ static void pm2pci_init(struct pm2fb_info* p) {
* Console hw acceleration * Console hw acceleration
***************************************************************************/ ***************************************************************************/
static int pm2fb_blank(int blank_mode, struct fb_info_gen* info) { static int pm2fb_blank(int blank_mode, struct fb_info_gen* info) {
struct pm2fb_info* i=(struct pm2fb_info* )info; struct pm2fb_info* i=(struct pm2fb_info* )info;
u32 video; u32 video;
...@@ -1168,6 +1320,7 @@ static int pm2fb_blank(int blank_mode, struct fb_info_gen* info) { ...@@ -1168,6 +1320,7 @@ static int pm2fb_blank(int blank_mode, struct fb_info_gen* info) {
return 1; return 1;
video=i->current_par.video; video=i->current_par.video;
if (blank_mode>0) { if (blank_mode>0) {
i->is_blank=1;
switch (blank_mode-1) { switch (blank_mode-1) {
case VESA_NO_BLANKING: /* FIXME */ case VESA_NO_BLANKING: /* FIXME */
video=video&~(PM2F_VIDEO_ENABLE); video=video&~(PM2F_VIDEO_ENABLE);
...@@ -1187,8 +1340,9 @@ static int pm2fb_blank(int blank_mode, struct fb_info_gen* info) { ...@@ -1187,8 +1340,9 @@ static int pm2fb_blank(int blank_mode, struct fb_info_gen* info) {
break; break;
} }
} }
WAIT_FIFO(i, 1); else
pm2_WR(i, PM2R_VIDEO_CONTROL, video); i->is_blank=0;
set_video(i, video);
return 0; return 0;
} }
...@@ -1321,7 +1475,7 @@ static void pm2fb_clear_margins16(struct vc_data* conp, struct display* p, ...@@ -1321,7 +1475,7 @@ static void pm2fb_clear_margins16(struct vc_data* conp, struct display* p,
u32 sx; u32 sx;
u32 sy; u32 sy;
c = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]; c=((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
c|=c<<16; c|=c<<16;
sx=conp->vc_cols*fontwidth(p); sx=conp->vc_cols*fontwidth(p);
sy=conp->vc_rows*fontheight(p); sy=conp->vc_rows*fontheight(p);
...@@ -1374,26 +1528,15 @@ static void pm2fb_clear24(struct vc_data* conp, struct display* p, ...@@ -1374,26 +1528,15 @@ static void pm2fb_clear24(struct vc_data* conp, struct display* p,
static void pm2fb_clear_margins24(struct vc_data* conp, struct display* p, static void pm2fb_clear_margins24(struct vc_data* conp, struct display* p,
int bottom_only) { int bottom_only) {
struct pm2fb_info* i=(struct pm2fb_info* )p->fb_info; struct pm2fb_info* i=(struct pm2fb_info* )p->fb_info;
u32 c;
u32 sx; u32 sx;
u32 sy; u32 sy;
c=attr_bgcol_ec(p, conp); sx=conp->vc_cols*fontwidth(p);
if ( i->palette[c].red==i->palette[c].green && sy=conp->vc_rows*fontheight(p);
i->palette[c].green==i->palette[c].blue) { if (!bottom_only)
c=((u32 *)p->dispsw_data)[c];
c|=(c&0xff0000)<<8;
sx=conp->vc_cols*fontwidth(p);
sy=conp->vc_rows*fontheight(p);
if (!bottom_only)
pm2fb_block_op(i, 0, 0, 0, sx, 0, (p->var.xres-sx), pm2fb_block_op(i, 0, 0, 0, sx, 0, (p->var.xres-sx),
p->var.yres_virtual, c); p->var.yres_virtual, 0L);
pm2fb_block_op(i, 0, 0, 0, 0, p->var.yoffset+sy, pm2fb_block_op(i, 0, 0, 0, 0, p->var.yoffset+sy, sx, p->var.yres-sy, 0L);
sx, p->var.yres-sy, c);
}
else
fbcon_cfb24_clear_margins(conp, p, bottom_only);
} }
static struct display_switch pm2_cfb24 = { static struct display_switch pm2_cfb24 = {
...@@ -1430,7 +1573,7 @@ static void pm2fb_clear_margins32(struct vc_data* conp, struct display* p, ...@@ -1430,7 +1573,7 @@ static void pm2fb_clear_margins32(struct vc_data* conp, struct display* p,
u32 sx; u32 sx;
u32 sy; u32 sy;
c = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]; c=((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
sx=conp->vc_cols*fontwidth(p); sx=conp->vc_cols*fontwidth(p);
sy=conp->vc_rows*fontheight(p); sy=conp->vc_rows*fontheight(p);
if (!bottom_only) if (!bottom_only)
...@@ -1466,17 +1609,14 @@ static int pm2fb_encode_fix(struct fb_fix_screeninfo* fix, ...@@ -1466,17 +1609,14 @@ static int pm2fb_encode_fix(struct fb_fix_screeninfo* fix,
struct pm2fb_par* p=(struct pm2fb_par* )par; struct pm2fb_par* p=(struct pm2fb_par* )par;
strcpy(fix->id, permedia2_name); strcpy(fix->id, permedia2_name);
fix->smem_start=i->regions.p_fb; fix->smem_start=(unsigned long )i->regions.p_fb;
fix->smem_len=i->regions.fb_size; fix->smem_len=i->regions.fb_size;
fix->mmio_start=i->regions.p_regs; fix->mmio_start=(unsigned long )i->regions.p_regs;
fix->mmio_len=PM2_REGS_SIZE; fix->mmio_len=PM2_REGS_SIZE;
fix->accel=FB_ACCEL_3DLABS_PERMEDIA2; fix->accel=FB_ACCEL_3DLABS_PERMEDIA2;
fix->type=FB_TYPE_PACKED_PIXELS; fix->type=FB_TYPE_PACKED_PIXELS;
fix->visual=p->depth==8?FB_VISUAL_PSEUDOCOLOR:FB_VISUAL_TRUECOLOR; fix->visual=p->depth==8?FB_VISUAL_PSEUDOCOLOR:FB_VISUAL_TRUECOLOR;
if (i->current_par_valid) fix->line_length=p->width*p->depth/8;
fix->line_length=i->current_par.width*(i->current_par.depth/8);
else
fix->line_length=0;
fix->xpanstep=p->depth==24?8:64/p->depth; fix->xpanstep=p->depth==24?8:64/p->depth;
fix->ypanstep=1; fix->ypanstep=1;
fix->ywrapstep=0; fix->ywrapstep=0;
...@@ -1525,11 +1665,13 @@ static int pm2fb_decode_var(const struct fb_var_screeninfo* var, ...@@ -1525,11 +1665,13 @@ static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
int data64; int data64;
memset(&p, 0, sizeof(struct pm2fb_par)); memset(&p, 0, sizeof(struct pm2fb_par));
if (var->accel_flags & FB_ACCELF_TEXT)
p.flags |= PM2FF_ACCEL;
p.width=(var->xres_virtual+7)&~7; p.width=(var->xres_virtual+7)&~7;
p.height=var->yres_virtual; p.height=var->yres_virtual;
p.depth=(var->bits_per_pixel+7)&~7; p.depth=(var->bits_per_pixel+7)&~7;
p.depth=p.depth>32?32:p.depth; p.depth=p.depth>32?32:p.depth;
data64=p.depth>8 || i->type == PM2_TYPE_PERMEDIA2V; data64=p.depth>8 || i->type==PM2_TYPE_PERMEDIA2V;
xres=(var->xres+31)&~31; xres=(var->xres+31)&~31;
if (p.width<xres+var->xoffset) if (p.width<xres+var->xoffset)
p.width=xres+var->xoffset; p.width=xres+var->xoffset;
...@@ -1578,12 +1720,22 @@ static int pm2fb_decode_var(const struct fb_var_screeninfo* var, ...@@ -1578,12 +1720,22 @@ static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
p.base=to3264(var->yoffset*xres+var->xoffset, p.depth, 1); p.base=to3264(var->yoffset*xres+var->xoffset, p.depth, 1);
if (data64) if (data64)
p.video|=PM2F_DATA_64_ENABLE; p.video|=PM2F_DATA_64_ENABLE;
if (var->sync & FB_SYNC_HOR_HIGH_ACT) if (var->sync & FB_SYNC_HOR_HIGH_ACT) {
p.video|=PM2F_HSYNC_ACT_HIGH; if (pm2fb_options.flags & OPTF_LOW_HSYNC) {
DPRINTK("ignoring +hsync, using -hsync.\n");
p.video|=PM2F_HSYNC_ACT_LOW;
} else
p.video|=PM2F_HSYNC_ACT_HIGH;
}
else else
p.video|=PM2F_HSYNC_ACT_LOW; p.video|=PM2F_HSYNC_ACT_LOW;
if (var->sync & FB_SYNC_VERT_HIGH_ACT) if (var->sync & FB_SYNC_VERT_HIGH_ACT) {
p.video|=PM2F_VSYNC_ACT_HIGH; if (pm2fb_options.flags & OPTF_LOW_VSYNC) {
DPRINTK("ignoring +vsync, using -vsync.\n");
p.video|=PM2F_VSYNC_ACT_LOW;
} else
p.video|=PM2F_VSYNC_ACT_HIGH;
}
else else
p.video|=PM2F_VSYNC_ACT_LOW; p.video|=PM2F_VSYNC_ACT_LOW;
if ((var->vmode & FB_VMODE_MASK)==FB_VMODE_INTERLACED) { if ((var->vmode & FB_VMODE_MASK)==FB_VMODE_INTERLACED) {
...@@ -1611,110 +1763,115 @@ static int pm2fb_decode_var(const struct fb_var_screeninfo* var, ...@@ -1611,110 +1763,115 @@ static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
} }
#endif #endif
static int pm2fb_encode_var(struct fb_var_screeninfo* var, static void pm2fb_par2var(struct fb_var_screeninfo* v,
const void* par, struct fb_info_gen* info) { const struct pm2fb_par* p) {
struct pm2fb_par* p=(struct pm2fb_par* )par;
struct fb_var_screeninfo v;
u32 base; u32 base;
memset(&v, 0, sizeof(struct fb_var_screeninfo)); memset(v, 0, sizeof(struct fb_var_screeninfo));
v.xres_virtual=p->width; if (p->flags & PM2FF_ACCEL)
v.yres_virtual=p->height; v->accel_flags |= FB_ACCELF_TEXT;
v.xres=(p->htotal+1)-p->hbend; v->xres_virtual=p->width;
v.yres=(p->vtotal+1)-p->vbend; v->yres_virtual=p->height;
v.right_margin=p->hsstart; v->xres=(p->htotal+1)-p->hbend;
v.hsync_len=p->hsend-p->hsstart; v->yres=(p->vtotal+1)-p->vbend;
v.left_margin=p->hbend-p->hsend; v->right_margin=p->hsstart;
v.lower_margin=p->vsstart+1; v->hsync_len=p->hsend-p->hsstart;
v.vsync_len=p->vsend-v.lower_margin+1; v->left_margin=p->hbend-p->hsend;
v.upper_margin=p->vbend-v.lower_margin-v.vsync_len; v->lower_margin=p->vsstart+1;
v.bits_per_pixel=p->depth; v->vsync_len=p->vsend-v->lower_margin+1;
v->upper_margin=p->vbend-v->lower_margin-v->vsync_len;
v->bits_per_pixel=p->depth;
if (p->video & PM2F_DATA_64_ENABLE) { if (p->video & PM2F_DATA_64_ENABLE) {
v.xres=v.xres<<1; v->xres=v->xres<<1;
v.right_margin=v.right_margin<<1; v->right_margin=v->right_margin<<1;
v.hsync_len=v.hsync_len<<1; v->hsync_len=v->hsync_len<<1;
v.left_margin=v.left_margin<<1; v->left_margin=v->left_margin<<1;
} }
switch (p->depth) { switch (p->depth) {
case 8: case 8:
v.red.length=v.green.length=v.blue.length=8; v->red.length=v->green.length=v->blue.length=8;
v.xres=v.xres<<2; v->xres=v->xres<<2;
v.right_margin=v.right_margin<<2; v->right_margin=v->right_margin<<2;
v.hsync_len=v.hsync_len<<2; v->hsync_len=v->hsync_len<<2;
v.left_margin=v.left_margin<<2; v->left_margin=v->left_margin<<2;
break; break;
case 16: case 16:
v.red.offset=11; v->red.offset=11;
v.red.length=5; v->red.length=5;
v.green.offset=5; v->green.offset=5;
v.green.length=6; v->green.length=6;
v.blue.length=5; v->blue.length=5;
v.xres=v.xres<<1; v->xres=v->xres<<1;
v.right_margin=v.right_margin<<1; v->right_margin=v->right_margin<<1;
v.hsync_len=v.hsync_len<<1; v->hsync_len=v->hsync_len<<1;
v.left_margin=v.left_margin<<1; v->left_margin=v->left_margin<<1;
break; break;
case 32: case 32:
v.transp.offset=24; v->transp.offset=24;
v.red.offset=16; v->red.offset=16;
v.green.offset=8; v->green.offset=8;
v.red.length=v.green.length=v.blue.length= v->red.length=v->green.length=v->blue.length=
v.transp.length=8; v->transp.length=8;
break; break;
case 24: case 24:
v.blue.offset=16; v->blue.offset=16;
v.green.offset=8; v->green.offset=8;
v.red.length=v.green.length=v.blue.length=8; v->red.length=v->green.length=v->blue.length=8;
v.xres=(v.xres<<2)/3; v->xres=(v->xres<<2)/3;
v.right_margin=(v.right_margin<<2)/3; v->right_margin=(v->right_margin<<2)/3;
v.hsync_len=(v.hsync_len<<2)/3; v->hsync_len=(v->hsync_len<<2)/3;
v.left_margin=(v.left_margin<<2)/3; v->left_margin=(v->left_margin<<2)/3;
break; break;
} }
base=from3264(p->base, p->depth, 1); base=from3264(p->base, p->depth, 1);
v.xoffset=base%v.xres; v->xoffset=base%v->xres;
v.yoffset=base/v.xres; v->yoffset=base/v->xres;
v.height=v.width=-1; v->height=v->width=-1;
v.pixclock=KHZ2PICOS(p->pixclock); v->pixclock=KHZ2PICOS(p->pixclock);
if ((p->video & PM2F_HSYNC_MASK)==PM2F_HSYNC_ACT_HIGH) if ((p->video & PM2F_HSYNC_MASK)==PM2F_HSYNC_ACT_HIGH)
v.sync|=FB_SYNC_HOR_HIGH_ACT; v->sync|=FB_SYNC_HOR_HIGH_ACT;
if ((p->video & PM2F_VSYNC_MASK)==PM2F_VSYNC_ACT_HIGH) if ((p->video & PM2F_VSYNC_MASK)==PM2F_VSYNC_ACT_HIGH)
v.sync|=FB_SYNC_VERT_HIGH_ACT; v->sync|=FB_SYNC_VERT_HIGH_ACT;
if (p->video & PM2F_LINE_DOUBLE) if (p->video & PM2F_LINE_DOUBLE)
v.vmode=FB_VMODE_DOUBLE; v->vmode=FB_VMODE_DOUBLE;
*var=v; }
static int pm2fb_encode_var(struct fb_var_screeninfo* var,
const void* par, struct fb_info_gen* info) {
pm2fb_par2var(var, (struct pm2fb_par* )par);
return 0; return 0;
} }
static void set_user_mode(struct pm2fb_info* i) { static void set_user_mode(struct pm2fb_info* i) {
memcpy(&i->current_par, &pm2fb_options.user_mode,
sizeof(i->current_par));
if (pm2fb_options.flags & OPTF_YPAN) { if (pm2fb_options.flags & OPTF_YPAN) {
int h = i->current_par.height;
i->current_par.height=i->regions.fb_size/ i->current_par.height=i->regions.fb_size/
(i->current_par.width*i->current_par.depth/8); (i->current_par.width*i->current_par.depth/8);
i->current_par.height=MIN(i->current_par.height,2047); i->current_par.height=MIN(i->current_par.height,2047);
i->current_par.height=MAX(i->current_par.height,h); i->current_par.height=MAX(i->current_par.height,
pm2fb_options.user_mode.height);
} }
} }
static void pm2fb_get_par(void* par, struct fb_info_gen* info) { static void pm2fb_get_par(void* par, struct fb_info_gen* info) {
struct pm2fb_info* i=(struct pm2fb_info* )info; struct pm2fb_info* i=(struct pm2fb_info* )info;
if (!i->current_par_valid) { if (!i->current_par_valid) {
set_user_mode(i); set_user_mode(i);
pm2fb_reset(i); pm2fb_set_par(&i->current_par, info);
set_screen(i, &i->current_par);
i->current_par_valid=1;
} }
*((struct pm2fb_par* )par)=i->current_par; get_screen(i, (struct pm2fb_par* )par);
} }
static void pm2fb_set_par(const void* par, struct fb_info_gen* info) { static void pm2fb_set_par(const void* par, struct fb_info_gen* info) {
struct pm2fb_info* i=(struct pm2fb_info* )info; struct pm2fb_info* i=(struct pm2fb_info* )info;
struct pm2fb_par* p; struct pm2fb_par* p=(struct pm2fb_par* )par;
p=(struct pm2fb_par* )par; if (screen_is_valid(i)) {
if (i->current_par_valid) {
i->current_par.base=p->base; i->current_par.base=p->base;
if (!memcmp(p, &i->current_par, sizeof(struct pm2fb_par))) { if (!memcmp(p, &i->current_par, sizeof(struct pm2fb_par))) {
WAIT_FIFO(i, 1); WAIT_FIFO(i, 1);
...@@ -1722,12 +1879,16 @@ static void pm2fb_set_par(const void* par, struct fb_info_gen* info) { ...@@ -1722,12 +1879,16 @@ static void pm2fb_set_par(const void* par, struct fb_info_gen* info) {
return; return;
} }
} }
wait_pm2(i);
reset_units(i);
set_screen(i, p); set_screen(i, p);
i->current_par=*p; i->current_par=*p;
i->current_par_valid=1; i->current_par_valid=1;
#ifdef PM2FB_HW_CURSOR #ifdef PM2FB_HW_CURSOR
if (i->cursor) { if (i->cursor) {
pm2v_set_cursor_color(i, cursor_color_map, cursor_color_map, cursor_color_map); pm2v_set_cursor_color(i, cursor_color_map,
cursor_color_map, cursor_color_map);
pm2v_set_cursor_shape(i); pm2v_set_cursor_shape(i);
} }
#endif #endif
...@@ -1801,35 +1962,51 @@ static int pm2fb_setcolreg(unsigned regno, ...@@ -1801,35 +1962,51 @@ static int pm2fb_setcolreg(unsigned regno,
} }
static void pm2fb_set_disp(const void* par, struct display* disp, static void pm2fb_set_disp(const void* par, struct display* disp,
struct fb_info_gen* info) { struct fb_info_gen* info) {
struct pm2fb_info* i=(struct pm2fb_info* )info; struct pm2fb_info* i=(struct pm2fb_info* )info;
struct pm2fb_par* p=(struct pm2fb_par* )par;
unsigned long flags; unsigned long flags;
unsigned long depth;
save_flags(flags); save_flags(flags);
cli(); cli();
i->gen.info.screen_base = i->regions.v_fb; #ifdef __alpha__
switch (depth=((struct pm2fb_par* )par)->depth) { disp->screen_base=i->regions.v_fb + dense_mem(i->regions.v_fb);
#else
disp->screen_base=i->regions.v_fb;
#endif
switch (p->depth) {
#ifdef FBCON_HAS_CFB8 #ifdef FBCON_HAS_CFB8
case 8: case 8:
disp->dispsw=&pm2_cfb8; if (p->flags & PM2FF_ACCEL)
disp->dispsw=&pm2_cfb8;
else
disp->dispsw=&fbcon_cfb8;
break; break;
#endif #endif
#ifdef FBCON_HAS_CFB16 #ifdef FBCON_HAS_CFB16
case 16: case 16:
disp->dispsw=&pm2_cfb16; if (p->flags & PM2FF_ACCEL)
disp->dispsw=&pm2_cfb16;
else
disp->dispsw=&fbcon_cfb16;
disp->dispsw_data=i->cmap.cmap16; disp->dispsw_data=i->cmap.cmap16;
break; break;
#endif #endif
#ifdef FBCON_HAS_CFB24 #ifdef FBCON_HAS_CFB24
case 24: case 24:
disp->dispsw=&pm2_cfb24; if (p->flags & PM2FF_ACCEL)
disp->dispsw=&pm2_cfb24;
else
disp->dispsw=&fbcon_cfb24;
disp->dispsw_data=i->cmap.cmap24; disp->dispsw_data=i->cmap.cmap24;
break; break;
#endif #endif
#ifdef FBCON_HAS_CFB32 #ifdef FBCON_HAS_CFB32
case 32: case 32:
disp->dispsw=&pm2_cfb32; if (p->flags & PM2FF_ACCEL)
disp->dispsw=&pm2_cfb32;
else
disp->dispsw=&fbcon_cfb32;
disp->dispsw_data=i->cmap.cmap32; disp->dispsw_data=i->cmap.cmap32;
break; break;
#endif #endif
...@@ -2050,46 +2227,62 @@ static int pm2fb_set_font(struct display *d, int width, int height) ...@@ -2050,46 +2227,62 @@ static int pm2fb_set_font(struct display *d, int width, int height)
#ifdef MODULE #ifdef MODULE
static void pm2fb_cleanup(void) { static void pm2fb_cleanup(void) {
struct pm2fb_info* i = &fb_info; struct pm2fb_info* i=&fb_info;
unregister_framebuffer((struct fb_info *)i); unregister_framebuffer((struct fb_info* )info);
pm2fb_reset(i); pm2fb_reset(i);
UNMAP(i->regions.v_fb, i->regions.fb_size); UNMAP(i->regions.v_fb, i->regions.fb_size);
release_mem_region(i->regions.p_fb, i->regions.fb_size); release_mem_region(i->regions.p_fb, i->regions.fb_size);
UNMAP(i->regions.v_regs, PM2_REGS_SIZE); UNMAP(i->regions.v_regs, PM2_REGS_SIZE);
release_mem_region(i->regions.p_regs, PM2_REGS_SIZE); release_mem_region(i->regions.p_regs, PM2_REGS_SIZE);
if (board_table[i->board].cleanup) if (board_table[i->board].cleanup)
board_table[i->board].cleanup(i); board_table[i->board].cleanup(i);
} }
#endif /* MODULE */ #endif /* MODULE */
int __init pm2fb_init(void){ int __init pm2fb_init(void) {
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
memset(&fb_info, 0, sizeof(fb_info)); memset(&fb_info, 0, sizeof(fb_info));
memcpy(&fb_info.current_par, &pm2fb_options.user_mode, sizeof(fb_info.current_par));
if (!pm2fb_conf(&fb_info)) { if (!pm2fb_conf(&fb_info)) {
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
return -ENXIO; return -ENXIO;
} }
/* Pick up user_var settings if set. */
if ((pm2fb_options.flags & OPTF_USER_VAR) &&
pm2fb_decode_var(&user_var, &pm2fb_options.user_mode,
&fb_info.gen)<0) {
printk("pm2fb: user supplied var: mode is bad.\n");
memcpy(&pm2fb_options.user_mode,
&user_mode[DEFAULT_USER_MODE].par,
sizeof(struct pm2fb_par));
}
memcpy(&fb_info.current_par, &pm2fb_options.user_mode,
sizeof(fb_info.current_par));
pm2fb_reset(&fb_info); pm2fb_reset(&fb_info);
fb_info.disp.scrollmode=SCROLL_YNOMOVE; fb_info.disp.scrollmode=SCROLL_YNOMOVE;
fb_info.gen.parsize=sizeof(struct pm2fb_par); fb_info.gen.parsize=sizeof(struct pm2fb_par);
fb_info.gen.fbhw=&pm2fb_hwswitch; fb_info.gen.fbhw=&pm2fb_hwswitch;
strcpy(fb_info.gen.info.modename, permedia2_name); strcpy(fb_info.gen.info.modename, permedia2_name);
fb_info.gen.info.node = NODEV;
fb_info.gen.info.flags=FBINFO_FLAG_DEFAULT; fb_info.gen.info.flags=FBINFO_FLAG_DEFAULT;
fb_info.gen.info.fbops=&pm2fb_ops; fb_info.gen.info.fbops=&pm2fb_ops;
fb_info.gen.info.disp=&fb_info.disp; fb_info.gen.info.disp=&fb_info.disp;
strcpy(fb_info.gen.info.fontname, pm2fb_options.font); strcpy(fb_info.gen.info.fontname, pm2fb_options.font);
fb_info.gen.info.switch_con=&fbgen_switch; fb_info.gen.info.switch_con=&fbgen_switch;
fb_info.gen.info.updatevar=&fbgen_update_var; fb_info.gen.info.updatevar=&fbgen_update_var;
fbgen_get_var(&fb_info.disp.var, -1, &fb_info.gen.info); fbgen_get_var(&fb_info.disp.var, -1, &fb_info.gen.info);
fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen); fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen);
fbgen_set_disp(-1, &fb_info.gen); fbgen_set_disp(-1, &fb_info.gen);
do_install_cmap(0, &fb_info.gen.info); fbgen_install_cmap(0, &fb_info.gen);
if (register_framebuffer(&fb_info.gen.info)<0) { if (register_framebuffer(&fb_info.gen.info)<0) {
printk(KERN_ERR "pm2fb: unable to register.\n"); printk(KERN_ERR "pm2fb: unable to register.\n");
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
...@@ -2103,7 +2296,7 @@ int __init pm2fb_init(void){ ...@@ -2103,7 +2296,7 @@ int __init pm2fb_init(void){
return 0; return 0;
} }
static void __init pm2fb_mode_setup(char* options){ static void __init pm2fb_mode_setup(char* options) {
int i; int i;
for (i=0; user_mode[i].name[0] && for (i=0; user_mode[i].name[0] &&
...@@ -2111,17 +2304,77 @@ static void __init pm2fb_mode_setup(char* options){ ...@@ -2111,17 +2304,77 @@ static void __init pm2fb_mode_setup(char* options){
if (user_mode[i].name[0]) { if (user_mode[i].name[0]) {
memcpy(&pm2fb_options.user_mode, &user_mode[i].par, memcpy(&pm2fb_options.user_mode, &user_mode[i].par,
sizeof(pm2fb_options.user_mode)); sizeof(pm2fb_options.user_mode));
pm2fb_options.flags |= OPTF_USER; pm2fb_options.flags|=OPTF_USER;
} }
} }
static void __init pm2fb_font_setup(char* options){ static void __init pm2fb_font_setup(char* options) {
strncpy(pm2fb_options.font, options, sizeof(pm2fb_options.font)); strncpy(pm2fb_options.font, options, sizeof(pm2fb_options.font));
pm2fb_options.font[sizeof(pm2fb_options.font)-1]='\0'; pm2fb_options.font[sizeof(pm2fb_options.font)-1]='\0';
} }
int __init pm2fb_setup(char* options){ static void __init pm2fb_var_setup(char* options) {
char* next;
pm2fb_par2var(&user_var, &pm2fb_options.user_mode);
while (options) {
if ((next=strchr(options, ';')))
*(next++)='\0';
if (!strncmp(options, "bpp:", 4))
user_var.bits_per_pixel=
simple_strtoul(options+4, NULL, 0);
else if (!strncmp(options, "xres:", 5))
user_var.xres=simple_strtoul(options+5, NULL, 0);
else if (!strncmp(options, "yres:", 5))
user_var.yres=simple_strtoul(options+5, NULL, 0);
else if (!strncmp(options, "vxres:", 6))
user_var.xres_virtual=
simple_strtoul(options+6, NULL, 0);
else if (!strncmp(options, "vyres:", 6))
user_var.yres_virtual=
simple_strtoul(options+6, NULL, 0);
else if (!strncmp(options, "left:", 5))
user_var.left_margin=
simple_strtoul(options+5, NULL, 0);
else if (!strncmp(options, "right:", 6))
user_var.right_margin=
simple_strtoul(options+6, NULL, 0);
else if (!strncmp(options, "lower:", 6))
user_var.lower_margin=
simple_strtoul(options+6, NULL, 0);
else if (!strncmp(options, "upper:", 6))
user_var.upper_margin=
simple_strtoul(options+6, NULL, 0);
else if (!strncmp(options, "hslen:", 6))
user_var.hsync_len=simple_strtoul(options+6, NULL, 0);
else if (!strncmp(options, "vslen:", 6))
user_var.vsync_len=simple_strtoul(options+6, NULL, 0);
else if (!strncmp(options, "pixclock:", 9))
user_var.pixclock=simple_strtoul(options+9, NULL, 0);
else if (!strcmp(options, "+hsync"))
user_var.sync|=FB_SYNC_HOR_HIGH_ACT;
else if (!strcmp(options, "-hsync"))
user_var.sync&=~FB_SYNC_HOR_HIGH_ACT;
else if (!strcmp(options, "+vsync"))
user_var.sync|=FB_SYNC_VERT_HIGH_ACT;
else if (!strcmp(options, "-vsync"))
user_var.sync&=~FB_SYNC_VERT_HIGH_ACT;
else if (!strcmp(options, "+double"))
user_var.vmode|=FB_VMODE_DOUBLE;
else if (!strcmp(options, "-double"))
user_var.vmode&=~FB_VMODE_DOUBLE;
else if (!strcmp(options, "+accel"))
user_var.accel_flags|=FB_ACCELF_TEXT;
else if (!strcmp(options, "-accel"))
user_var.accel_flags&=~FB_ACCELF_TEXT;
options=next;
}
pm2fb_options.flags|=OPTF_USER_VAR;
}
int __init pm2fb_setup(char* options) {
char* next; char* next;
while (options) { while (options) {
...@@ -2131,16 +2384,23 @@ int __init pm2fb_setup(char* options){ ...@@ -2131,16 +2384,23 @@ int __init pm2fb_setup(char* options){
pm2fb_font_setup(options+5); pm2fb_font_setup(options+5);
else if (!strncmp(options, "mode:", 5)) else if (!strncmp(options, "mode:", 5))
pm2fb_mode_setup(options+5); pm2fb_mode_setup(options+5);
else if (!strncmp(options, "var:", 4))
pm2fb_var_setup(options+4);
else if (!strcmp(options, "ypan")) else if (!strcmp(options, "ypan"))
pm2fb_options.flags |= OPTF_YPAN; pm2fb_options.flags |= OPTF_YPAN;
else if (!strcmp(options, "oldmem")) else if (!strcmp(options, "oldmem"))
pm2fb_options.flags |= OPTF_OLD_MEM; pm2fb_options.flags |= OPTF_OLD_MEM;
else if (!strcmp(options, "virtual")) else if (!strcmp(options, "virtual"))
pm2fb_options.flags |= OPTF_VIRTUAL; pm2fb_options.flags |= OPTF_VIRTUAL;
else if (!strcmp(options, "lowhsync"))
pm2fb_options.flags |= OPTF_LOW_HSYNC;
else if (!strcmp(options, "lowvsync"))
pm2fb_options.flags |= OPTF_LOW_VSYNC;
else if (!strcmp(options, "noblink")) else if (!strcmp(options, "noblink"))
curblink = 0; curblink=0;
options=next; options=next;
} }
user_var.activate=FB_ACTIVATE_NOW;
return 0; return 0;
} }
...@@ -2156,9 +2416,10 @@ static char *mode = NULL; ...@@ -2156,9 +2416,10 @@ static char *mode = NULL;
MODULE_PARM(mode, "s"); MODULE_PARM(mode, "s");
int __init init_module(void) { int init_module(void) {
if (mode) pm2fb_mode_setup(mode); if (mode)
pm2fb_mode_setup(mode);
return pm2fb_init(); return pm2fb_init();
} }
......
...@@ -37,12 +37,6 @@ ...@@ -37,12 +37,6 @@
#include "pmag-ba-fb.h" #include "pmag-ba-fb.h"
#include <video/fbcon.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>
#define arraysize(x) (sizeof(x)/sizeof(*(x)))
struct pmag_ba_ramdac_regs { struct pmag_ba_ramdac_regs {
unsigned char addr_low; unsigned char addr_low;
...@@ -54,316 +48,119 @@ struct pmag_ba_ramdac_regs { ...@@ -54,316 +48,119 @@ struct pmag_ba_ramdac_regs {
unsigned char cmap; unsigned char cmap;
}; };
struct pmag_ba_my_fb_info {
struct fb_info info;
struct pmag_ba_ramdac_regs *bt459_regs;
unsigned long pmagba_fb_start;
unsigned long pmagba_fb_size;
unsigned long pmagba_fb_line_length;
};
static struct display disp;
/* /*
* Max 3 TURBOchannel slots -> max 3 PMAG-BA :) * Max 3 TURBOchannel slots -> max 3 PMAG-BA :)
*/ */
static struct pmag_ba_my_fb_info pmagba_fb_info[3]; static struct fb_info pmagba_fb_info[3];
static struct display pmagba_disp[3];
static struct fb_var_screeninfo pmagbafb_defined = { static struct fb_var_screeninfo pmagbafb_defined = {
0, 0, 0, 0, /* W,H, W, H (virtual) load xres,xres_virtual */ xres: 1024,
0, 0, /* virtual -> visible no offset */ yres: 864,
0, /* depth -> load bits_per_pixel */ xres_virtual: 1024,
0, /* greyscale ? */ yres_virtual: 864,
{0, 0, 0}, /* R */ bits_per_pixel: 8,
{0, 0, 0}, /* G */ activate: FB_ACTIVATE_NOW,
{0, 0, 0}, /* B */ height: 274,
{0, 0, 0}, /* transparency */ width: 195,
0, /* standard pixel format */ accel: FB_ACCEL_NONE,
FB_ACTIVATE_NOW, vmode: FB_VMODE_NONINTERLACED,
274, 195, /* 14" monitor */ }
FB_ACCEL_NONE,
0L, 0L, 0L, 0L, 0L, static struct fb_fix_screeninfo pmagbafb_fix = {
0L, 0L, 0, /* No sync info */ id: "PMAG-BA",
FB_VMODE_NONINTERLACED, smem_len: (1024 * 864),
{0, 0, 0, 0, 0, 0} type: FB_TYPE_PACKED_PIXELS,
}; visual: FB_VISUAL_PSEUDOCOLOR,
line_length: 1024,
struct pmagbafb_par {
};
struct pmagbafb_par current_par;
static void pmagbafb_encode_var(struct fb_var_screeninfo *var,
struct pmagbafb_par *par)
{
int i = 0;
var->xres = 1024;
var->yres = 864;
var->xres_virtual = 1024;
var->yres_virtual = 864;
var->xoffset = 0;
var->yoffset = 0;
var->bits_per_pixel = 8;
var->grayscale = 0;
var->transp.offset = 0;
var->transp.length = 0;
var->transp.msb_right = 0;
var->nonstd = 0;
var->activate = 1;
var->height = -1;
var->width = -1;
var->vmode = FB_VMODE_NONINTERLACED;
var->pixclock = 0;
var->sync = 0;
var->left_margin = 0;
var->right_margin = 0;
var->upper_margin = 0;
var->lower_margin = 0;
var->hsync_len = 0;
var->vsync_len = 0;
for (i = 0; i < arraysize(var->reserved); i++)
var->reserved[i] = 0;
}
static void pmagbafb_get_par(struct pmagbafb_par *par)
{
*par = current_par;
}
static int pmagba_fb_update_var(int con, struct fb_info *info)
{
return 0;
}
static int pmagba_do_fb_set_var(struct fb_var_screeninfo *var,
int isactive)
{
struct pmagbafb_par par;
pmagbafb_get_par(&par);
pmagbafb_encode_var(var, &par);
return 0;
} }
/* /*
* Turn hardware cursor off * Turn hardware cursor off
*/ */
void pmagbafb_erase_cursor(struct pmag_ba_my_fb_info *info) void pmagbafb_erase_cursor(struct pmag_ba_ramdac_regs *bt459_regs)
{
info->bt459_regs->addr_low = 0;
info->bt459_regs->addr_hi = 3;
info->bt459_regs->data = 0;
}
/*
* Write to a Bt459 color map register
*/
void pmag_ba_bt459_write_colormap(struct pmag_ba_my_fb_info *info,
int reg, __u8 red, __u8 green, __u8 blue)
{
info->bt459_regs->addr_low = (__u8) reg;
info->bt459_regs->addr_hi = 0;
info->bt459_regs->cmap = red;
info->bt459_regs->cmap = green;
info->bt459_regs->cmap = blue;
}
/*
* Get the palette
*/
static int pmagbafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{ {
unsigned int i; bt459_regs->addr_low = 0;
unsigned int length; bt459_regs->addr_hi = 3;
bt459_regs->data = 0;
if (((cmap->start) + (cmap->len)) >= 256) {
length = 256 - (cmap->start);
} else {
length = cmap->len;
}
for (i = 0; i < length; i++) {
/*
* TODO
*/
}
return 0;
} }
/* /*
* Set the palette. * Set the palette.
*/ */
static int pmagbafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, static int pmagbafb_setcolreg(unsigned regno, unsigned red, unsigned green,
struct fb_info *info) unsigned blue, unsigned transp,
struct fb_info *info)
{ {
unsigned int i; struct pmag_ba_ramdac_regs *bt459_regs = (struct pmag_ba_ramdac_regs *) info->par;
__u8 cmap_red, cmap_green, cmap_blue;
unsigned int length;
if (((cmap->start) + (cmap->len)) >= 256)
length = 256 - (cmap->start);
else
length = cmap->len;
for (i = 0; i < length; i++) { if (regno >= info->cmap.len)
cmap_red = ((cmap->red[i]) >> 8); /* The cmap fields are 16 bits */ return 1;
cmap_green = ((cmap->green[i]) >> 8); /* wide, but the harware colormap */
cmap_blue = ((cmap->blue[i]) >> 8); /* registers are only 8 bits wide */
pmag_ba_bt459_write_colormap((struct pmag_ba_my_fb_info *)
info, cmap->start + i,
cmap_red, cmap_green,
cmap_blue);
}
return 0;
}
static int pmagbafb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
struct pmagbafb_par par;
if (con == -1) {
pmagbafb_get_par(&par);
pmagbafb_encode_var(var, &par);
} else
*var = fb_display[con].var;
return 0;
}
static int pmagbafb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
int err;
if ((err = pmagba_do_fb_set_var(var, 1)))
return err;
return 0;
}
static void pmagbafb_encode_fix(struct fb_fix_screeninfo *fix,
struct pmagbafb_par *par,
struct pmag_ba_my_fb_info *info)
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, "PMAG-BA");
fix->smem_start = info->pmagba_fb_start;
fix->smem_len = info->pmagba_fb_size;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_PSEUDOCOLOR;
fix->xpanstep = 0;
fix->ypanstep = 0;
fix->ywrapstep = 0;
fix->line_length = info->pmagba_fb_line_length;
}
static int pmagbafb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
{
struct pmagbafb_par par;
pmagbafb_get_par(&par); red >>= 8; /* The cmap fields are 16 bits */
pmagbafb_encode_fix(fix, &par, (struct pmag_ba_my_fb_info *) info); green >>= 8; /* wide, but the harware colormap */
blue >>= 8; /* registers are only 8 bits wide */
bt459_regs->addr_low = (__u8) regno;
bt459_regs->addr_hi = 0;
bt459_regs->cmap = red;
bt459_regs->cmap = green;
bt459_regs->cmap = blue;
return 0; return 0;
} }
static int pmagbafb_switch(int con, struct fb_info *info)
{
pmagba_do_fb_set_var(&fb_display[con].var, 1);
info->currcon = con;
return 0;
}
static void pmagbafb_set_disp(int con, struct pmag_ba_my_fb_info *info)
{
struct fb_fix_screeninfo fix;
struct display *display;
if (con >= 0)
display = &fb_display[con];
else
display = &disp; /* used during initialization */
pmagbafb_get_fix(&fix, con, (struct fb_info *) info);
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
display->ypanstep = fix.ypanstep;
display->ywrapstep = fix.ywrapstep;
display->line_length = fix.line_length;
display->next_line = fix.line_length;
display->can_soft_blank = 0;
display->inverse = 0;
display->dispsw = &fbcon_cfb8;
}
static struct fb_ops pmagbafb_ops = { static struct fb_ops pmagbafb_ops = {
owner: THIS_MODULE, owner: THIS_MODULE,
fb_get_fix: pmagbafb_get_fix, fb_get_fix: gen_get_fix,
fb_get_var: pmagbafb_get_var, fb_get_var: gen_get_var,
fb_set_var: pmagbafb_set_var, fb_set_var: gen_set_var,
fb_get_cmap: pmagbafb_get_cmap, fb_get_cmap: gen_get_cmap,
fb_set_cmap: pmagbafb_set_cmap, fb_set_cmap: gen_set_cmap,
}; fb_setcolreg: pmagbafb_setcolreg,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
}
int __init pmagbafb_init_one(int slot) int __init pmagbafb_init_one(int slot)
{ {
unsigned long base_addr = get_tc_base_addr(slot); unsigned long base_addr = get_tc_base_addr(slot);
struct pmag_ba_my_fb_info *ip = struct fb_info *info = &pmagba_fb_info[slot];
(struct pmag_ba_my_fb_info *) &pmagba_fb_info[slot]; struct display *disp = &pmagba_disp[slot];
printk("PMAG-BA framebuffer in slot %d\n", slot); printk("PMAG-BA framebuffer in slot %d\n", slot);
/* /*
* Framebuffer display memory base address and friends * Framebuffer display memory base address and friends
*/ */
ip->bt459_regs = pmagbafb_fix.smem_start = base_addr + PMAG_BA_ONBOARD_FBMEM_OFFSET;
(struct pmag_ba_ramdac_regs *) (base_addr + info->par = (base_addr + PMAG_BA_BT459_OFFSET);
PMAG_BA_BT459_OFFSET);
ip->pmagba_fb_start = base_addr + PMAG_BA_ONBOARD_FBMEM_OFFSET;
ip->pmagba_fb_size = 1024 * 864;
ip->pmagba_fb_line_length = 1024;
/* /*
* Configure the Bt459 RAM DAC * Configure the Bt459 RAM DAC
*/ */
pmagbafb_erase_cursor(ip); pmagbafb_erase_cursor((struct pmag_ba_ramdac_regs *) info->par);
/*
* Fill in the available video resolution
*/
pmagbafb_defined.xres = 1024;
pmagbafb_defined.yres = 864;
pmagbafb_defined.xres_virtual = 1024;
pmagbafb_defined.yres_virtual = 864;
pmagbafb_defined.bits_per_pixel = 8;
/* /*
* Let there be consoles.. * Let there be consoles..
*/ */
strcpy(ip->info.modename, "PMAG-BA"); strcpy(info->modename, pmagbafb_fix.id);
ip->info.changevar = NULL; info->changevar = NULL;
ip->info.node = NODEV; info->node = NODEV;
ip->info.fbops = &pmagbafb_ops; info->fbops = &pmagbafb_ops;
ip->info.screen_base = ip->pmagba_fb_start; info->var = pmagbafb_defined;
ip->info.disp = &disp; info->fix = pmagbafb_fix;
ip->info.currcon = -1; info->screen_base = pmagbafb_fix.smem_start;
ip->info.switch_con = &pmagbafb_switch; info->disp = &disp;
ip->info.updatevar = &pmagba_fb_update_var; info->currcon = -1;
ip->info.flags = FBINFO_FLAG_DEFAULT; info->switch_con = gen_switch;
info->updatevar = gen_update_var;
pmagba_do_fb_set_var(&pmagbafb_defined, 1); info->flags = FBINFO_FLAG_DEFAULT;
pmagbafb_get_var(&disp.var, -1, (struct fb_info *) ip);
pmagbafb_set_disp(-1, ip); fb_alloc_cmap(&fb_info.cmap, 256, 0);
gen_set_disp(-1, info);
if (register_framebuffer((struct fb_info *) ip) < 0) if (register_framebuffer(info) < 0)
return 1; return 1;
return 0; return 0;
} }
......
...@@ -40,12 +40,6 @@ ...@@ -40,12 +40,6 @@
#include "pmagb-b-fb.h" #include "pmagb-b-fb.h"
#include <video/fbcon.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>
#define arraysize(x) (sizeof(x)/sizeof(*(x)))
struct pmagb_b_ramdac_regs { struct pmagb_b_ramdac_regs {
unsigned char addr_low; unsigned char addr_low;
...@@ -57,317 +51,119 @@ struct pmagb_b_ramdac_regs { ...@@ -57,317 +51,119 @@ struct pmagb_b_ramdac_regs {
unsigned char cmap; unsigned char cmap;
}; };
struct pmagb_b_my_fb_info {
struct fb_info info;
struct pmagb_b_ramdac_regs *bt459_regs;
unsigned long pmagbb_fb_start;
unsigned long pmagbb_fb_size;
unsigned long pmagbb_fb_line_length;
};
static struct display disp;
/* /*
* Max 3 TURBOchannel slots -> max 3 PMAGB-B :) * Max 3 TURBOchannel slots -> max 3 PMAGB-B :)
*/ */
static struct pmagb_b_my_fb_info pmagbb_fb_info[3]; static struct fb_info pmagbb_fb_info[3];
static struct display pmagbb_disp[3];
static struct fb_var_screeninfo pmagbbfb_defined = { static struct fb_var_screeninfo pmagbbfb_defined = {
0, 0, 0, 0, /* W,H, W, H (virtual) load xres,xres_virtual */ xres: 1280,
0, 0, /* virtual -> visible no offset */ yres: 1024,
0, /* depth -> load bits_per_pixel */ xres_virtual: 1280,
0, /* greyscale ? */ yres_virtual: 1024,
{0, 0, 0}, /* R */ bits_per_pixel: 8,
{0, 0, 0}, /* G */ activate: FB_ACTIVATE_NOW,
{0, 0, 0}, /* B */ height: 274,
{0, 0, 0}, /* transparency */ width: 195,
0, /* standard pixel format */ accel_flags: FB_ACCEL_NONE,
FB_ACTIVATE_NOW, vmode: FB_VMODE_NONINTERLACED,
274, 195, /* 14" monitor */
FB_ACCEL_NONE,
0L, 0L, 0L, 0L, 0L,
0L, 0L, 0, /* No sync info */
FB_VMODE_NONINTERLACED,
{0, 0, 0, 0, 0, 0}
};
struct pmagbbfb_par {
}; };
struct pmagbbfb_par current_par; static struct fb_fix_screeninfo pmagbafb_fix = {
id: "PMAGB-BA",
static void pmagbbfb_encode_var(struct fb_var_screeninfo *var, smem_len: (1280 * 1024),
struct pmagbbfb_par *par) type: FB_TYPE_PACKED_PIXELS,
{ visual: FB_VISUAL_PSEUDOCOLOR,
int i = 0; line_length: 1280,
var->xres = 1280;
var->yres = 1024;
var->xres_virtual = 1280;
var->yres_virtual = 1024;
var->xoffset = 0;
var->yoffset = 0;
var->bits_per_pixel = 8;
var->grayscale = 0;
var->transp.offset = 0;
var->transp.length = 0;
var->transp.msb_right = 0;
var->nonstd = 0;
var->activate = 1;
var->height = -1;
var->width = -1;
var->vmode = FB_VMODE_NONINTERLACED;
var->pixclock = 0;
var->sync = 0;
var->left_margin = 0;
var->right_margin = 0;
var->upper_margin = 0;
var->lower_margin = 0;
var->hsync_len = 0;
var->vsync_len = 0;
for (i = 0; i < arraysize(var->reserved); i++)
var->reserved[i] = 0;
}
static void pmagbbfb_get_par(struct pmagbbfb_par *par)
{
*par = current_par;
}
static int pmagbb_fb_update_var(int con, struct fb_info *info)
{
return 0;
}
static int pmagbb_do_fb_set_var(struct fb_var_screeninfo *var,
int isactive)
{
struct pmagbbfb_par par;
pmagbbfb_get_par(&par);
pmagbbfb_encode_var(var, &par);
return 0;
} }
/* /*
* Turn hardware cursor off * Turn hardware cursor off
*/ */
void pmagbbfb_erase_cursor(struct pmagb_b_my_fb_info *info) void pmagbbfb_erase_cursor(struct pmagb_b_ramdac_regs *bt459_regs)
{ {
info->bt459_regs->addr_low = 0; bt459_regs->addr_low = 0;
info->bt459_regs->addr_hi = 3; bt459_regs->addr_hi = 3;
info->bt459_regs->data = 0; bt459_regs->data = 0;
}
/*
* Write to a Bt459 color map register
*/
void pmagb_b_bt459_write_colormap(struct pmagb_b_my_fb_info *info,
int reg, __u8 red, __u8 green, __u8 blue)
{
info->bt459_regs->addr_low = (__u8) reg;
info->bt459_regs->addr_hi = 0;
info->bt459_regs->cmap = red;
info->bt459_regs->cmap = green;
info->bt459_regs->cmap = blue;
}
/*
* Get the palette
*/
static int pmagbbfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
unsigned int i;
unsigned int length;
if (((cmap->start) + (cmap->len)) >= 256) {
length = 256 - (cmap->start);
} else {
length = cmap->len;
}
for (i = 0; i < length; i++) {
/*
* TODO
*/
}
return 0;
} }
/* /*
* Set the palette. * Set the palette.
*/ */
static int pmagbbfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, static int pmagbbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
struct fb_info *info) unsigned blue, unsigned transp,
{ struct fb_info *info)
unsigned int i;
__u8 cmap_red, cmap_green, cmap_blue;
unsigned int length;
if (((cmap->start) + (cmap->len)) >= 256)
length = 256 - (cmap->start);
else
length = cmap->len;
for (i = 0; i < length; i++) {
cmap_red = ((cmap->red[i]) >> 8); /* The cmap fields are 16 bits */
cmap_green = ((cmap->green[i]) >> 8); /* wide, but the harware colormap */
cmap_blue = ((cmap->blue[i]) >> 8); /* registers are only 8 bits wide */
pmagb_b_bt459_write_colormap((struct pmagb_b_my_fb_info *)
info, cmap->start + i,
cmap_red, cmap_green,
cmap_blue);
}
return 0;
}
static int pmagbbfb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
struct pmagbbfb_par par;
if (con == -1) {
pmagbbfb_get_par(&par);
pmagbbfb_encode_var(var, &par);
} else
*var = fb_display[con].var;
return 0;
}
static int pmagbbfb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
int err;
if ((err = pmagbb_do_fb_set_var(var, 1)))
return err;
return 0;
}
static void pmagbbfb_encode_fix(struct fb_fix_screeninfo *fix,
struct pmagbbfb_par *par,
struct pmagb_b_my_fb_info *info)
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, "PMAGB-BA");
fix->smem_start = info->pmagbb_fb_start;
fix->smem_len = info->pmagbb_fb_size;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_PSEUDOCOLOR;
fix->xpanstep = 0;
fix->ypanstep = 0;
fix->ywrapstep = 0;
fix->line_length = info->pmagbb_fb_line_length;
}
static int pmagbbfb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
{ {
struct pmagbbfb_par par; struct pmagb_b_ramdac_regs *bt459_regs = (struct pmagb_b_ramdac_regs *) info->par;
if (regno >= info->cmap.len)
return 1;
pmagbbfb_get_par(&par); red >>= 8; /* The cmap fields are 16 bits */
pmagbbfb_encode_fix(fix, &par, (struct pmagb_b_my_fb_info *) info); green >>= 8; /* wide, but the harware colormap */
blue >>= 8; /* registers are only 8 bits wide */
bt459_regs->addr_low = (__u8) regno;
bt459_regs->addr_hi = 0;
bt459_regs->cmap = red;
bt459_regs->cmap = green;
bt459_regs->cmap = blue;
return 0; return 0;
} }
static int pmagbbfb_switch(int con, struct fb_info *info)
{
pmagbb_do_fb_set_var(&fb_display[con].var, 1);
info->currcon = con;
return 0;
}
static void pmagbbfb_set_disp(int con, struct pmagb_b_my_fb_info *info)
{
struct fb_fix_screeninfo fix;
struct display *display;
if (con >= 0)
display = &fb_display[con];
else
display = &disp; /* used during initialization */
pmagbbfb_get_fix(&fix, con, (struct fb_info *) info);
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
display->ypanstep = fix.ypanstep;
display->ywrapstep = fix.ywrapstep;
display->line_length = fix.line_length;
display->next_line = fix.line_length;
display->can_soft_blank = 0;
display->inverse = 0;
display->dispsw = &fbcon_cfb8;
}
static struct fb_ops pmagbbfb_ops = { static struct fb_ops pmagbbfb_ops = {
owner: THIS_MODULE, owner: THIS_MODULE,
fb_get_fix: pmagbbfb_get_fix, fb_get_fix: gen_get_fix,
fb_get_var: pmagbbfb_get_var, fb_get_var: gen_get_var,
fb_set_var: pmagbbfb_set_var, fb_set_var: gen_set_var,
fb_get_cmap: pmagbbfb_get_cmap, fb_get_cmap: gen_get_cmap,
fb_set_cmap: pmagbbfb_set_cmap, fb_set_cmap: gen_set_cmap,
fb_setcolreg: pmagbbfb_setcolreg,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
}; };
int __init pmagbbfb_init_one(int slot) int __init pmagbbfb_init_one(int slot)
{ {
unsigned long base_addr = get_tc_base_addr(slot); unsigned long base_addr = get_tc_base_addr(slot);
struct pmagb_b_my_fb_info *ip = struct fb_info *info = &pmagbb_fb_info[slot];
(struct pmagb_b_my_fb_info *) &pmagbb_fb_info[slot]; struct display *disp = &pmagbb_disp[slot];
printk("PMAGB-BA framebuffer in slot %d\n", slot); printk("PMAGB-BA framebuffer in slot %d\n", slot);
/* /*
* Framebuffer display memory base address and friends * Framebuffer display memory base address and friends
*/ */
ip->bt459_regs = pmagbbfb_fix.smem_start = base_addr + PMAGB_B_ONBOARD_FBMEM_OFFSET;
(struct pmagb_b_ramdac_regs *) (base_addr + info->par = (base_addr + PMAGB_B_BT459_OFFSET);
PMAGB_B_BT459_OFFSET);
ip->pmagbb_fb_start = base_addr + PMAGB_B_ONBOARD_FBMEM_OFFSET;
ip->pmagbb_fb_size = 1280 * 1024;
ip->pmagbb_fb_line_length = 1280;
/* /*
* Configure the Bt459 RAM DAC * Configure the Bt459 RAM DAC
*/ */
pmagbbfb_erase_cursor(ip); pmagbbfb_erase_cursor((struct pmagb_b_ramdac_regs *) info->par);
/*
* Fill in the available video resolution
*/
pmagbbfb_defined.xres = 1280;
pmagbbfb_defined.yres = 1024;
pmagbbfb_defined.xres_virtual = 1280;
pmagbbfb_defined.yres_virtual = 1024;
pmagbbfb_defined.bits_per_pixel = 8;
/* /*
* Let there be consoles.. * Let there be consoles..
*/ */
strcpy(ip->info.modename, "PMAGB-BA"); strcpy(info->modename, pmagbbfb_fix.id);
ip->info.changevar = NULL; info->changevar = NULL;
ip->info.node = NODEV; info->node = NODEV;
ip->info.fbops = &pmagbbfb_ops; info->fbops = &pmagbbfb_ops;
ip->info.screen_base = (char *) ip->pmagbb_fb_start; info->var = pmagbbfb_defined;
fix->smem_len = info->pmagbb_fb_size; info->fix = pmagbbfb_fix;
ip->info.disp = &disp; info->screen_base = pmagbbfb_fix.smem_start;
ip->info.currcon = -1; info->disp = &disp;
ip->info.switch_con = &pmagbbfb_switch; info->currcon = -1;
ip->info.updatevar = &pmagbb_fb_update_var; info->switch_con = gen_switch;
ip->info.flags = FBINFO_FLAG_DEFAULT; info->updatevar = gen_update_var;
info->flags = FBINFO_FLAG_DEFAULT;
pmagbb_do_fb_set_var(&pmagbbfb_defined, 1);
pmagbbfb_get_var(&disp.var, -1, (struct fb_info *) ip); fb_alloc_cmap(&fb_info.cmap, 256, 0);
pmagbbfb_set_disp(-1, ip); gen_set_disp(-1, info);
if (register_framebuffer((struct fb_info *) ip) < 0) if (register_framebuffer(info) < 0)
return 1; return 1;
return 0; return 0;
} }
......
...@@ -298,7 +298,7 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green, ...@@ -298,7 +298,7 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
* Returns negative errno on error, or zero on success. * Returns negative errno on error, or zero on success.
* *
*/ */
static int xxxfb_pan_display(struct fb_var_screeninfo *var, static int xxxfb_pan_display(struct fb_var_screeninfo *var, int con,
const struct fb_info *info) const struct fb_info *info)
{ {
/* ... */ /* ... */
......
...@@ -18,12 +18,12 @@ ...@@ -18,12 +18,12 @@
* Voodoo3 support was contributed Harold Oga. Lots of additions * Voodoo3 support was contributed Harold Oga. Lots of additions
* (proper acceleration, 24 bpp, hardware cursor) and bug fixes by Attila * (proper acceleration, 24 bpp, hardware cursor) and bug fixes by Attila
* Kesmarki. Thanks guys! * Kesmarki. Thanks guys!
* *
* Voodoo1 and Voodoo2 support aren't relevant to this driver as they * Voodoo1 and Voodoo2 support aren't relevant to this driver as they
* behave very differently from the Voodoo3/4/5. For anyone wanting to * behave very differently from the Voodoo3/4/5. For anyone wanting to
* use frame buffer on the Voodoo1/2, see the sstfb driver (which is * use frame buffer on the Voodoo1/2, see the sstfb driver (which is
* located at http://www.sourceforge.net/projects/sstfb). * located at http://www.sourceforge.net/projects/sstfb).
* *
* While I _am_ grateful to 3Dfx for releasing the specs for Banshee, * While I _am_ grateful to 3Dfx for releasing the specs for Banshee,
* I do wish the next version is a bit more complete. Without the XF86 * I do wish the next version is a bit more complete. Without the XF86
* patches I couldn't have gotten even this far... for instance, the * patches I couldn't have gotten even this far... for instance, the
...@@ -76,374 +76,205 @@ ...@@ -76,374 +76,205 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/kd.h>
#include <linux/console.h>
#include <linux/selection.h>
#include <linux/vt_kern.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
#include <video/tdfx.h> #include <video/tdfx.h>
#include <video/fbcon.h> #include <video/fbcon.h>
#ifndef PCI_DEVICE_ID_3DFX_VOODOO5 #ifndef PCI_DEVICE_ID_3DFX_VOODOO5
#define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009 #define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009
#endif #endif
#define TDFXF_HSYNC_ACT_HIGH 0x01 #undef TDFXFB_DEBUG
#define TDFXF_HSYNC_ACT_LOW 0x02
#define TDFXF_VSYNC_ACT_HIGH 0x04
#define TDFXF_VSYNC_ACT_LOW 0x08
#define TDFXF_LINE_DOUBLE 0x10
#define TDFXF_VIDEO_ENABLE 0x20
#define TDFXF_HSYNC_MASK 0x03
#define TDFXF_VSYNC_MASK 0x0c
//#define TDFXFB_DEBUG
#ifdef TDFXFB_DEBUG #ifdef TDFXFB_DEBUG
#define DPRINTK(a,b...) printk(KERN_DEBUG "fb: %s: " a, __FUNCTION__ , ## b) #define DPRINTK(a,b...) printk(KERN_DEBUG "fb: %s: " a, __FUNCTION__ , ## b)
#else #else
#define DPRINTK(a,b...) #define DPRINTK(a,b...)
#endif #endif
#define BANSHEE_MAX_PIXCLOCK 270000.0 #define BANSHEE_MAX_PIXCLOCK 270000.0
#define VOODOO3_MAX_PIXCLOCK 300000.0 #define VOODOO3_MAX_PIXCLOCK 300000.0
#define VOODOO5_MAX_PIXCLOCK 350000.0 #define VOODOO5_MAX_PIXCLOCK 350000.0
struct tdfxfb_par { static struct fb_fix_screeninfo tdfx_fix __initdata = {
u32 pixclock; id: "3Dfx",
type: FB_TYPE_PACKED_PIXELS,
u32 baseline; visual: FB_VISUAL_PSEUDOCOLOR,
ypanstep: 1,
u32 width; ywrapstep: 1,
u32 height; accel: FB_ACCEL_3DFX_BANSHEE
u32 width_virt;
u32 height_virt;
u32 lpitch; /* line pitch, in bytes */
u32 ppitch; /* pixel pitch, in bits */
u32 bpp;
u32 hdispend;
u32 hsyncsta;
u32 hsyncend;
u32 htotal;
u32 vdispend;
u32 vsyncsta;
u32 vsyncend;
u32 vtotal;
u32 video;
u32 accel_flags;
u32 cmap_len;
}; };
struct fb_info_tdfx { static struct fb_var_screeninfo tdfx_var __initdata = {
struct fb_info fb_info; /* "640x480, 8 bpp @ 60 Hz */
xres: 640,
u16 dev; yres: 480,
u32 max_pixclock; xres_virtual: 640,
yres_virtual: 1024,
unsigned long regbase_phys; bits_per_pixel: 8,
void *regbase_virt; red: {0, 8, 0},
unsigned long regbase_size; blue: {0, 8, 0},
unsigned long bufbase_phys; green: {0, 8, 0},
void *bufbase_virt; activate: FB_ACTIVATE_NOW,
unsigned long bufbase_size; height: -1,
unsigned long iobase; width: -1,
accel_flags: FB_ACCELF_TEXT,
struct { pixclock: 39722,
unsigned red, green, blue, pad; left_margin: 40,
} palette[256]; right_margin: 24,
struct tdfxfb_par default_par; upper_margin: 32,
struct tdfxfb_par current_par; lower_margin: 11,
struct display disp; hsync_len: 96,
#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32) vsync_len: 2,
union { vmode: FB_VMODE_NONINTERLACED
#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;
#endif
struct {
int type;
int state;
int w, u, d;
int x, y, redraw;
unsigned long enable, disable;
unsigned long cursorimage;
struct timer_list timer;
} cursor;
spinlock_t DAClock;
#ifdef CONFIG_MTRR
int mtrr_idx;
#endif
}; };
/*
* Frame buffer device API
*/
static int tdfxfb_get_fix(struct fb_fix_screeninfo *fix,
int con, struct fb_info *fb);
static int tdfxfb_get_var(struct fb_var_screeninfo *var,
int con, struct fb_info *fb);
static int tdfxfb_set_var(struct fb_var_screeninfo *var,
int con, struct fb_info *fb);
static int tdfxfb_setcolreg(u_int regno,
u_int red,
u_int green,
u_int blue, u_int transp, struct fb_info *fb);
static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
int con, struct fb_info *fb);
static int tdfxfb_get_cmap(struct fb_cmap *cmap,
int kspc, int con, struct fb_info *info);
static int tdfxfb_set_cmap(struct fb_cmap *cmap,
int kspc, int con, struct fb_info *info);
/*
* Interface to the low level console driver
*/
static int tdfxfb_switch_con(int con, struct fb_info *fb);
static int tdfxfb_updatevar(int con, struct fb_info *fb);
static int tdfxfb_blank(int blank, struct fb_info *fb);
/*
* Internal routines
*/
static void tdfxfb_set_par(const struct tdfxfb_par *par,
struct fb_info_tdfx *info);
static int tdfxfb_decode_var(const struct fb_var_screeninfo *var,
struct tdfxfb_par *par,
const struct fb_info_tdfx *info);
static int tdfxfb_encode_var(struct fb_var_screeninfo *var,
const struct tdfxfb_par *par,
const struct fb_info_tdfx *info);
static int tdfxfb_encode_fix(struct fb_fix_screeninfo *fix,
const struct tdfxfb_par *par,
const struct fb_info_tdfx *info);
static void tdfxfb_set_dispsw(struct display *disp,
struct fb_info_tdfx *info,
int bpp, int accel);
static int tdfxfb_getcolreg(u_int regno,
u_int * red,
u_int * green,
u_int * blue,
u_int * transp, struct fb_info *fb);
static void tdfxfb_hwcursor_init(void);
static void tdfxfb_createcursorshape(struct display *p);
static void tdfxfb_createcursor(struct display *p);
/*
* do_xxx: Hardware-specific functions
*/
static void do_pan_var(struct fb_var_screeninfo *var,
struct fb_info_tdfx *i);
static void do_flashcursor(unsigned long ptr);
static void do_bitblt(u32 curx, u32 cury, u32 dstx, u32 dsty,
u32 width, u32 height, u32 stride, u32 bpp);
static void do_fillrect(u32 x, u32 y, u32 w, u32 h,
u32 color, u32 stride, u32 bpp, u32 rop);
static void do_putc(u32 fgx, u32 bgx, struct display *p,
int c, int yy, int xx);
static void do_putcs(u32 fgx, u32 bgx, struct display *p,
const unsigned short *s, int count, int yy, int xx);
static u32 do_calc_pll(int freq, int *freq_out);
static void do_write_regs(struct banshee_reg *reg);
static unsigned long do_lfb_size(void);
/*
* Interface used by the world
*/
int tdfxfb_init(void);
void tdfxfb_setup(char *options, int *ints);
/* /*
* PCI driver prototypes * PCI driver prototypes
*/ */
static int tdfxfb_probe(struct pci_dev *pdev, static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id);
const struct pci_device_id *id);
static void tdfxfb_remove(struct pci_dev *pdev); static void tdfxfb_remove(struct pci_dev *pdev);
static struct fb_ops tdfxfb_ops = {
owner:THIS_MODULE,
fb_get_fix:tdfxfb_get_fix,
fb_get_var:tdfxfb_get_var,
fb_set_var:tdfxfb_set_var,
fb_get_cmap:tdfxfb_get_cmap,
fb_set_cmap:tdfxfb_set_cmap,
fb_setcolreg:tdfxfb_setcolreg,
fb_pan_display:tdfxfb_pan_display,
fb_blank:tdfxfb_blank,
};
static struct pci_device_id tdfxfb_id_table[] __devinitdata = { static struct pci_device_id tdfxfb_id_table[] __devinitdata = {
{PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE, { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE,
PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
0xff0000, 0}, 0xff0000, 0 },
{PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3, { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3,
PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
0xff0000, 0}, 0xff0000, 0 },
{PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO5, { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO5,
PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
0xff0000, 0}, 0xff0000, 0 },
{0,} { 0, }
}; };
static struct pci_driver tdfxfb_driver = { static struct pci_driver tdfxfb_driver = {
name:"tdfxfb", name: "tdfxfb",
id_table:tdfxfb_id_table, id_table: tdfxfb_id_table,
probe:tdfxfb_probe, probe: tdfxfb_probe,
remove:__devexit_p(tdfxfb_remove), remove: tdfxfb_remove,
}; };
MODULE_DEVICE_TABLE(pci, tdfxfb_id_table); MODULE_DEVICE_TABLE(pci, tdfxfb_id_table);
struct mode { /*
char *name; * Frame buffer device API
struct fb_var_screeninfo var; */
} mode; int tdfxfb_init(void);
void tdfxfb_setup(char *options, int *ints);
/* 2.3.x kernels have a fb mode database, so supply only one backup default */
struct mode default_mode[] = { static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb);
{"640x480-8@60", /* @ 60 Hz */ static int tdfxfb_set_par(struct fb_info *info);
{ static int tdfxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
640, 480, 640, 1024, 0, 0, 8, 0, u_int transp, struct fb_info *info);
{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, static int tdfxfb_blank(int blank, struct fb_info *info);
0, FB_ACTIVATE_NOW, -1, -1, FB_ACCELF_TEXT, static int tdfxfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info);
39722, 40, 24, 32, 11, 96, 2, static void tdfxfb_fillrect(struct fb_info *info, struct fb_fillrect *rect);
0, FB_VMODE_NONINTERLACED} static void tdfxfb_copyarea(struct fb_info *info, struct fb_copyarea *area);
} static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *image);
static struct fb_ops tdfxfb_ops = {
owner: THIS_MODULE,
fb_get_fix: gen_get_fix,
fb_get_var: gen_get_var,
fb_set_var: gen_set_var,
fb_get_cmap: gen_get_cmap,
fb_set_cmap: gen_set_cmap,
fb_check_var: tdfxfb_check_var,
fb_set_par: tdfxfb_set_par,
fb_setcolreg: tdfxfb_setcolreg,
fb_blank: tdfxfb_blank,
fb_pan_display: tdfxfb_pan_display,
fb_fillrect: tdfxfb_fillrect,
fb_copyarea: tdfxfb_copyarea,
fb_imageblit: tdfxfb_imageblit,
}; };
static struct fb_info_tdfx fb_info; /*
* do_xxx: Hardware-specific functions
*/
static u32 do_calc_pll(int freq, int *freq_out);
static void do_write_regs(struct banshee_reg *reg);
static unsigned long do_lfb_size(unsigned short);
static int noaccel = 0; /*
static int nopan = 0; * Driver data
static int nowrap = 1; // not implemented (yet) */
static int inverse = 0; static struct tdfx_par default_par;
#ifdef CONFIG_MTRR
static int nomtrr = 0; static int nopan = 0;
#endif static int nowrap = 1; // not implemented (yet)
static int nohwcursor = 0; static int inverse = 0;
static char __initdata fontname[40] = { 0 };
static char *mode_option __initdata = NULL; static char *mode_option __initdata = NULL;
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* Hardware-specific funcions * Hardware-specific funcions
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
#ifdef VGA_REG_IO #ifdef VGA_REG_IO
static inline u8 vga_inb(u32 reg) static inline u8 vga_inb(u32 reg) { return inb(reg); }
{ static inline u16 vga_inw(u32 reg) { return inw(reg); }
return inb(reg); static inline u16 vga_inl(u32 reg) { return inl(reg); }
}
static inline u16 vga_inw(u32 reg)
{
return inw(reg);
}
static inline u16 vga_inl(u32 reg)
{
return inl(reg);
}
static inline void vga_outb(u32 reg, u8 val) static inline void vga_outb(u32 reg, u8 val) { outb(val, reg); }
{ static inline void vga_outw(u32 reg, u16 val) { outw(val, reg); }
outb(val, reg); static inline void vga_outl(u32 reg, u32 val) { outl(val, reg); }
}
static inline void vga_outw(u32 reg, u16 val)
{
outw(val, reg);
}
static inline void vga_outl(u32 reg, u32 val)
{
outl(val, reg);
}
#else #else
static inline u8 vga_inb(u32 reg) static inline u8 vga_inb(u32 reg) {
{ return inb(default_par.iobase + reg - 0x300);
return inb(fb_info.iobase + reg - 0x300);
} }
static inline u16 vga_inw(u32 reg) static inline u16 vga_inw(u32 reg) {
{ return inw(default_par.iobase + reg - 0x300);
return inw(fb_info.iobase + reg - 0x300);
} }
static inline u16 vga_inl(u32 reg) static inline u16 vga_inl(u32 reg) {
{ return inl(default_par.iobase + reg - 0x300);
return inl(fb_info.iobase + reg - 0x300);
} }
static inline void vga_outb(u32 reg, u8 val) {
static inline void vga_outb(u32 reg, u8 val) outb(val, default_par.iobase + reg - 0x300);
{
outb(val, fb_info.iobase + reg - 0x300);
} }
static inline void vga_outw(u32 reg, u16 val) static inline void vga_outw(u32 reg, u16 val) {
{ outw(val, default_par.iobase + reg - 0x300);
outw(val, fb_info.iobase + reg - 0x300);
} }
static inline void vga_outl(u32 reg, u32 val) static inline void vga_outl(u32 reg, u32 val) {
{ outl(val, default_par.iobase + reg - 0x300);
outl(val, fb_info.iobase + reg - 0x300);
} }
#endif #endif
static inline void gra_outb(u32 idx, u8 val) static inline void gra_outb(u32 idx, u8 val) {
{ vga_outb(GRA_I, idx); vga_outb(GRA_D, val);
vga_outb(GRA_I, idx);
vga_outb(GRA_D, val);
} }
static inline u8 gra_inb(u32 idx) static inline u8 gra_inb(u32 idx) {
{ vga_outb(GRA_I, idx); return vga_inb(GRA_D);
vga_outb(GRA_I, idx);
return vga_inb(GRA_D);
} }
static inline void seq_outb(u32 idx, u8 val) static inline void seq_outb(u32 idx, u8 val) {
{ vga_outb(SEQ_I, idx); vga_outb(SEQ_D, val);
vga_outb(SEQ_I, idx);
vga_outb(SEQ_D, val);
} }
static inline u8 seq_inb(u32 idx) static inline u8 seq_inb(u32 idx) {
{ vga_outb(SEQ_I, idx); return vga_inb(SEQ_D);
vga_outb(SEQ_I, idx);
return vga_inb(SEQ_D);
} }
static inline void crt_outb(u32 idx, u8 val) static inline void crt_outb(u32 idx, u8 val) {
{ vga_outb(CRT_I, idx); vga_outb(CRT_D, val);
vga_outb(CRT_I, idx);
vga_outb(CRT_D, val);
} }
static inline u8 crt_inb(u32 idx) static inline u8 crt_inb(u32 idx) {
{ vga_outb(CRT_I, idx); return vga_inb(CRT_D);
vga_outb(CRT_I, idx);
return vga_inb(CRT_D);
} }
static inline void att_outb(u32 idx, u8 val) static inline void att_outb(u32 idx, u8 val)
{ {
unsigned char tmp; unsigned char tmp;
tmp = vga_inb(IS1_R); tmp = vga_inb(IS1_R);
vga_outb(ATT_IW, idx); vga_outb(ATT_IW, idx);
vga_outb(ATT_IW, val); vga_outb(ATT_IW, val);
} }
static inline u8 att_inb(u32 idx) static inline u8 att_inb(u32 idx)
{ {
unsigned char tmp; unsigned char tmp;
tmp = vga_inb(IS1_R); tmp = vga_inb(IS1_R);
vga_outb(ATT_IW, idx); vga_outb(ATT_IW, idx);
return vga_inb(ATT_IW); return vga_inb(ATT_IW);
...@@ -452,6 +283,7 @@ static inline u8 att_inb(u32 idx) ...@@ -452,6 +283,7 @@ static inline u8 att_inb(u32 idx)
static inline void vga_disable_video(void) static inline void vga_disable_video(void)
{ {
unsigned char s; unsigned char s;
s = seq_inb(0x01) | 0x20; s = seq_inb(0x01) | 0x20;
seq_outb(0x00, 0x01); seq_outb(0x00, 0x01);
seq_outb(0x01, s); seq_outb(0x01, s);
...@@ -461,6 +293,7 @@ static inline void vga_disable_video(void) ...@@ -461,6 +293,7 @@ static inline void vga_disable_video(void)
static inline void vga_enable_video(void) static inline void vga_enable_video(void)
{ {
unsigned char s; unsigned char s;
s = seq_inb(0x01) & 0xdf; s = seq_inb(0x01) & 0xdf;
seq_outb(0x00, 0x01); seq_outb(0x00, 0x01);
seq_outb(0x01, s); seq_outb(0x01, s);
...@@ -479,21 +312,21 @@ static inline void vga_enable_palette(void) ...@@ -479,21 +312,21 @@ static inline void vga_enable_palette(void)
vga_outb(ATT_IW, 0x20); vga_outb(ATT_IW, 0x20);
} }
static inline u32 tdfx_inl(unsigned int reg) static inline u32 tdfx_inl(unsigned int reg)
{ {
return readl(fb_info.regbase_virt + reg); return readl(default_par.regbase_virt + reg);
} }
static inline void tdfx_outl(unsigned int reg, u32 val) static inline void tdfx_outl(unsigned int reg, u32 val)
{ {
writel(val, fb_info.regbase_virt + reg); writel(val, default_par.regbase_virt + reg);
} }
static inline void banshee_make_room(int size) static inline void banshee_make_room(int size)
{ {
while ((tdfx_inl(STATUS) & 0x1f) < size); while((tdfx_inl(STATUS) & 0x1f) < size);
} }
static inline void banshee_wait_idle(void) static inline void banshee_wait_idle(void)
{ {
int i = 0; int i = 0;
...@@ -501,10 +334,9 @@ static inline void banshee_wait_idle(void) ...@@ -501,10 +334,9 @@ static inline void banshee_wait_idle(void)
banshee_make_room(1); banshee_make_room(1);
tdfx_outl(COMMAND_3D, COMMAND_3D_NOP); tdfx_outl(COMMAND_3D, COMMAND_3D_NOP);
while (1) { while(1) {
i = (tdfx_inl(STATUS) & STATUS_BUSY) ? 0 : i + 1; i = (tdfx_inl(STATUS) & STATUS_BUSY) ? 0 : i + 1;
if (i == 3) if(i == 3) break;
break;
} }
} }
...@@ -512,249 +344,17 @@ static inline void banshee_wait_idle(void) ...@@ -512,249 +344,17 @@ static inline void banshee_wait_idle(void)
* Set the color of a palette entry in 8bpp mode * Set the color of a palette entry in 8bpp mode
*/ */
static inline void do_setpalentry(unsigned regno, u32 c) static inline void do_setpalentry(unsigned regno, u32 c)
{ {
banshee_make_room(2); banshee_make_room(2);
tdfx_outl(DACADDR, regno); tdfx_outl(DACADDR, regno);
tdfx_outl(DACDATA, c); tdfx_outl(DACDATA, c);
} }
/* static u32 do_calc_pll(int freq, int* freq_out)
* Set the starting position of the visible screen to var->yoffset
*/
static void do_pan_var(struct fb_var_screeninfo *var,
struct fb_info_tdfx *i)
{
u32 addr;
addr = var->yoffset * i->current_par.lpitch;
banshee_make_room(1);
tdfx_outl(VIDDESKSTART, addr);
}
/*
* Invert the hardware cursor image (timerfunc)
*/
static void do_flashcursor(unsigned long ptr)
{
struct fb_info_tdfx *i = (struct fb_info_tdfx *) ptr;
unsigned long flags;
spin_lock_irqsave(&i->DAClock, flags);
banshee_make_room(1);
tdfx_outl(VIDPROCCFG,
tdfx_inl(VIDPROCCFG) ^ VIDCFG_HWCURSOR_ENABLE);
i->cursor.timer.expires = jiffies + HZ / 2;
add_timer(&i->cursor.timer);
spin_unlock_irqrestore(&i->DAClock, flags);
}
/*
* FillRect 2D command (solidfill or invert (via ROP_XOR))
*/
static void do_fillrect(u32 x, u32 y, u32 w, u32 h,
u32 color, u32 stride, u32 bpp, u32 rop)
{
u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
banshee_make_room(5);
tdfx_outl(DSTFORMAT, fmt);
tdfx_outl(COLORFORE, color);
tdfx_outl(COMMAND_2D, COMMAND_2D_FILLRECT | (rop << 24));
tdfx_outl(DSTSIZE, w | (h << 16));
tdfx_outl(LAUNCH_2D, x | (y << 16));
banshee_wait_idle();
}
/*
* Screen-to-Screen BitBlt 2D command (for the bmove fb op.)
*/
static void do_bitblt(u32 curx,
u32 cury,
u32 dstx,
u32 dsty, u32 width, u32 height, u32 stride, u32 bpp)
{
u32 blitcmd = COMMAND_2D_S2S_BITBLT | (TDFX_ROP_COPY << 24);
u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
if (curx <= dstx) {
//-X
blitcmd |= BIT(14);
curx += width - 1;
dstx += width - 1;
}
if (cury <= dsty) {
//-Y
blitcmd |= BIT(15);
cury += height - 1;
dsty += height - 1;
}
banshee_make_room(6);
tdfx_outl(SRCFORMAT, fmt);
tdfx_outl(DSTFORMAT, fmt);
tdfx_outl(COMMAND_2D, blitcmd);
tdfx_outl(DSTSIZE, width | (height << 16));
tdfx_outl(DSTXY, dstx | (dsty << 16));
tdfx_outl(LAUNCH_2D, curx | (cury << 16));
banshee_wait_idle();
}
static void do_putc(u32 fgx, u32 bgx,
struct display *p, int c, int yy, int xx)
{
int i;
int stride = fb_info.current_par.lpitch;
u32 bpp = fb_info.current_par.bpp;
int fw = (fontwidth(p) + 7) >> 3;
u8 *chardata =
p->fontdata + (c & p->charmask) * fontheight(p) * fw;
u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
xx *= fontwidth(p);
yy *= fontheight(p);
banshee_make_room(8 + ((fontheight(p) * fw + 3) >> 2));
tdfx_outl(COLORFORE, fgx);
tdfx_outl(COLORBACK, bgx);
tdfx_outl(SRCXY, 0);
tdfx_outl(DSTXY, xx | (yy << 16));
tdfx_outl(COMMAND_2D,
COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24));
tdfx_outl(SRCFORMAT, 0x400000);
tdfx_outl(DSTFORMAT, fmt);
tdfx_outl(DSTSIZE, fontwidth(p) | (fontheight(p) << 16));
i = fontheight(p);
switch (fw) {
case 1:
while (i >= 4) {
tdfx_outl(LAUNCH_2D, *(u32 *) chardata);
chardata += 4;
i -= 4;
}
switch (i) {
case 0:
break;
case 1:
tdfx_outl(LAUNCH_2D, *chardata);
break;
case 2:
tdfx_outl(LAUNCH_2D, *(u16 *) chardata);
break;
case 3:
tdfx_outl(LAUNCH_2D,
*(u16 *) chardata | ((chardata[3]) <<
24));
break;
}
break;
case 2:
while (i >= 2) {
tdfx_outl(LAUNCH_2D, *(u32 *) chardata);
chardata += 4;
i -= 2;
}
if (i)
tdfx_outl(LAUNCH_2D, *(u16 *) chardata);
break;
default:
// Is there a font with width more that 16 pixels ?
for (i = fontheight(p); i > 0; i--) {
tdfx_outl(LAUNCH_2D, *(u32 *) chardata);
chardata += 4;
}
break;
}
banshee_wait_idle();
}
static void do_putcs(u32 fgx, u32 bgx,
struct display *p,
const unsigned short *s, int count, int yy, int xx)
{
int i;
int stride = fb_info.current_par.lpitch;
u32 bpp = fb_info.current_par.bpp;
int fw = (fontwidth(p) + 7) >> 3;
int w = fontwidth(p);
int h = fontheight(p);
int regsneed = 1 + ((h * fw + 3) >> 2);
u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
xx *= w;
yy = (yy * h) << 16;
banshee_make_room(8);
tdfx_outl(COMMAND_3D, COMMAND_3D_NOP);
tdfx_outl(COLORFORE, fgx);
tdfx_outl(COLORBACK, bgx);
tdfx_outl(SRCFORMAT, 0x400000);
tdfx_outl(DSTFORMAT, fmt);
tdfx_outl(DSTSIZE, w | (h << 16));
tdfx_outl(SRCXY, 0);
tdfx_outl(COMMAND_2D,
COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24));
while (count--) {
u8 *chardata =
p->fontdata + (scr_readw(s++) & p->charmask) * h * fw;
banshee_make_room(regsneed);
tdfx_outl(DSTXY, xx | yy);
xx += w;
i = h;
switch (fw) {
case 1:
while (i >= 4) {
tdfx_outl(LAUNCH_2D, *(u32 *) chardata);
chardata += 4;
i -= 4;
}
switch (i) {
case 0:
break;
case 1:
tdfx_outl(LAUNCH_2D, *chardata);
break;
case 2:
tdfx_outl(LAUNCH_2D, *(u16 *) chardata);
break;
case 3:
tdfx_outl(LAUNCH_2D,
*(u16 *) chardata |
((chardata[3]) << 24));
break;
}
break;
case 2:
while (i >= 2) {
tdfx_outl(LAUNCH_2D, *(u32 *) chardata);
chardata += 4;
i -= 2;
}
if (i)
tdfx_outl(LAUNCH_2D, *(u16 *) chardata);
break;
default:
// Is there a font with width more that 16 pixels ?
for (; i > 0; i--) {
tdfx_outl(LAUNCH_2D, *(u32 *) chardata);
chardata += 4;
}
break;
}
}
banshee_wait_idle();
}
static u32 do_calc_pll(int freq, int *freq_out)
{ {
int m, n, k, best_m, best_n, best_k, f_cur, best_error; int m, n, k, best_m, best_n, best_k, f_cur, best_error;
int fref = 14318; int fref = 14318;
/* this really could be done with more intelligence -- /* this really could be done with more intelligence --
255*63*4 = 64260 iterations is silly */ 255*63*4 = 64260 iterations is silly */
best_error = freq; best_error = freq;
...@@ -762,10 +362,9 @@ static u32 do_calc_pll(int freq, int *freq_out) ...@@ -762,10 +362,9 @@ static u32 do_calc_pll(int freq, int *freq_out)
for (n = 1; n < 256; n++) { for (n = 1; n < 256; n++) {
for (m = 1; m < 64; m++) { for (m = 1; m < 64; m++) {
for (k = 0; k < 4; k++) { for (k = 0; k < 4; k++) {
f_cur = f_cur = fref*(n + 2)/(m + 2)/(1 << k);
fref * (n + 2) / (m + 2) / (1 << k);
if (abs(f_cur - freq) < best_error) { if (abs(f_cur - freq) < best_error) {
best_error = abs(f_cur - freq); best_error = abs(f_cur-freq);
best_n = n; best_n = n;
best_m = m; best_m = m;
best_k = k; best_k = k;
...@@ -776,12 +375,11 @@ static u32 do_calc_pll(int freq, int *freq_out) ...@@ -776,12 +375,11 @@ static u32 do_calc_pll(int freq, int *freq_out)
n = best_n; n = best_n;
m = best_m; m = best_m;
k = best_k; k = best_k;
*freq_out = fref * (n + 2) / (m + 2) / (1 << k); *freq_out = fref*(n + 2)/(m + 2)/(1 << k);
return (n << 8) | (m << 2) | k; return (n << 8) | (m << 2) | k;
} }
static void do_write_regs(struct banshee_reg *reg) static void do_write_regs(struct banshee_reg* reg)
{ {
int i; int i;
...@@ -789,16 +387,16 @@ static void do_write_regs(struct banshee_reg *reg) ...@@ -789,16 +387,16 @@ static void do_write_regs(struct banshee_reg *reg)
tdfx_outl(MISCINIT1, tdfx_inl(MISCINIT1) | 0x01); tdfx_outl(MISCINIT1, tdfx_inl(MISCINIT1) | 0x01);
crt_outb(0x11, crt_inb(0x11) & 0x7f); /* CRT unprotect */ crt_outb(0x11, crt_inb(0x11) & 0x7f); /* CRT unprotect */
banshee_make_room(3); banshee_make_room(3);
tdfx_outl(VGAINIT1, reg->vgainit1 & 0x001FFFFF); tdfx_outl(VGAINIT1, reg->vgainit1 & 0x001FFFFF);
tdfx_outl(VIDPROCCFG, reg->vidcfg & ~0x00000001); tdfx_outl(VIDPROCCFG, reg->vidcfg & ~0x00000001);
#if 0 #if 0
tdfx_outl(PLLCTRL1, reg->mempll); tdfx_outl(PLLCTRL1, reg->mempll);
tdfx_outl(PLLCTRL2, reg->gfxpll); tdfx_outl(PLLCTRL2, reg->gfxpll);
#endif #endif
tdfx_outl(PLLCTRL0, reg->vidpll); tdfx_outl(PLLCTRL0, reg->vidpll);
vga_outb(MISC_W, reg->misc[0x00] | 0x01); vga_outb(MISC_W, reg->misc[0x00] | 0x01);
...@@ -821,56 +419,49 @@ static void do_write_regs(struct banshee_reg *reg) ...@@ -821,56 +419,49 @@ static void do_write_regs(struct banshee_reg *reg)
vga_enable_video(); vga_enable_video();
banshee_make_room(11); banshee_make_room(11);
tdfx_outl(VGAINIT0, reg->vgainit0); tdfx_outl(VGAINIT0, reg->vgainit0);
tdfx_outl(DACMODE, reg->dacmode); tdfx_outl(DACMODE, reg->dacmode);
tdfx_outl(VIDDESKSTRIDE, reg->stride); tdfx_outl(VIDDESKSTRIDE, reg->stride);
if (nohwcursor) { tdfx_outl(HWCURPATADDR, 0);
tdfx_outl(HWCURPATADDR, 0);
} else { tdfx_outl(VIDSCREENSIZE,reg->screensize);
tdfx_outl(HWCURPATADDR, reg->curspataddr); tdfx_outl(VIDDESKSTART, reg->startaddr);
tdfx_outl(HWCURC0, reg->cursc0); tdfx_outl(VIDPROCCFG, reg->vidcfg);
tdfx_outl(HWCURC1, reg->cursc1); tdfx_outl(VGAINIT1, reg->vgainit1);
tdfx_outl(HWCURLOC, reg->cursloc); tdfx_outl(MISCINIT0, reg->miscinit0);
}
tdfx_outl(VIDSCREENSIZE, reg->screensize);
tdfx_outl(VIDDESKSTART, reg->startaddr);
tdfx_outl(VIDPROCCFG, reg->vidcfg);
tdfx_outl(VGAINIT1, reg->vgainit1);
tdfx_outl(MISCINIT0, reg->miscinit0);
banshee_make_room(8); banshee_make_room(8);
tdfx_outl(SRCBASE, reg->srcbase); tdfx_outl(SRCBASE, reg->srcbase);
tdfx_outl(DSTBASE, reg->dstbase); tdfx_outl(DSTBASE, reg->dstbase);
tdfx_outl(COMMANDEXTRA_2D, 0); tdfx_outl(COMMANDEXTRA_2D, 0);
tdfx_outl(CLIP0MIN, 0); tdfx_outl(CLIP0MIN, 0);
tdfx_outl(CLIP0MAX, 0x0fff0fff); tdfx_outl(CLIP0MAX, 0x0fff0fff);
tdfx_outl(CLIP1MIN, 0); tdfx_outl(CLIP1MIN, 0);
tdfx_outl(CLIP1MAX, 0x0fff0fff); tdfx_outl(CLIP1MAX, 0x0fff0fff);
tdfx_outl(SRCXY, 0); tdfx_outl(SRCXY, 0);
banshee_wait_idle(); banshee_wait_idle();
} }
static unsigned long do_lfb_size(void) static unsigned long do_lfb_size(unsigned short dev_id)
{ {
u32 draminit0 = 0; u32 draminit0 = 0;
u32 draminit1 = 0; u32 draminit1 = 0;
u32 miscinit1 = 0; u32 miscinit1 = 0;
u32 lfbsize = 0; u32 lfbsize = 0;
int sgram_p = 0; int sgram_p = 0;
draminit0 = tdfx_inl(DRAMINIT0); draminit0 = tdfx_inl(DRAMINIT0);
draminit1 = tdfx_inl(DRAMINIT1); draminit1 = tdfx_inl(DRAMINIT1);
if ((fb_info.dev == PCI_DEVICE_ID_3DFX_BANSHEE) || if ((dev_id == PCI_DEVICE_ID_3DFX_BANSHEE) ||
(fb_info.dev == PCI_DEVICE_ID_3DFX_VOODOO3)) { (dev_id == PCI_DEVICE_ID_3DFX_VOODOO3)) {
sgram_p = (draminit1 & DRAMINIT1_MEM_SDRAM) ? 0 : 1; sgram_p = (draminit1 & DRAMINIT1_MEM_SDRAM) ? 0 : 1;
lfbsize = sgram_p ? lfbsize = sgram_p ?
(((draminit0 & DRAMINIT0_SGRAM_NUM) ? 2 : 1) * (((draminit0 & DRAMINIT0_SGRAM_NUM) ? 2 : 1) *
((draminit0 & DRAMINIT0_SGRAM_TYPE) ? 8 : 4) * 1024 * ((draminit0 & DRAMINIT0_SGRAM_TYPE) ? 8 : 4) * 1024 * 1024) :
1024) : 16 * 1024 * 1024; 16 * 1024 * 1024;
} else { } else {
/* Voodoo4/5 */ /* Voodoo4/5 */
u32 chips, psize, banks; u32 chips, psize, banks;
...@@ -880,316 +471,164 @@ static unsigned long do_lfb_size(void) ...@@ -880,316 +471,164 @@ static unsigned long do_lfb_size(void)
banks = ((draminit0 & (1 << 30)) == 0) ? 2 : 4; banks = ((draminit0 & (1 << 30)) == 0) ? 2 : 4;
lfbsize = chips * psize * banks; lfbsize = chips * psize * banks;
lfbsize <<= 20; lfbsize <<= 20;
} }
/* disable block writes for SDRAM (why?) */ /* disable block writes for SDRAM (why?) */
miscinit1 = tdfx_inl(MISCINIT1); miscinit1 = tdfx_inl(MISCINIT1);
miscinit1 |= sgram_p ? 0 : MISCINIT1_2DBLOCK_DIS; miscinit1 |= sgram_p ? 0 : MISCINIT1_2DBLOCK_DIS;
miscinit1 |= MISCINIT1_CLUT_INV; miscinit1 |= MISCINIT1_CLUT_INV;
banshee_make_room(1); banshee_make_room(1);
tdfx_outl(MISCINIT1, miscinit1); tdfx_outl(MISCINIT1, miscinit1);
return lfbsize; return lfbsize;
} }
/* ------------------------------------------------------------------------- /* ------------------------------------------------------------------------- */
* Hardware independent part, interface to the world
* ------------------------------------------------------------------------- */
#define tdfx_cfb24_putc tdfx_cfb32_putc
#define tdfx_cfb24_putcs tdfx_cfb32_putcs
#define tdfx_cfb24_clear tdfx_cfb32_clear
static void tdfx_cfbX_clear_margins(struct vc_data *conp, static int tdfxfb_check_var(struct fb_var_screeninfo *var,struct fb_info *info)
struct display *p, int bottom_only)
{ {
unsigned int cw = fontwidth(p); struct tdfx_par *par = (struct tdfx_par *) info->par;
unsigned int ch = fontheight(p); u32 lpitch;
unsigned int rw = p->var.xres % cw; // it be in a non-standard mode or not?
unsigned int bh = p->var.yres % ch;
unsigned int rs = p->var.xres - rw;
unsigned int bs = p->var.yres - bh;
if (!bottom_only && rw) {
do_fillrect(p->var.xoffset + rs, 0,
rw, p->var.yres_virtual, 0,
fb_info.current_par.lpitch,
fb_info.current_par.bpp, TDFX_ROP_COPY);
}
if (bh) { if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 &&
do_fillrect(p->var.xoffset, p->var.yoffset + bs, var->bits_per_pixel != 24 && var->bits_per_pixel != 32) {
rs, bh, 0, DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
fb_info.current_par.lpitch, return -EINVAL;
fb_info.current_par.bpp, TDFX_ROP_COPY);
} }
}
static void tdfx_cfbX_bmove(struct display *p,
int sy,
int sx, int dy, int dx, int height, int width)
{
do_bitblt(fontwidth(p) * sx,
fontheight(p) * sy,
fontwidth(p) * dx,
fontheight(p) * dy,
fontwidth(p) * width,
fontheight(p) * height,
fb_info.current_par.lpitch, fb_info.current_par.bpp);
}
static void tdfx_cfb8_putc(struct vc_data *conp,
struct display *p, int c, int yy, int xx)
{
u32 fgx, bgx;
fgx = attr_fgcol(p, c);
bgx = attr_bgcol(p, c);
do_putc(fgx, bgx, p, c, yy, xx);
}
static void tdfx_cfb16_putc(struct vc_data *conp, if (var->xres != var->xres_virtual) {
struct display *p, int c, int yy, int xx) DPRINTK("virtual x resolution != physical x resolution not supported\n");
{ return -EINVAL;
u32 fgx, bgx; }
fgx = ((u16 *) p->dispsw_data)[attr_fgcol(p, c)];
bgx = ((u16 *) p->dispsw_data)[attr_bgcol(p, c)];
do_putc(fgx, bgx, p, c, yy, xx);
}
static void tdfx_cfb32_putc(struct vc_data *conp,
struct display *p, int c, int yy, int xx)
{
u32 fgx, bgx;
fgx = ((u32 *) p->dispsw_data)[attr_fgcol(p, c)];
bgx = ((u32 *) p->dispsw_data)[attr_bgcol(p, c)];
do_putc(fgx, bgx, p, c, yy, xx);
}
static void tdfx_cfb8_putcs(struct vc_data *conp,
struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
u16 c = scr_readw(s);
u32 fgx = attr_fgcol(p, c);
u32 bgx = attr_bgcol(p, c);
do_putcs(fgx, bgx, p, s, count, yy, xx);
}
static void tdfx_cfb16_putcs(struct vc_data *conp,
struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
u16 c = scr_readw(s);
u32 fgx = ((u16 *) p->dispsw_data)[attr_fgcol(p, c)];
u32 bgx = ((u16 *) p->dispsw_data)[attr_bgcol(p, c)];
do_putcs(fgx, bgx, p, s, count, yy, xx);
}
static void tdfx_cfb32_putcs(struct vc_data *conp,
struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
u16 c = scr_readw(s);
u32 fgx = ((u32 *) p->dispsw_data)[attr_fgcol(p, c)];
u32 bgx = ((u32 *) p->dispsw_data)[attr_bgcol(p, c)];
do_putcs(fgx, bgx, p, s, count, yy, xx);
}
static void tdfx_cfb8_clear(struct vc_data *conp,
struct display *p,
int sy, int sx, int height, int width)
{
u32 bg;
bg = attr_bgcol_ec(p, conp);
do_fillrect(fontwidth(p) * sx,
fontheight(p) * sy,
fontwidth(p) * width,
fontheight(p) * height,
bg,
fb_info.current_par.lpitch,
fb_info.current_par.bpp, TDFX_ROP_COPY);
}
static void tdfx_cfb16_clear(struct vc_data *conp, if (var->yres > var->yres_virtual) {
struct display *p, DPRINTK("virtual y resolution < physical y resolution not possible\n");
int sy, int sx, int height, int width) return -EINVAL;
{ }
u32 bg;
bg = ((u16 *) p->dispsw_data)[attr_bgcol_ec(p, conp)];
do_fillrect(fontwidth(p) * sx,
fontheight(p) * sy,
fontwidth(p) * width,
fontheight(p) * height,
bg,
fb_info.current_par.lpitch,
fb_info.current_par.bpp, TDFX_ROP_COPY);
}
static void tdfx_cfb32_clear(struct vc_data *conp, if (var->xoffset) {
struct display *p, DPRINTK("xoffset not supported\n");
int sy, int sx, int height, int width) return -EINVAL;
{ }
u32 bg;
bg = ((u32 *) p->dispsw_data)[attr_bgcol_ec(p, conp)];
do_fillrect(fontwidth(p) * sx,
fontheight(p) * sy,
fontwidth(p) * width,
fontheight(p) * height,
bg,
fb_info.current_par.lpitch,
fb_info.current_par.bpp, TDFX_ROP_COPY);
}
static void tdfx_cfbX_revc(struct display *p, int xx, int yy)
{
int bpp = fb_info.current_par.bpp;
do_fillrect(xx * fontwidth(p), yy * fontheight(p), /* fixme: does Voodoo3 support interlace? Banshee doesn't */
fontwidth(p), fontheight(p), if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
(bpp == 8) ? 0x0f : 0xffffffff, DPRINTK("interlace not supported\n");
fb_info.current_par.lpitch, bpp, TDFX_ROP_XOR); return -EINVAL;
}
} var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
static void tdfx_cfbX_cursor(struct display *p, int mode, int x, int y) lpitch = var->xres * ((var->bits_per_pixel + 7)>>3);
{
unsigned long flags; if (var->xres < 320 || var->xres > 2048) {
int tip; DPRINTK("width not supported: %u\n", var->xres);
struct fb_info_tdfx *info = (struct fb_info_tdfx *) p->fb_info; return -EINVAL;
tip = p->conp->vc_cursor_type & CUR_HWMASK;
if (mode == CM_ERASE) {
if (info->cursor.state != CM_ERASE) {
spin_lock_irqsave(&info->DAClock, flags);
info->cursor.state = CM_ERASE;
del_timer(&(info->cursor.timer));
tdfx_outl(VIDPROCCFG, info->cursor.disable);
spin_unlock_irqrestore(&info->DAClock, flags);
}
return;
} }
if ((p->conp->vc_cursor_type & CUR_HWMASK) != info->cursor.type)
tdfxfb_createcursor(p); if (var->yres < 200 || var->yres > 2048) {
x *= fontwidth(p); DPRINTK("height not supported: %u\n", var->yres);
y *= fontheight(p); return -EINVAL;
y -= p->var.yoffset; }
spin_lock_irqsave(&info->DAClock, flags);
if ((x != info->cursor.x) || if (lpitch * var->yres_virtual > info->fix.smem_len) {
(y != info->cursor.y) || (info->cursor.redraw)) { DPRINTK("no memory for screen (%ux%ux%u)\n",
info->cursor.x = x; var->xres, var->yres_virtual, var->bits_per_pixel);
info->cursor.y = y; return -EINVAL;
info->cursor.redraw = 0; }
x += 63;
y += 63; if (PICOS2KHZ(var->pixclock) > par->max_pixclock) {
banshee_make_room(2); DPRINTK("pixclock too high (%ldKHz)\n",PICOS2KHZ(var->pixclock));
tdfx_outl(VIDPROCCFG, info->cursor.disable); return -EINVAL;
tdfx_outl(HWCURLOC, (y << 16) + x);
/* fix cursor color - XFree86 forgets to restore it properly */
tdfx_outl(HWCURC0, 0);
tdfx_outl(HWCURC1, 0xffffff);
} }
info->cursor.state = CM_DRAW;
mod_timer(&info->cursor.timer, jiffies + HZ / 2);
banshee_make_room(1);
tdfx_outl(VIDPROCCFG, info->cursor.enable);
spin_unlock_irqrestore(&info->DAClock, flags);
return;
}
#ifdef FBCON_HAS_CFB8
static struct display_switch fbcon_banshee8 = {
setup:fbcon_cfb8_setup,
bmove:tdfx_cfbX_bmove,
clear:tdfx_cfb8_clear,
putc:tdfx_cfb8_putc,
putcs:tdfx_cfb8_putcs,
revc:tdfx_cfbX_revc,
cursor:tdfx_cfbX_cursor,
clear_margins:tdfx_cfbX_clear_margins,
fontwidthmask:FONTWIDTHRANGE(8, 12)
};
#endif
#ifdef FBCON_HAS_CFB16
static struct display_switch fbcon_banshee16 = {
setup:fbcon_cfb16_setup,
bmove:tdfx_cfbX_bmove,
clear:tdfx_cfb16_clear,
putc:tdfx_cfb16_putc,
putcs:tdfx_cfb16_putcs,
revc:tdfx_cfbX_revc,
cursor:tdfx_cfbX_cursor,
clear_margins:tdfx_cfbX_clear_margins,
fontwidthmask:FONTWIDTHRANGE(8, 12)
};
#endif
#ifdef FBCON_HAS_CFB24
static struct display_switch fbcon_banshee24 = {
setup:fbcon_cfb24_setup,
bmove:tdfx_cfbX_bmove,
clear:tdfx_cfb24_clear,
putc:tdfx_cfb24_putc,
putcs:tdfx_cfb24_putcs,
revc:tdfx_cfbX_revc,
cursor:tdfx_cfbX_cursor,
clear_margins:tdfx_cfbX_clear_margins,
fontwidthmask:FONTWIDTHRANGE(8, 12)
};
#endif
#ifdef FBCON_HAS_CFB32
static struct display_switch fbcon_banshee32 = {
setup:fbcon_cfb32_setup,
bmove:tdfx_cfbX_bmove,
clear:tdfx_cfb32_clear,
putc:tdfx_cfb32_putc,
putcs:tdfx_cfb32_putcs,
revc:tdfx_cfbX_revc,
cursor:tdfx_cfbX_cursor,
clear_margins:tdfx_cfbX_clear_margins,
fontwidthmask:FONTWIDTHRANGE(8, 12)
};
#endif
/* ------------------------------------------------------------------------- */ switch(var->bits_per_pixel) {
case 8:
var->red.length = var->green.length = var->blue.length = 8;
break;
case 16:
var->red.offset = 11;
var->red.length = 5;
var->green.offset = 5;
var->green.length = 6;
var->blue.offset = 0;
var->blue.length = 5;
break;
case 24:
var->red.offset=16;
var->green.offset=8;
var->blue.offset=0;
var->red.length = var->green.length = var->blue.length = 8;
case 32:
var->red.offset = 16;
var->green.offset = 8;
var->blue.offset = 0;
var->red.length = var->green.length = var->blue.length = 8;
break;
}
var->height = var->width = -1;
var->accel_flags = FB_ACCELF_TEXT;
DPRINTK("Checking graphics mode at %dx%d depth %d\n", var->xres, var->yres, var->bits_per_pixel);
return 0;
}
static void tdfxfb_set_par(const struct tdfxfb_par *par, static int tdfxfb_set_par(struct fb_info *info)
struct fb_info_tdfx *info)
{ {
struct fb_info_tdfx *i = (struct fb_info_tdfx *) info; struct tdfx_par *par = (struct tdfx_par *) info->par;
struct banshee_reg reg; u32 hdispend, hsyncsta, hsyncend, htotal;
u32 cpp;
u32 hd, hs, he, ht, hbs, hbe; u32 hd, hs, he, ht, hbs, hbe;
u32 vd, vs, ve, vt, vbs, vbe; u32 vd, vs, ve, vt, vbs, vbe;
u32 wd; struct banshee_reg reg;
int fout; int fout, freq;
int freq; u32 wd, cpp;
info->cmap.len = (info->var.bits_per_pixel == 8) ? 256 : 16;
par->baseline = 0;
memset(&reg, 0, sizeof(reg)); memset(&reg, 0, sizeof(reg));
cpp = (info->var.bits_per_pixel + 7)/8;
reg.vidcfg = VIDCFG_VIDPROC_ENABLE | VIDCFG_DESK_ENABLE | VIDCFG_CURS_X11 | ((cpp - 1) << VIDCFG_PIXFMT_SHIFT) | (cpp != 1 ? VIDCFG_CLUT_BYPASS : 0);
/* PLL settings */
freq = PICOS2KHZ(info->var.pixclock);
cpp = (par->bpp + 7) / 8; reg.dacmode = 0;
reg.vidcfg &= ~VIDCFG_2X;
wd = (par->hdispend >> 3) - 1; hdispend = info->var.xres;
hsyncsta = hdispend + info->var.right_margin;
hsyncend = hsyncsta + info->var.hsync_len;
htotal = hsyncend + info->var.left_margin;
hd = (par->hdispend >> 3) - 1; if (freq > par->max_pixclock/2) {
hs = (par->hsyncsta >> 3) - 1; freq = freq > par->max_pixclock ? par->max_pixclock : freq;
he = (par->hsyncend >> 3) - 1; reg.dacmode |= DACMODE_2X;
ht = (par->htotal >> 3) - 1; reg.vidcfg |= VIDCFG_2X;
hdispend >>= 1;
hsyncsta >>= 1;
hsyncend >>= 1;
htotal >>= 1;
}
hd = wd = (hdispend >> 3) - 1;
hs = (hsyncsta >> 3) - 1;
he = (hsyncend >> 3) - 1;
ht = (htotal >> 3) - 1;
hbs = hd; hbs = hd;
hbe = ht; hbe = ht;
vd = par->vdispend - 1; vbs = vd = info->var.yres - 1;
vs = par->vsyncsta - 1; vs = vd + info->var.lower_margin;
ve = par->vsyncend - 1; ve = vs + info->var.vsync_len;
vt = par->vtotal - 2; vbe = vt = ve + info->var.upper_margin - 1;
vbs = vd;
vbe = vt;
/* this is all pretty standard VGA register stuffing */ /* this is all pretty standard VGA register stuffing */
reg.misc[0x00] = reg.misc[0x00] = 0x0f |
0x0f | (info->var.xres < 400 ? 0xa0 :
(par->hdispend < 400 ? 0xa0 : info->var.xres < 480 ? 0x60 :
par->hdispend < 480 ? 0x60 : info->var.xres < 768 ? 0xe0 : 0x20);
par->hdispend < 768 ? 0xe0 : 0x20);
reg.gra[0x00] = 0x00; reg.gra[0x00] = 0x00;
reg.gra[0x01] = 0x00; reg.gra[0x01] = 0x00;
reg.gra[0x02] = 0x00; reg.gra[0x02] = 0x00;
...@@ -1223,7 +662,7 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par, ...@@ -1223,7 +662,7 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
reg.att[0x14] = 0x00; reg.att[0x14] = 0x00;
reg.seq[0x00] = 0x03; reg.seq[0x00] = 0x03;
reg.seq[0x01] = 0x01; /* fixme: clkdiv2? */ reg.seq[0x01] = 0x01; /* fixme: clkdiv2? */
reg.seq[0x02] = 0x0f; reg.seq[0x02] = 0x0f;
reg.seq[0x03] = 0x00; reg.seq[0x03] = 0x00;
reg.seq[0x04] = 0x0e; reg.seq[0x04] = 0x0e;
...@@ -1233,18 +672,17 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par, ...@@ -1233,18 +672,17 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
reg.crt[0x02] = hbs; reg.crt[0x02] = hbs;
reg.crt[0x03] = 0x80 | (hbe & 0x1f); reg.crt[0x03] = 0x80 | (hbe & 0x1f);
reg.crt[0x04] = hs; reg.crt[0x04] = hs;
reg.crt[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f); reg.crt[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
reg.crt[0x06] = vt; reg.crt[0x06] = vt;
reg.crt[0x07] = reg.crt[0x07] = ((vs & 0x200) >> 2) |
((vs & 0x200) >> 2) | ((vd & 0x200) >> 3) |
((vd & 0x200) >> 3) | ((vt & 0x200) >> 4) | 0x10 |
((vt & 0x200) >> 4) | ((vbs & 0x100) >> 5) |
0x10 | ((vs & 0x100) >> 6) |
((vbs & 0x100) >> 5) | ((vd & 0x100) >> 7) |
((vs & 0x100) >> 6) | ((vt & 0x100) >> 8);
((vd & 0x100) >> 7) | ((vt & 0x100) >> 8);
reg.crt[0x08] = 0x00; reg.crt[0x08] = 0x00;
reg.crt[0x09] = 0x40 | ((vbs & 0x200) >> 4); reg.crt[0x09] = 0x40 | ((vbs & 0x200) >> 4);
reg.crt[0x0a] = 0x00; reg.crt[0x0a] = 0x00;
reg.crt[0x0b] = 0x00; reg.crt[0x0b] = 0x00;
reg.crt[0x0c] = 0x00; reg.crt[0x0c] = 0x00;
...@@ -1252,63 +690,53 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par, ...@@ -1252,63 +690,53 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
reg.crt[0x0e] = 0x00; reg.crt[0x0e] = 0x00;
reg.crt[0x0f] = 0x00; reg.crt[0x0f] = 0x00;
reg.crt[0x10] = vs; reg.crt[0x10] = vs;
reg.crt[0x11] = (ve & 0x0f) | 0x20; reg.crt[0x11] = (ve & 0x0f) | 0x20;
reg.crt[0x12] = vd; reg.crt[0x12] = vd;
reg.crt[0x13] = wd; reg.crt[0x13] = wd;
reg.crt[0x14] = 0x00; reg.crt[0x14] = 0x00;
reg.crt[0x15] = vbs; reg.crt[0x15] = vbs;
reg.crt[0x16] = vbe + 1; reg.crt[0x16] = vbe + 1;
reg.crt[0x17] = 0xc3; reg.crt[0x17] = 0xc3;
reg.crt[0x18] = 0xff; reg.crt[0x18] = 0xff;
/* Banshee's nonvga stuff */ /* Banshee's nonvga stuff */
reg.ext[0x00] = (((ht & 0x100) >> 8) | reg.ext[0x00] = (((ht & 0x100) >> 8) |
((hd & 0x100) >> 6) | ((hd & 0x100) >> 6) |
((hbs & 0x100) >> 4) | ((hbs & 0x100) >> 4) |
((hbe & 0x40) >> 1) | ((hbe & 0x40) >> 1) |
((hs & 0x100) >> 2) | ((he & 0x20) << 2)); ((hs & 0x100) >> 2) |
reg.ext[0x01] = (((vt & 0x400) >> 10) | ((he & 0x20) << 2));
((vd & 0x400) >> 8) | reg.ext[0x01] = (((vt & 0x400) >> 10) |
((vbs & 0x400) >> 6) | ((vbe & 0x400) >> 4)); ((vd & 0x400) >> 8) |
((vbs & 0x400) >> 6) |
reg.vgainit0 = ((vbe & 0x400) >> 4));
VGAINIT0_8BIT_DAC |
VGAINIT0_EXT_ENABLE | reg.vgainit0 = VGAINIT0_8BIT_DAC |
VGAINIT0_WAKEUP_3C3 | VGAINIT0_EXT_ENABLE |
VGAINIT0_ALT_READBACK | VGAINIT0_EXTSHIFTOUT; VGAINIT0_WAKEUP_3C3 |
VGAINIT0_ALT_READBACK |
VGAINIT0_EXTSHIFTOUT;
reg.vgainit1 = tdfx_inl(VGAINIT1) & 0x1fffff; reg.vgainit1 = tdfx_inl(VGAINIT1) & 0x1fffff;
reg.vidcfg = reg.cursloc = 0;
VIDCFG_VIDPROC_ENABLE |
VIDCFG_DESK_ENABLE | reg.cursc0 = 0;
VIDCFG_CURS_X11 | reg.cursc1 = 0xffffff;
((cpp - 1) << VIDCFG_PIXFMT_SHIFT) |
(cpp != 1 ? VIDCFG_CLUT_BYPASS : 0); reg.stride = info->var.xres * cpp;
fb_info.cursor.enable = reg.vidcfg | VIDCFG_HWCURSOR_ENABLE;
fb_info.cursor.disable = reg.vidcfg;
reg.stride = par->width * cpp;
reg.cursloc = 0;
reg.cursc0 = 0;
reg.cursc1 = 0xffffff;
reg.curspataddr = fb_info.cursor.cursorimage;
reg.startaddr = par->baseline * reg.stride; reg.startaddr = par->baseline * reg.stride;
reg.srcbase = reg.startaddr; reg.srcbase = reg.startaddr;
reg.dstbase = reg.startaddr; reg.dstbase = reg.startaddr;
/* PLL settings */ /* PLL settings */
freq = par->pixclock; freq = PICOS2KHZ(info->var.pixclock);
reg.dacmode &= ~DACMODE_2X; reg.dacmode &= ~DACMODE_2X;
reg.vidcfg &= ~VIDCFG_2X; reg.vidcfg &= ~VIDCFG_2X;
if (freq > i->max_pixclock / 2) { if (freq > par->max_pixclock/2) {
freq = freq > i->max_pixclock ? i->max_pixclock : freq; freq = freq > par->max_pixclock ? par->max_pixclock : freq;
reg.dacmode |= DACMODE_2X; reg.dacmode |= DACMODE_2X;
reg.vidcfg |= VIDCFG_2X; reg.vidcfg |= VIDCFG_2X;
} }
reg.vidpll = do_calc_pll(freq, &fout); reg.vidpll = do_calc_pll(freq, &fout);
#if 0 #if 0
...@@ -1316,648 +744,418 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par, ...@@ -1316,648 +744,418 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
reg.gfxpll = do_calc_pll(..., &fout); reg.gfxpll = do_calc_pll(..., &fout);
#endif #endif
reg.screensize = par->width | (par->height << 12); reg.screensize = info->var.xres | (info->var.yres << 12);
reg.vidcfg &= ~VIDCFG_HALF_MODE; reg.vidcfg &= ~VIDCFG_HALF_MODE;
reg.miscinit0 = tdfx_inl(MISCINIT0); reg.miscinit0 = tdfx_inl(MISCINIT0);
#if defined(__BIG_ENDIAN) #if defined(__BIG_ENDIAN)
switch (par->bpp) { switch (info->var.bits_per_pixel) {
case 8: case 8:
reg.miscinit0 &= ~(1 << 30); reg.miscinit0 &= ~(1 << 30);
reg.miscinit0 &= ~(1 << 31); reg.miscinit0 &= ~(1 << 31);
break; break;
case 16: case 16:
reg.miscinit0 |= (1 << 30); reg.miscinit0 |= (1 << 30);
reg.miscinit0 |= (1 << 31); reg.miscinit0 |= (1 << 31);
break; break;
case 24: case 24:
case 32: case 32:
reg.miscinit0 |= (1 << 30); reg.miscinit0 |= (1 << 30);
reg.miscinit0 &= ~(1 << 31); reg.miscinit0 &= ~(1 << 31);
break; break;
} }
#endif #endif
do_write_regs(&reg); do_write_regs(&reg);
i->current_par = *par; /* Now change fb_fix_screeninfo according to changes in par */
info->fix.line_length = info->var.xres * ((info->var.bits_per_pixel + 7)>>3);
info->fix.visual = (info->var.bits_per_pixel == 8)
? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_TRUECOLOR;
DPRINTK("Graphics mode is now set at %dx%d depth %d\n", info->var.xres, info->var.yres, info->var.bits_per_pixel);
return 0;
} }
static int tdfxfb_decode_var(const struct fb_var_screeninfo *var, static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
struct tdfxfb_par *par, unsigned blue,unsigned transp,struct fb_info *info)
const struct fb_info_tdfx *info)
{ {
struct fb_info_tdfx *i = (struct fb_info_tdfx *) info; u32 rgbcol;
if (var->bits_per_pixel != 8 && if (regno >= info->cmap.len) return 1;
var->bits_per_pixel != 16 &&
var->bits_per_pixel != 24 && var->bits_per_pixel != 32) { switch (info->fix.visual) {
DPRINTK("depth not supported: %u\n", var->bits_per_pixel); case FB_VISUAL_PSEUDOCOLOR:
return -EINVAL; rgbcol =(((u32)red & 0xff00) << 8) |
} (((u32)green & 0xff00) << 0) |
(((u32)blue & 0xff00) >> 8);
if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { do_setpalentry(regno, rgbcol);
DPRINTK("interlace not supported\n"); break;
return -EINVAL; /* Truecolor has no hardware color palettes. */
} case FB_VISUAL_TRUECOLOR:
rgbcol = (red << info->var.red.offset) |
if (var->xoffset) { (green << info->var.green.offset) |
DPRINTK("xoffset not supported\n"); (blue << info->var.blue.offset) |
return -EINVAL; (transp << info->var.transp.offset);
} if (info->var.bits_per_pixel <= 16)
((u16*)(info->pseudo_palette))[regno] = rgbcol;
if (var->xres != var->xres_virtual) { else
DPRINTK ((u32*)(info->pseudo_palette))[regno] = rgbcol;
("virtual x resolution != physical x resolution not supported\n"); break;
return -EINVAL; default:
} DPRINTK("bad depth %u\n", info->var.bits_per_pixel);
break;
if (var->yres > var->yres_virtual) {
DPRINTK
("virtual y resolution < physical y resolution not possible\n");
return -EINVAL;
} }
return 0;
}
/* fixme: does Voodoo3 support interlace? Banshee doesn't */ /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { static int tdfxfb_blank(int blank, struct fb_info *info)
DPRINTK("interlace not supported\n"); {
return -EINVAL; u32 dacmode, state = 0, vgablank = 0;
}
memset(par, 0, sizeof(struct tdfxfb_par)); dacmode = tdfx_inl(DACMODE);
switch (i->dev) {
case PCI_DEVICE_ID_3DFX_BANSHEE:
case PCI_DEVICE_ID_3DFX_VOODOO3:
case PCI_DEVICE_ID_3DFX_VOODOO5:
par->width = (var->xres + 15) & ~15; /* could sometimes be 8 */
par->width_virt = par->width;
par->height = var->yres;
par->height_virt = var->yres_virtual;
par->bpp = var->bits_per_pixel;
par->ppitch = var->bits_per_pixel;
par->lpitch = par->width * ((par->ppitch + 7) >> 3);
par->cmap_len = (par->bpp == 8) ? 256 : 16;
par->baseline = 0;
if (par->width < 320 || par->width > 2048) {
DPRINTK("width not supported: %u\n", par->width);
return -EINVAL;
}
if (par->height < 200 || par->height > 2048) {
DPRINTK("height not supported: %u\n", par->height);
return -EINVAL;
}
if (par->lpitch * par->height_virt > i->bufbase_size) {
DPRINTK("no memory for screen (%ux%ux%u)\n",
par->width, par->height_virt, par->bpp);
return -EINVAL;
}
par->pixclock = PICOS2KHZ(var->pixclock);
if (par->pixclock > i->max_pixclock) {
DPRINTK("pixclock too high (%uKHz)\n",
par->pixclock);
return -EINVAL;
}
par->hdispend = var->xres; switch (blank) {
par->hsyncsta = par->hdispend + var->right_margin; case 0: /* Screen: On; HSync: On, VSync: On */
par->hsyncend = par->hsyncsta + var->hsync_len; state = 0;
par->htotal = par->hsyncend + var->left_margin; vgablank = 0;
break;
par->vdispend = var->yres; case 1: /* Screen: Off; HSync: On, VSync: On */
par->vsyncsta = par->vdispend + var->lower_margin; state = 0;
par->vsyncend = par->vsyncsta + var->vsync_len; vgablank = 1;
par->vtotal = par->vsyncend + var->upper_margin; break;
case 2: /* Screen: Off; HSync: On, VSync: Off */
if (var->sync & FB_SYNC_HOR_HIGH_ACT) state = BIT(3);
par->video |= TDFXF_HSYNC_ACT_HIGH; vgablank = 1;
else break;
par->video |= TDFXF_HSYNC_ACT_LOW; case 3: /* Screen: Off; HSync: Off, VSync: On */
if (var->sync & FB_SYNC_VERT_HIGH_ACT) state = BIT(1);
par->video |= TDFXF_VSYNC_ACT_HIGH; vgablank = 1;
else break;
par->video |= TDFXF_VSYNC_ACT_LOW; case 4: /* Screen: Off; HSync: Off, VSync: Off */
if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) state = BIT(1) | BIT(3);
par->video |= TDFXF_LINE_DOUBLE; vgablank = 1;
if (var->activate == FB_ACTIVATE_NOW) break;
par->video |= TDFXF_VIDEO_ENABLE;
} }
if (var->accel_flags & FB_ACCELF_TEXT) dacmode &= ~(BIT(1) | BIT(3));
par->accel_flags = FB_ACCELF_TEXT; dacmode |= state;
banshee_make_room(1);
tdfx_outl(DACMODE, dacmode);
if (vgablank)
vga_disable_video();
else else
par->accel_flags = 0; vga_enable_video();
return 0; return 0;
} }
static int tdfxfb_encode_var(struct fb_var_screeninfo *var, /*
const struct tdfxfb_par *par, * Set the starting position of the visible screen to var->yoffset
const struct fb_info_tdfx *info) */
static int tdfxfb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{ {
struct fb_var_screeninfo v; u32 addr;
memset(&v, 0, sizeof(struct fb_var_screeninfo));
v.xres_virtual = par->width_virt;
v.yres_virtual = par->height_virt;
v.xres = par->width;
v.yres = par->height;
v.right_margin = par->hsyncsta - par->hdispend;
v.hsync_len = par->hsyncend - par->hsyncsta;
v.left_margin = par->htotal - par->hsyncend;
v.lower_margin = par->vsyncsta - par->vdispend;
v.vsync_len = par->vsyncend - par->vsyncsta;
v.upper_margin = par->vtotal - par->vsyncend;
v.bits_per_pixel = par->bpp;
switch (par->bpp) {
case 8:
v.red.length = v.green.length = v.blue.length = 8;
break;
case 16:
v.red.offset = 11;
v.red.length = 5;
v.green.offset = 5;
v.green.length = 6;
v.blue.offset = 0;
v.blue.length = 5;
break;
case 24:
v.red.offset = 16;
v.green.offset = 8;
v.blue.offset = 0;
v.red.length = v.green.length = v.blue.length = 8;
case 32:
v.red.offset = 16;
v.green.offset = 8;
v.blue.offset = 0;
v.red.length = v.green.length = v.blue.length = 8;
break;
}
v.height = v.width = -1;
v.pixclock = KHZ2PICOS(par->pixclock);
if ((par->video & TDFXF_HSYNC_MASK) == TDFXF_HSYNC_ACT_HIGH)
v.sync |= FB_SYNC_HOR_HIGH_ACT;
if ((par->video & TDFXF_VSYNC_MASK) == TDFXF_VSYNC_ACT_HIGH)
v.sync |= FB_SYNC_VERT_HIGH_ACT;
if (par->video & TDFXF_LINE_DOUBLE)
v.vmode = FB_VMODE_DOUBLE;
*var = v;
return 0;
}
static int tdfxfb_encode_fix(struct fb_fix_screeninfo *fix, if (nopan || var->xoffset || (var->yoffset > var->yres_virtual))
const struct tdfxfb_par *par, return -EINVAL;
const struct fb_info_tdfx *info) if ((var->yoffset + var->yres > var->yres_virtual && nowrap))
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
switch (info->dev) {
case PCI_DEVICE_ID_3DFX_BANSHEE:
strcpy(fix->id, "3Dfx Banshee");
break;
case PCI_DEVICE_ID_3DFX_VOODOO3:
strcpy(fix->id, "3Dfx Voodoo3");
break;
case PCI_DEVICE_ID_3DFX_VOODOO5:
strcpy(fix->id, "3Dfx Voodoo5");
break;
default:
return -EINVAL; return -EINVAL;
}
fix->smem_start = info->bufbase_phys;
fix->smem_len = info->bufbase_size;
fix->mmio_start = info->regbase_phys;
fix->mmio_len = info->regbase_size;
fix->accel = FB_ACCEL_3DFX_BANSHEE;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
fix->line_length = par->lpitch;
fix->visual = (par->bpp == 8)
? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
fix->xpanstep = 0;
fix->ypanstep = nopan ? 0 : 1;
fix->ywrapstep = nowrap ? 0 : 1;
return 0;
}
static int tdfxfb_get_fix(struct fb_fix_screeninfo *fix,
int con, struct fb_info *fb)
{
const struct fb_info_tdfx *info = (struct fb_info_tdfx *) fb;
struct tdfxfb_par par;
if (con == -1) addr = var->yoffset * info->fix.line_length;
par = info->default_par; banshee_make_room(1);
else tdfx_outl(VIDDESKSTART, addr);
tdfxfb_decode_var(&fb_display[con].var, &par, info);
tdfxfb_encode_fix(fix, &par, info); info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
return 0; return 0;
} }
static int tdfxfb_get_var(struct fb_var_screeninfo *var, /*
int con, struct fb_info *fb) * FillRect 2D command (solidfill or invert (via ROP_XOR))
{ */
const struct fb_info_tdfx *info = (struct fb_info_tdfx *) fb; static void tdfxfb_fillrect(struct fb_info *info, struct fb_fillrect *rect)
{
u32 bpp = info->var.bits_per_pixel;
u32 stride = info->fix.line_length;
u32 fmt= stride | ((bpp+((bpp==8) ? 0 : 8)) << 13);
int tdfx_rop;
if (rect->rop == ROP_COPY)
tdfx_rop = TDFX_ROP_COPY;
else
tdfx_rop = TDFX_ROP_XOR;
if (con == -1) banshee_make_room(5);
tdfxfb_encode_var(var, &info->default_par, info); tdfx_outl(DSTFORMAT, fmt);
else tdfx_outl(COLORFORE, rect->color);
*var = fb_display[con].var; tdfx_outl(COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));
return 0; tdfx_outl(DSTSIZE, rect->width | (rect->height << 16));
tdfx_outl(LAUNCH_2D, rect->dx | (rect->dy << 16));
banshee_wait_idle();
} }
static void tdfxfb_set_dispsw(struct display *disp, /*
struct fb_info_tdfx *info, * Screen-to-Screen BitBlt 2D command (for the bmove fb op.)
int bpp, int accel) */
static void tdfxfb_copyarea(struct fb_info *info, struct fb_copyarea *area)
{ {
u32 bpp = info->var.bits_per_pixel;
if (disp->dispsw && disp->conp) u32 stride = info->fix.line_length;
fb_con.con_cursor(disp->conp, CM_ERASE); u32 blitcmd = COMMAND_2D_S2S_BITBLT | (TDFX_ROP_COPY << 24);
switch (bpp) { u32 fmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13);
#ifdef FBCON_HAS_CFB8
case 8: if (area->sx <= area->dx) {
disp->dispsw = noaccel ? &fbcon_cfb8 : &fbcon_banshee8; //-X
if (nohwcursor) blitcmd |= BIT(14);
fbcon_banshee8.cursor = NULL; area->sx += area->width - 1;
break; area->dx += area->width - 1;
#endif
#ifdef FBCON_HAS_CFB16
case 16:
disp->dispsw = noaccel ? &fbcon_cfb16 : &fbcon_banshee16;
disp->dispsw_data = info->fbcon_cmap.cfb16;
if (nohwcursor)
fbcon_banshee16.cursor = NULL;
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
disp->dispsw = noaccel ? &fbcon_cfb24 : &fbcon_banshee24;
disp->dispsw_data = info->fbcon_cmap.cfb24;
if (nohwcursor)
fbcon_banshee24.cursor = NULL;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
disp->dispsw = noaccel ? &fbcon_cfb32 : &fbcon_banshee32;
disp->dispsw_data = info->fbcon_cmap.cfb32;
if (nohwcursor)
fbcon_banshee32.cursor = NULL;
break;
#endif
default:
disp->dispsw = &fbcon_dummy;
} }
if (area->sy <= area->dy) {
} //-Y
blitcmd |= BIT(15);
static int tdfxfb_set_var(struct fb_var_screeninfo *var, area->sy += area->height - 1;
int con, struct fb_info *fb) area->dy += area->height - 1;
{
struct fb_info_tdfx *info = (struct fb_info_tdfx *) fb;
struct tdfxfb_par par;
struct display *display;
int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel, accel,
err;
int activate = var->activate;
int j, k;
if (con >= 0)
display = &fb_display[con];
else
display = fb->disp; /* used during initialization */
if ((err = tdfxfb_decode_var(var, &par, info)))
return err;
tdfxfb_encode_var(var, &par, info);
if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
oldxres = display->var.xres;
oldyres = display->var.yres;
oldvxres = display->var.xres_virtual;
oldvyres = display->var.yres_virtual;
oldbpp = display->var.bits_per_pixel;
oldaccel = display->var.accel_flags;
display->var = *var;
if (con < 0 ||
oldxres != var->xres ||
oldyres != var->yres ||
oldvxres != var->xres_virtual ||
oldvyres != var->yres_virtual ||
oldbpp != var->bits_per_pixel ||
oldaccel != var->accel_flags) {
struct fb_fix_screeninfo fix;
tdfxfb_encode_fix(&fix, &par, info);
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 = 1;
display->inverse = inverse;
accel = var->accel_flags & FB_ACCELF_TEXT;
tdfxfb_set_dispsw(display, info, par.bpp, accel);
if (nopan)
display->scrollmode = SCROLL_YREDRAW;
if (info->fb_info.changevar)
(*info->fb_info.changevar) (con);
}
if (var->bits_per_pixel == 8)
for (j = 0; j < 16; j++) {
k = color_table[j];
fb_info.palette[j].red = default_red[k];
fb_info.palette[j].green = default_grn[k];
fb_info.palette[j].blue = default_blu[k];
}
del_timer(&(info->cursor.timer));
fb_info.cursor.state = CM_ERASE;
if (!info->fb_info.display_fg ||
info->fb_info.display_fg->vc_num == con || con < 0)
tdfxfb_set_par(&par, info);
if (!nohwcursor)
if (display && display->conp)
tdfxfb_createcursor(display);
info->cursor.redraw = 1;
if (oldbpp != var->bits_per_pixel || con < 0) {
if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
return err;
do_install_cmap(con, &(info->fb_info));
}
} }
banshee_make_room(6);
return 0; tdfx_outl(SRCFORMAT, fmt);
} tdfx_outl(DSTFORMAT, fmt);
tdfx_outl(COMMAND_2D, blitcmd);
static int tdfxfb_pan_display(struct fb_var_screeninfo *var, tdfx_outl(DSTSIZE, area->width | (area->height << 16));
int con, struct fb_info *fb) tdfx_outl(DSTXY, area->dx | (area->dy << 16));
{ tdfx_outl(LAUNCH_2D, area->sx | (area->sy << 16));
struct fb_info_tdfx *i = (struct fb_info_tdfx *) fb; banshee_wait_idle();
if (nopan)
return -EINVAL;
if (var->xoffset)
return -EINVAL;
if (var->yoffset > var->yres_virtual)
return -EINVAL;
if (nowrap && (var->yoffset + var->yres > var->yres_virtual))
return -EINVAL;
if (con == fb->currcon)
do_pan_var(var, i);
fb_display[con].var.xoffset = var->xoffset;
fb_display[con].var.yoffset = var->yoffset;
return 0;
} }
static int tdfxfb_get_cmap(struct fb_cmap *cmap, static void tdfxfb_imageblit(struct fb_info *info, struct fb_image *pixmap)
int kspc, int con, struct fb_info *fb)
{ {
int size = pixmap->height*((pixmap->width*pixmap->depth + 7)>>3);
int i, stride = info->fix.line_length;
u32 bpp = info->var.bits_per_pixel;
u32 dstfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13);
u8 *chardata = (u8 *) pixmap->data;
u32 srcfmt;
struct fb_info_tdfx *i = (struct fb_info_tdfx *) fb; if (pixmap->depth == 1) {
struct display *d = (con < 0) ? fb->disp : fb_display + con; banshee_make_room(8 + ((size + 3) >> 2));
tdfx_outl(COLORFORE, pixmap->fg_color);
if (con == fb->currcon) { tdfx_outl(COLORBACK, pixmap->bg_color);
/* current console? */ srcfmt = 0x400000;
return fb_get_cmap(cmap, kspc, tdfxfb_getcolreg, fb);
} else if (d->cmap.len) {
/* non default colormap? */
fb_copy_cmap(&d->cmap, cmap, kspc ? 0 : 2);
} else {
fb_copy_cmap(fb_default_cmap(i->current_par.cmap_len),
cmap, kspc ? 0 : 2);
}
return 0;
}
static int tdfxfb_set_cmap(struct fb_cmap *cmap,
int kspc, int con, struct fb_info *fb)
{
struct display *d = (con < 0) ? fb->disp : fb_display + con;
struct fb_info_tdfx *i = (struct fb_info_tdfx *) fb;
int cmap_len = (i->current_par.bpp == 8) ? 256 : 16;
if (d->cmap.len != cmap_len) {
int err;
if ((err = fb_alloc_cmap(&d->cmap, cmap_len, 0)))
return err;
}
if (con == fb->currcon) {
/* current console? */
return fb_set_cmap(cmap, kspc, fb);
} else { } else {
fb_copy_cmap(cmap, &d->cmap, kspc ? 0 : 1); banshee_make_room(6 + ((size + 3) >> 2));
srcfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13) | 0x400000;
}
tdfx_outl(SRCXY, 0);
tdfx_outl(DSTXY, pixmap->dx | (pixmap->dy << 16));
tdfx_outl(COMMAND_2D, COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24));
tdfx_outl(SRCFORMAT, srcfmt);
tdfx_outl(DSTFORMAT, dstfmt);
tdfx_outl(DSTSIZE, pixmap->width | (pixmap->height << 16));
/* Send four bytes at a time of data */
for (i = (size >> 2) ; i > 0; i--) {
tdfx_outl(LAUNCH_2D,*(u32*)chardata);
chardata += 4;
}
/* Send the leftovers now */
i = size%4;
switch (i) {
case 0: break;
case 1: tdfx_outl(LAUNCH_2D,*chardata); break;
case 2: tdfx_outl(LAUNCH_2D,*(u16*)chardata); break;
case 3: tdfx_outl(LAUNCH_2D,*(u16*)chardata | ((chardata[3]) << 24)); break;
} }
return 0; banshee_wait_idle();
} }
/** /**
* tdfxfb_probe - Device Initializiation * tdfxfb_probe - Device Initializiation
* *
* @pdev: PCI Device to initialize * @pdev: PCI Device to initialize
* @id: PCI Device ID * @id: PCI Device ID
* *
* Initializes and allocates resources for PCI device @pdev. * Initializes and allocates resources for PCI device @pdev.
* *
*/ */
static int __devinit tdfxfb_probe(struct pci_dev *pdev, static int __devinit tdfxfb_probe(struct pci_dev *pdev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
struct fb_var_screeninfo var; struct fb_info *info;
char *name = NULL; int size, err;
fb_info.dev = pdev->device; if ((err = pci_enable_device(pdev))) {
printk(KERN_WARNING "tdfxfb: Can't enable pdev: %d\n", err);
switch (pdev->device) { return err;
case PCI_DEVICE_ID_3DFX_BANSHEE:
fb_info.max_pixclock = BANSHEE_MAX_PIXCLOCK;
name = "Banshee";
break;
case PCI_DEVICE_ID_3DFX_VOODOO3:
fb_info.max_pixclock = VOODOO3_MAX_PIXCLOCK;
name = "Voodoo3";
break;
case PCI_DEVICE_ID_3DFX_VOODOO5:
fb_info.max_pixclock = VOODOO5_MAX_PIXCLOCK;
name = "Voodoo5";
break;
} }
fb_info.regbase_phys = pci_resource_start(pdev, 0); info = kmalloc(sizeof(struct fb_info) + sizeof(struct display) +
fb_info.regbase_size = 1 << 24; sizeof(u32) * 16, GFP_KERNEL);
fb_info.regbase_virt =
ioremap_nocache(fb_info.regbase_phys, 1 << 24);
if (!fb_info.regbase_virt) { if (!info) return -ENXIO;
printk(KERN_WARNING "fb: Can't remap %s register area.\n",
name); memset(info, 0, sizeof(info) + sizeof(struct display) + sizeof(u32) * 16);
return -ENXIO;
/* Configure the default fb_fix_screeninfo first */
switch (pdev->device) {
case PCI_DEVICE_ID_3DFX_BANSHEE:
strcat(tdfx_fix.id, " Banshee");
default_par.max_pixclock = BANSHEE_MAX_PIXCLOCK;
break;
case PCI_DEVICE_ID_3DFX_VOODOO3:
strcat(tdfx_fix.id, " Voodoo3");
default_par.max_pixclock = VOODOO3_MAX_PIXCLOCK;
break;
case PCI_DEVICE_ID_3DFX_VOODOO5:
strcat(tdfx_fix.id, " Voodoo5");
default_par.max_pixclock = VOODOO5_MAX_PIXCLOCK;
break;
} }
fb_info.bufbase_phys = pci_resource_start(pdev, 1); tdfx_fix.mmio_start = pci_resource_start(pdev, 0);
tdfx_fix.mmio_len = 1 << 24;
if (!(fb_info.bufbase_size = do_lfb_size())) { default_par.regbase_virt = ioremap_nocache(tdfx_fix.mmio_start, 1<<24);
iounmap(fb_info.regbase_virt); if (!default_par.regbase_virt) {
printk(KERN_WARNING "fb: Can't count %s memory.\n", name); printk("fb: Can't remap %s register area.\n", tdfx_fix.id);
return -ENXIO; return -ENXIO;
} }
fb_info.bufbase_virt = ioremap_nocache(fb_info.bufbase_phys, if (!request_mem_region(pci_resource_start(pdev, 0),
fb_info.bufbase_size); pci_resource_len(pdev, 0), "tdfx regbase")) {
printk(KERN_WARNING "tdfxfb: Can't reserve regbase\n");
if (!fb_info.regbase_virt) { iounmap(default_par.regbase_virt);
printk(KERN_WARNING "fb: Can't remap %s framebuffer.\n",
name);
iounmap(fb_info.regbase_virt);
return -ENXIO; return -ENXIO;
} }
fb_info.iobase = pci_resource_start(pdev, 2);
printk("fb: %s memory = %ldK\n", name, fb_info.bufbase_size >> 10);
#ifdef CONFIG_MTRR tdfx_fix.smem_start = pci_resource_start(pdev, 1);
if (!nomtrr) { if (!(tdfx_fix.smem_len = do_lfb_size(pdev->device))) {
fb_info.mtrr_idx = mtrr_add(fb_info.bufbase_phys, iounmap(default_par.regbase_virt);
fb_info.bufbase_size, printk("fb: Can't count %s memory.\n", tdfx_fix.id);
MTRR_TYPE_WRCOMB, 1); return -ENXIO;
printk(KERN_INFO "fb: MTRR's turned on\n");
} }
#endif
/* clear framebuffer memory */ if (!request_mem_region(pci_resource_start(pdev, 1),
memset_io(fb_info.bufbase_virt, 0, fb_info.bufbase_size); pci_resource_len(pdev, 1), "tdfx smem")) {
fb_info.fb_info.currcon = -1; printk(KERN_WARNING "tdfxfb: Can't reserve smem\n");
release_mem_region(pci_resource_start(pdev, 0),
if (!nohwcursor) pci_resource_len(pdev, 0));
tdfxfb_hwcursor_init(); iounmap(default_par.regbase_virt);
return -ENXIO;
init_timer(&fb_info.cursor.timer);
fb_info.cursor.timer.function = do_flashcursor;
fb_info.cursor.timer.data = (unsigned long) (&fb_info);
fb_info.cursor.state = CM_ERASE;
spin_lock_init(&fb_info.DAClock);
strcpy(fb_info.fb_info.modename, "3Dfx ");
strcat(fb_info.fb_info.modename, name);
fb_info.fb_info.changevar = NULL;
fb_info.fb_info.node = NODEV;
fb_info.fb_info.fbops = &tdfxfb_ops;
fb_info.fb_info.disp = &fb_info.disp;
fb_info.fb_info.currcon = -1;
strcpy(fb_info.fb_info.fontname, fontname);
fb_info.fb_info.switch_con = &tdfxfb_switch_con;
fb_info.fb_info.updatevar = &tdfxfb_updatevar;
fb_info.fb_info.flags = FBINFO_FLAG_DEFAULT;
memset(&var, 0, sizeof(var));
if (!mode_option || !fb_find_mode(&var, &fb_info.fb_info,
mode_option, NULL, 0, NULL, 8))
var = default_mode[0].var;
noaccel ? (var.accel_flags &= ~FB_ACCELF_TEXT) :
(var.accel_flags |= FB_ACCELF_TEXT);
if (tdfxfb_decode_var(&var, &fb_info.default_par, &fb_info)) {
/*
* ugh -- can't use the mode from the mode db. (or command
* line), so try the default
*/
printk(KERN_NOTICE
"tdfxfb: can't decode the supplied video mode, using default\n");
var = default_mode[0].var;
noaccel ? (var.accel_flags &= ~FB_ACCELF_TEXT) :
(var.accel_flags |= FB_ACCELF_TEXT);
if (tdfxfb_decode_var
(&var, &fb_info.default_par, &fb_info)) {
/* this is getting really bad!... */
printk(KERN_WARNING
"tdfxfb: can't decode default video mode\n");
return -ENXIO;
}
} }
fb_info.fb_info.screen_base = fb_info.bufbase_virt; info->screen_base = ioremap_nocache(tdfx_fix.smem_start,
fb_info.disp.var = var; tdfx_fix.smem_len);
if (!info->screen_base) {
if (tdfxfb_set_var(&var, -1, &fb_info.fb_info)) { printk("fb: Can't remap %s framebuffer.\n", tdfx_fix.id);
printk(KERN_WARNING iounmap(default_par.regbase_virt);
"tdfxfb: can't set default video mode\n");
return -ENXIO; return -ENXIO;
} }
if (register_framebuffer(&fb_info.fb_info) < 0) { default_par.iobase = pci_resource_start(pdev, 2);
printk(KERN_WARNING
"tdfxfb: can't register framebuffer\n"); if (!request_region(pci_resource_start(pdev, 2),
pci_resource_len(pdev, 2), "tdfx iobase")) {
printk(KERN_WARNING "tdfxfb: Can't reserve iobase\n");
release_mem_region(pci_resource_start(pdev, 1),
pci_resource_len(pdev, 1));
release_mem_region(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
iounmap(default_par.regbase_virt);
iounmap(info->screen_base);
return -ENXIO; return -ENXIO;
} }
printk(KERN_INFO "fb%d: %s frame buffer device\n", printk("fb: %s memory = %dK\n", tdfx_fix.id, tdfx_fix.smem_len >> 10);
GET_FB_IDX(fb_info.fb_info.node), fb_info.fb_info.modename);
return 0; /* clear framebuffer memory */
memset_io(info->screen_base, 0, tdfx_fix.smem_len);
tdfx_fix.ypanstep = nopan ? 0 : 1;
tdfx_fix.ywrapstep = nowrap ? 0 : 1;
info->node = NODEV;
info->fbops = &tdfxfb_ops;
info->fix = tdfx_fix;
info->par = &default_par;
info->disp = (struct display *)(info + 1);
info->pseudo_palette = (void *)(info->disp + 1);
info->flags = FBINFO_FLAG_DEFAULT;
/* The below feilds will go away !!!! */
strcpy(info->modename, info->fix.id);
info->currcon = -1;
info->switch_con = gen_switch;
info->updatevar = gen_update_var;
if (!mode_option)
mode_option = "640x480@60";
err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
if (!err || err == 4)
info->var = tdfx_var;
size = (info->var.bits_per_pixel == 8) ? 256 : 16;
fb_alloc_cmap(&info->cmap, size, 0);
gen_set_var(&info->var, -1, info);
if (register_framebuffer(info) < 0) {
printk("tdfxfb: can't register framebuffer\n");
return -ENXIO;
}
/*
* Our driver data
*/
pdev->driver_data = info;
return 0;
} }
/** /**
* tdfxfb_remove - Device removal * tdfxfb_remove - Device removal
* *
* @pdev: PCI Device to cleanup * @pdev: PCI Device to cleanup
* *
* Releases all resources allocated during the course of the driver's * Releases all resources allocated during the course of the driver's
* lifetime for the PCI device @pdev. * lifetime for the PCI device @pdev.
* *
*/ */
static void __devexit tdfxfb_remove(struct pci_dev *pdev) static void __devexit tdfxfb_remove(struct pci_dev *pdev)
{ {
unregister_framebuffer(&fb_info.fb_info); struct fb_info *info = (struct fb_info *)pdev->driver_data;
del_timer_sync(&fb_info.cursor.timer); struct tdfx_par *par = (struct tdfx_par *) info->par;
#ifdef CONFIG_MTRR
if (!nomtrr) {
mtrr_del(fb_info.mtrr_idx, fb_info.bufbase_phys,
fb_info.bufbase_size);
printk("fb: MTRR's turned off\n");
}
#endif
iounmap(fb_info.regbase_virt); unregister_framebuffer(info);
iounmap(fb_info.bufbase_virt); iounmap(par->regbase_virt);
iounmap(info->screen_base);
/* Clean up after reserved regions */
release_region(pci_resource_start(pdev, 2),
pci_resource_len(pdev, 2));
release_mem_region(pci_resource_start(pdev, 1),
pci_resource_len(pdev, 1));
release_mem_region(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
} }
int __init tdfxfb_init(void) int __init tdfxfb_init(void)
{ {
return pci_module_init(&tdfxfb_driver); return pci_module_init(&tdfxfb_driver);
} }
static void __exit tdfxfb_exit(void) static void __exit tdfxfb_exit(void)
{ {
pci_unregister_driver(&tdfxfb_driver); pci_unregister_driver(&tdfxfb_driver);
} }
MODULE_AUTHOR("Hannu Mallat <hmallat@cc.hut.fi>"); MODULE_AUTHOR("Hannu Mallat <hmallat@cc.hut.fi>");
MODULE_DESCRIPTION("3Dfx framebuffer device driver"); MODULE_DESCRIPTION("3Dfx framebuffer device driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_PARM(noaccel, "i");
MODULE_PARM_DESC(noaccel, "Disable hardware acceleration (1 = disabled), enabled by default.");
#ifdef MODULE #ifdef MODULE
module_init(tdfxfb_init); module_init(tdfxfb_init);
#endif #endif
...@@ -1966,300 +1164,26 @@ module_exit(tdfxfb_exit); ...@@ -1966,300 +1164,26 @@ module_exit(tdfxfb_exit);
#ifndef MODULE #ifndef MODULE
void tdfxfb_setup(char *options, int *ints) void tdfxfb_setup(char *options, int *ints)
{ {
char *this_opt; char* this_opt;
if (!options || !*options) if (!options || !*options)
return; return;
while ((this_opt = strsep(&options, ",")) != NULL) { while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt) if (!*this_opt)
continue; continue;
if (!strcmp(this_opt, "inverse")) { if (!strcmp(this_opt, "inverse")) {
inverse = 1; inverse = 1;
fb_invert_cmaps(); fb_invert_cmaps();
} else if (!strcmp(this_opt, "noaccel")) { } else if(!strcmp(this_opt, "nopan")) {
noaccel = nopan = nowrap = nohwcursor = 1;
} else if (!strcmp(this_opt, "nopan")) {
nopan = 1; nopan = 1;
} else if (!strcmp(this_opt, "nowrap")) { } else if(!strcmp(this_opt, "nowrap")) {
nowrap = 1; nowrap = 1;
} else if (!strcmp(this_opt, "nohwcursor")) {
nohwcursor = 1;
#ifdef CONFIG_MTRR
} else if (!strcmp(this_opt, "nomtrr")) {
nomtrr = 1;
#endif
} else if (!strncmp(this_opt, "font:", 5)) {
strncpy(fontname, this_opt + 5, 40);
} else { } else {
mode_option = this_opt; mode_option = this_opt;
} }
} }
} }
#endif #endif
static int tdfxfb_switch_con(int con, struct fb_info *fb)
{
struct fb_info_tdfx *info = (struct fb_info_tdfx *) fb;
struct tdfxfb_par par;
int old_con = fb->currcon;
int set_par = 1;
/* Do we have to save the colormap? */
if (fb->currcon >= 0)
if (fb_display[fb->currcon].cmap.len)
fb_get_cmap(&fb_display[fb->currcon].cmap, 1,
tdfxfb_getcolreg, fb);
fb->currcon = con;
fb_display[fb->currcon].var.activate = FB_ACTIVATE_NOW;
tdfxfb_decode_var(&fb_display[con].var, &par, info);
if (old_con >= 0 && vt_cons[old_con]->vc_mode != KD_GRAPHICS) {
/* check if we have to change video registers */
struct tdfxfb_par old_par;
tdfxfb_decode_var(&fb_display[old_con].var, &old_par,
info);
if (!memcmp(&par, &old_par, sizeof(par)))
set_par = 0; /* avoid flicker */
}
if (set_par)
tdfxfb_set_par(&par, info);
if (fb_display[con].dispsw && fb_display[con].conp)
fb_con.con_cursor(fb_display[con].conp, CM_ERASE);
del_timer(&(info->cursor.timer));
fb_info.cursor.state = CM_ERASE;
if (!nohwcursor)
if (fb_display[con].conp)
tdfxfb_createcursor(&fb_display[con]);
info->cursor.redraw = 1;
tdfxfb_set_dispsw(&fb_display[con],
info, par.bpp, par.accel_flags & FB_ACCELF_TEXT);
do_install_cmap(con, fb);
tdfxfb_updatevar(con, fb);
return 1;
}
/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
static int tdfxfb_blank(int blank, struct fb_info *fb)
{
u32 dacmode, state = 0, vgablank = 0;
dacmode = tdfx_inl(DACMODE);
switch (blank) {
case 0: /* Screen: On; HSync: On, VSync: On */
state = 0;
vgablank = 0;
break;
case 1: /* Screen: Off; HSync: On, VSync: On */
state = 0;
vgablank = 1;
break;
case 2: /* Screen: Off; HSync: On, VSync: Off */
state = BIT(3);
vgablank = 1;
break;
case 3: /* Screen: Off; HSync: Off, VSync: On */
state = BIT(1);
vgablank = 1;
break;
case 4: /* Screen: Off; HSync: Off, VSync: Off */
state = BIT(1) | BIT(3);
vgablank = 1;
break;
}
dacmode &= ~(BIT(1) | BIT(3));
dacmode |= state;
banshee_make_room(1);
tdfx_outl(DACMODE, dacmode);
if (vgablank)
vga_disable_video();
else
vga_enable_video();
return 0;
}
static int tdfxfb_updatevar(int con, struct fb_info *fb)
{
struct fb_info_tdfx *i = (struct fb_info_tdfx *) fb;
if ((con == fb->currcon) && (!nopan))
do_pan_var(&fb_display[con].var, i);
return 0;
}
static int tdfxfb_getcolreg(unsigned regno,
unsigned *red,
unsigned *green,
unsigned *blue,
unsigned *transp, struct fb_info *fb)
{
struct fb_info_tdfx *i = (struct fb_info_tdfx *) fb;
if (regno > i->current_par.cmap_len)
return 1;
*red = i->palette[regno].red;
*green = i->palette[regno].green;
*blue = i->palette[regno].blue;
*transp = 0;
return 0;
}
static int tdfxfb_setcolreg(unsigned regno,
unsigned red,
unsigned green,
unsigned blue,
unsigned transp, struct fb_info *info)
{
struct fb_info_tdfx *i = (struct fb_info_tdfx *) info;
#ifdef FBCON_HAS_CFB8
u32 rgbcol;
#endif
if (regno >= i->current_par.cmap_len)
return 1;
i->palette[regno].red = red;
i->palette[regno].green = green;
i->palette[regno].blue = blue;
switch (i->current_par.bpp) {
#ifdef FBCON_HAS_CFB8
case 8:
rgbcol = (((u32) red & 0xff00) << 8) |
(((u32) green & 0xff00) << 0) |
(((u32) blue & 0xff00) >> 8);
do_setpalentry(regno, rgbcol);
break;
#endif
#ifdef FBCON_HAS_CFB16
case 16:
i->fbcon_cmap.cfb16[regno] =
(((u32) red & 0xf800) >> 0) |
(((u32) green & 0xfc00) >> 5) |
(((u32) blue & 0xf800) >> 11);
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
i->fbcon_cmap.cfb24[regno] =
(((u32) red & 0xff00) << 8) |
(((u32) green & 0xff00) << 0) |
(((u32) blue & 0xff00) >> 8);
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
i->fbcon_cmap.cfb32[regno] =
(((u32) red & 0xff00) << 8) |
(((u32) green & 0xff00) << 0) |
(((u32) blue & 0xff00) >> 8);
break;
#endif
default:
DPRINTK("bad depth %u\n", i->current_par.bpp);
break;
}
return 0;
}
static void tdfxfb_createcursorshape(struct display *p)
{
unsigned int h, cu, cd;
h = fontheight(p);
cd = h;
if (cd >= 10)
cd--;
fb_info.cursor.type = p->conp->vc_cursor_type & CUR_HWMASK;
switch (fb_info.cursor.type) {
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;
}
fb_info.cursor.w = fontwidth(p);
fb_info.cursor.u = cu;
fb_info.cursor.d = cd;
}
static void tdfxfb_createcursor(struct display *p)
{
u8 *cursorbase;
u32 xline;
unsigned int i;
unsigned int h, to;
tdfxfb_createcursorshape(p);
xline = ~((1 << (32 - fb_info.cursor.w)) - 1);
#ifdef __LITTLE_ENDIAN
xline = swab32(xline);
#endif
cursorbase = (u8 *) fb_info.bufbase_virt;
h = fb_info.cursor.cursorimage;
to = fb_info.cursor.u;
for (i = 0; i < to; i++) {
writel(0, cursorbase + h);
writel(0, cursorbase + h + 4);
writel(~0, cursorbase + h + 8);
writel(~0, cursorbase + h + 12);
h += 16;
}
to = fb_info.cursor.d;
for (; i < to; i++) {
writel(xline, cursorbase + h);
writel(0, cursorbase + h + 4);
writel(~0, cursorbase + h + 8);
writel(~0, cursorbase + h + 12);
h += 16;
}
for (; i < 64; i++) {
writel(0, cursorbase + h);
writel(0, cursorbase + h + 4);
writel(~0, cursorbase + h + 8);
writel(~0, cursorbase + h + 12);
h += 16;
}
}
static void tdfxfb_hwcursor_init(void)
{
unsigned int start;
start = (fb_info.bufbase_size - 1024) & PAGE_MASK;
fb_info.bufbase_size = start;
fb_info.cursor.cursorimage = fb_info.bufbase_size;
printk("tdfxfb: reserving 1024 bytes for the hwcursor at %p\n",
fb_info.regbase_virt + fb_info.cursor.cursorimage);
}
/* /*
* linux/drivers/video/tx3912fb.c * drivers/video/tx3912fb.c
* *
* Copyright (C) 1999 Harald Koerfgen * Copyright (C) 1999 Harald Koerfgen
* Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com) * Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com)
* *
* This file is subject to the terms and conditions of the GNU General Public * 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 * License. See the file COPYING in the main directory of this archive for
* more details. * more details.
* *
* Framebuffer for LCD controller in TMPR3912/05 and PR31700 processors * Framebuffer for LCD controller in TMPR3912/05 and PR31700 processors
*/ */
#include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -20,282 +21,193 @@ ...@@ -20,282 +21,193 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <video/fbcon.h>
#include <asm/io.h>
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <video/fbcon.h> #include <asm/tx3912.h>
#include <video/fbcon-mfb.h> #include <video/tx3912.h>
#include <video/fbcon-cfb2.h>
#include <video/fbcon-cfb4.h>
#include <video/fbcon-cfb8.h>
#include "tx3912fb.h"
/* /*
* Frame buffer, palette and console structures * Frame buffer, palette and console structures
*/ */
static struct fb_info fb_info; static struct fb_info fb_info;
static struct { u_char red, green, blue, pad; } palette[256]; static u32 cfb8[16];
static struct display global_disp; static struct display disp;
/* static struct fb_fix_screeninfo tx3912fb_fix __initdata = {
* Interface used by the world id: "tx3912fb",
*/ #ifdef CONFIG_NINO_16MB
static int tx3912fb_get_fix(struct fb_fix_screeninfo *fix, int con, smem_len: (240 * 320),
struct fb_info *info); #else
static int tx3912fb_get_var(struct fb_var_screeninfo *var, int con, smem_len: ((240 * 320)/2),
struct fb_info *info); #endif
static int tx3912fb_set_var(struct fb_var_screeninfo *var, int con, type: FB_TYPE_PACKED_PIXELS,
struct fb_info *info); visual: FB_VISUAL_TRUECOLOR,
static int tx3912fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, xpanstep: 1,
struct fb_info *info); ypanstep: 1,
static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, ywrapstep: 1,
u_int transp, struct fb_info *info); accel: FB_ACCEL_NONE,
};
static struct fb_var_screeninfo tx3912fb_var = {
xres: 240,
yres: 320,
xres_virtual: 240,
yres_virtual: 320,
#ifdef CONFIG_NINO_16MB
bits_per_pixel: 8,
red: { 5, 3, 0 }, /* RGB 332 */
green: { 2, 3, 0 },
blue: { 0, 2, 0 },
#else
bits_per_pixel: 4,
#endif
activate: FB_ACTIVATE_NOW,
width: -1,
height: -1,
pixclock: 20000,
left_margin: 64,
right_margin: 64,
upper_margin: 32,
lower_margin: 32,
hsync_len: 64,
vsync_len: 2,
vmode: FB_VMODE_NONINTERLACED,
};
/* /*
* Interface used by console driver * Interface used by the world
*/ */
int tx3912fb_init(void); int tx3912fb_init(void);
static int tx3912fbcon_switch(int con, struct fb_info *info);
static int tx3912fbcon_updatevar(int con, struct fb_info *info); static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp,
struct fb_info *info);
/* /*
* Macros * Macros
*/ */
#define get_line_length(xres_virtual, bpp) \ #define get_line_length(xres_virtual, bpp) \
(u_long) (((int) xres_virtual * (int) bpp + 7) >> 3) (u_long) (((int) xres_virtual * (int) bpp + 7) >> 3)
/*
* Internal routines
*/
static int tx3912fb_getcolreg(u_int regno, u_int *red, u_int *green,
u_int *blue, u_int *transp, struct fb_info *info);
/* /*
* Frame buffer operations structure used by console driver * Frame buffer operations structure used by console driver
*/ */
static struct fb_ops tx3912fb_ops = { static struct fb_ops tx3912fb_ops = {
owner: THIS_MODULE, owner: THIS_MODULE,
fb_get_fix: tx3912fb_get_fix, fb_get_fix: gen_get_fix,
fb_get_var: tx3912fb_get_var, fb_get_var: gen_get_var,
fb_set_var: tx3912fb_set_var, fb_set_var: gen_set_var,
fb_get_cmap: tx3912fb_get_cmap, fb_get_cmap: gen_get_cmap,
fb_set_cmap: gen_set_cmap, fb_set_cmap: gen_set_cmap,
fb_setcolreg: tx3912fb_setcolreg, fb_setcolreg: tx3912fb_setcolreg,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
}; };
static int tx3912fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
/*
* Get fixed display data
*/
static int tx3912fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
{ {
struct display *display; /*
* Memory limit
memset(fix, 0, sizeof(struct fb_fix_screeninfo)); */
strcpy(fix->id, TX3912FB_NAME); line_length =
get_line_length(var->xres_virtual, var->bits_per_pixel);
if (con == -1) if ((line_length * var->yres_virtual) > info->fix.smem_len)
display = &global_disp; return -ENOMEM;
else
display = &fb_display[con];
fix->smem_start = tx3912fb_vaddr;
fix->smem_len = tx3912fb_size;
fix->type = display->type;
fix->type_aux = display->type_aux;
fix->xpanstep = 0;
fix->ypanstep = display->ypanstep;
fix->ywrapstep = display->ywrapstep;
fix->visual = display->visual;
fix->line_length = display->line_length;
fix->accel = FB_ACCEL_NONE;
return 0; return 0;
} }
/* static int tx3912fb_set_par(struct fb_info *info)
* Get user display data
*/
static int tx3912fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{ {
if (con == -1) u_long tx3912fb_paddr = 0;
*var = tx3912fb_info;
else
*var = fb_display[con].var;
return 0; /* Disable the video logic */
} outl(inl(TX3912_VIDEO_CTRL1) &
~(TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON),
TX3912_VIDEO_CTRL1);
udelay(200);
/* /* Set start address for DMA transfer */
* Set user display data outl(tx3912fb_paddr, TX3912_VIDEO_CTRL3);
*/
static int tx3912fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
int err, activate = var->activate;
int oldxres, oldyres, oldvxres, oldvyres, oldbpp;
u_long line_length;
struct display *display;
if (con == -1) /* Set end address for DMA transfer */
display = &global_disp; outl((tx3912fb_paddr + tx3912fb_fix.smem_len + 1), TX3912_VIDEO_CTRL4);
else
display = &fb_display[con];
/* /* Set the pixel depth */
* FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal switch (info->var.bits_per_pixel) {
* as FB_VMODE_SMOOTH_XPAN is only used internally case 1:
*/ /* Monochrome */
if (var->vmode & FB_VMODE_CONUPDATE) { outl(inl(TX3912_VIDEO_CTRL1) &
var->xoffset = display->var.xoffset; ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
var->yoffset = display->var.yoffset; info->fix.visual = FB_VISUAL_MONO10;
var->vmode |= FB_VMODE_YWRAP; break;
case 4:
/* 4-bit gray */
outl(inl(TX3912_VIDEO_CTRL1) &
~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
outl(inl(TX3912_VIDEO_CTRL1) |
TX3912_VIDEO_CTRL1_BITSEL_4BIT_GRAY,
TX3912_VIDEO_CTRL1);
info->fix.visual = FB_VISUAL_TRUECOLOR;
break;
case 8:
/* 8-bit color */
outl(inl(TX3912_VIDEO_CTRL1) &
~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
outl(inl(TX3912_VIDEO_CTRL1) |
TX3912_VIDEO_CTRL1_BITSEL_8BIT_COLOR,
TX3912_VIDEO_CTRL1);
info->fix.visual = FB_VISUAL_TRUECOLOR;
break;
case 2:
default:
/* 2-bit gray */
outl(inl(TX3912_VIDEO_CTRL1) &
~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
outl(inl(TX3912_VIDEO_CTRL1) |
TX3912_VIDEO_CTRL1_BITSEL_2BIT_GRAY,
TX3912_VIDEO_CTRL1);
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
break;
} }
/* /* Enable the video clock */
* Make sure values are in range outl(inl(TX3912_CLK_CTRL) | TX3912_CLK_CTRL_ENVIDCLK,
*/ TX3912_CLK_CTRL);
if (!var->xres)
var->xres = 1;
if (!var->yres)
var->yres = 1;
if (var->xres > var->xres_virtual)
var->xres_virtual = var->xres;
if (var->yres > var->yres_virtual)
var->yres_virtual = var->yres;
if (var->bits_per_pixel <= 1)
var->bits_per_pixel = 1;
else if (var->bits_per_pixel <= 2)
var->bits_per_pixel = 2;
else if (var->bits_per_pixel <= 4)
var->bits_per_pixel = 4;
else if (var->bits_per_pixel <= 8)
var->bits_per_pixel = 8;
else
return -EINVAL;
/* /* Unfreeze video logic and enable DF toggle */
* Memory limit outl(inl(TX3912_VIDEO_CTRL1) &
*/ ~(TX3912_VIDEO_CTRL1_ENFREEZEFRAME |
line_length = get_line_length(var->xres_virtual, var->bits_per_pixel); TX3912_VIDEO_CTRL1_DFMODE)
if ((line_length * var->yres_virtual) > tx3912fb_size) , TX3912_VIDEO_CTRL1);
return -ENOMEM; udelay(200);
/*
* This is only for color and we only support 8-bit color
*/
if (var->bits_per_pixel) {
/* RGB 332 */
var->red.offset = 5;
var->red.length = 3;
var->green.offset = 2;
var->green.length = 3;
var->blue.offset = 0;
var->blue.length = 2;
var->transp.offset = 0;
var->transp.length = 0;
}
var->red.msb_right = 0;
var->green.msb_right = 0;
var->blue.msb_right = 0;
var->transp.msb_right = 0;
/* /* Enable the video logic */
* Make changes if necessary outl(inl(TX3912_VIDEO_CTRL1) |
*/ (TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON),
if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { TX3912_VIDEO_CTRL1);
oldxres = display->var.xres;
oldyres = display->var.yres;
oldvxres = display->var.xres_virtual;
oldvyres = display->var.yres_virtual;
oldbpp = display->var.bits_per_pixel;
display->var = *var;
if (oldxres != var->xres || oldyres != var->yres ||
oldvxres != var->xres_virtual ||
oldvyres != var->yres_virtual ||
oldbpp != var->bits_per_pixel) {
switch (var->bits_per_pixel) {
case 1:
display->visual = FB_VISUAL_MONO10;
break;
case 2:
display->visual = FB_VISUAL_PSEUDOCOLOR;
case 4:
case 8:
display->visual = FB_VISUAL_TRUECOLOR;
break;
}
display->type = FB_TYPE_PACKED_PIXELS;
display->type_aux = 0;
display->ypanstep = 0;
display->ywrapstep = 0;
display->next_line =
display->line_length =
get_line_length(var->xres_virtual,
var->bits_per_pixel);
display->can_soft_blank = 0;
display->inverse = FB_IS_INVERSE;
switch (var->bits_per_pixel) {
#ifdef CONFIG_FBCON_MFB
case 1:
display->dispsw = &fbcon_mfb;
break;
#endif
#ifdef CONFIG_FBCON_CFB2
case 2:
display->dispsw = &fbcon_cfb2;
break;
#endif
#ifdef CONFIG_FBCON_CFB4
case 4:
display->dispsw = &fbcon_cfb4;
break;
#endif
#ifdef CONFIG_FBCON_CFB8
case 8:
display->dispsw = &fbcon_cfb8;
display->dispsw_data = fbcon_cmap.cfb8;
break;
#endif
default:
display->dispsw = &fbcon_dummy;
break;
}
if (fb_info.changevar)
(*fb_info.changevar)(con);
}
if (oldbpp != var->bits_per_pixel) {
if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
return err;
do_install_cmap(con, info);
}
}
return 0; info->fix.line_length = get_line_length(var->xres_virtual,
var->bits_per_pixel);
} }
/* /*
* Get the colormap * Set a single color register
*/ */
static int tx3912fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green,
struct fb_info *info) u_int blue, u_int transp,
struct fb_info *info)
{ {
if (con == info->currcon) if (regno > 255)
return fb_get_cmap(cmap, kspc, tx3912fb_getcolreg, info); return 1;
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);
if (regno < 16)
((u32 *)(info->pseudo_palette))[regno] = ((red & 0xe000) >> 8)
| ((green & 0xe000) >> 11)
| ((blue & 0xc000) >> 14);
return 0; return 0;
} }
...@@ -304,164 +216,126 @@ static int tx3912fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, ...@@ -304,164 +216,126 @@ static int tx3912fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
*/ */
int __init tx3912fb_init(void) int __init tx3912fb_init(void)
{ {
/* Stop the video logic when frame completes */ u_long tx3912fb_paddr = 0;
VidCtrl1 |= ENFREEZEFRAME;
IntClear1 |= INT1_LCDINT;
while (!(IntStatus1 & INT1_LCDINT));
/* Disable the video logic */ /* Disable the video logic */
VidCtrl1 &= ~(ENVID | DISPON); outl(inl(TX3912_VIDEO_CTRL1) &
~(TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON),
TX3912_VIDEO_CTRL1);
udelay(200); udelay(200);
/* Set start address for DMA transfer */ /* Set start address for DMA transfer */
VidCtrl3 = tx3912fb_paddr & outl(tx3912fb_paddr, TX3912_VIDEO_CTRL3);
(TX3912_VIDCTRL3_VIDBANK_MASK | TX3912_VIDCTRL3_VIDBASEHI_MASK);
/* Set end address for DMA transfer */ /* Set end address for DMA transfer */
VidCtrl4 = (tx3912fb_paddr + tx3912fb_size + 1) & outl((tx3912fb_paddr + tx3912fb_fix.smem_len + 1), TX3912_VIDEO_CTRL4);
TX3912_VIDCTRL4_VIDBASELO_MASK;
/* Set the pixel depth */ /* Set the pixel depth */
switch (tx3912fb_info.bits_per_pixel) { switch (tx3912fb_var.bits_per_pixel) {
case 1: case 1:
/* Monochrome */ /* Monochrome */
VidCtrl1 &= ~TX3912_VIDCTRL1_BITSEL_MASK; outl(inl(TX3912_VIDEO_CTRL1) &
~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
tx3912fb_fix.visual = FB_VISUAL_MONO10;
break; break;
case 4: case 4:
/* 4-bit gray */ /* 4-bit gray */
VidCtrl1 &= ~TX3912_VIDCTRL1_BITSEL_MASK; outl(inl(TX3912_VIDEO_CTRL1) &
VidCtrl1 |= TX3912_VIDCTRL1_4BIT_GRAY; ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
outl(inl(TX3912_VIDEO_CTRL1) |
TX3912_VIDEO_CTRL1_BITSEL_4BIT_GRAY,
TX3912_VIDEO_CTRL1);
tx3912fb_fix.visual = FB_VISUAL_TRUECOLOR;
tx3912fb_fix.grayscale = 1;
break; break;
case 8: case 8:
/* 8-bit color */ /* 8-bit color */
VidCtrl1 &= ~TX3912_VIDCTRL1_BITSEL_MASK; outl(inl(TX3912_VIDEO_CTRL1) &
VidCtrl1 |= TX3912_VIDCTRL1_8BIT_COLOR; ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
outl(inl(TX3912_VIDEO_CTRL1) |
TX3912_VIDEO_CTRL1_BITSEL_8BIT_COLOR,
TX3912_VIDEO_CTRL1);
tx3912fb_fix.visual = FB_VISUAL_TRUECOLOR;
break; break;
case 2: case 2:
default: default:
/* 2-bit gray */ /* 2-bit gray */
VidCtrl1 &= ~TX3912_VIDCTRL1_BITSEL_MASK; outl(inl(TX3912_VIDEO_CTRL1) &
VidCtrl1 |= TX3912_VIDCTRL1_2BIT_GRAY; ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1);
outl(inl(TX3912_VIDEO_CTRL1) |
TX3912_VIDEO_CTRL1_BITSEL_2BIT_GRAY,
TX3912_VIDEO_CTRL1);
tx3912fb_fix.visual = FB_VISUAL_PSEUDOCOLOR;
tx3912fb_fix.grayscale = 1;
break; break;
} }
/* Enable the video clock */
outl(inl(TX3912_CLK_CTRL) | TX3912_CLK_CTRL_ENVIDCLK,
TX3912_CLK_CTRL);
/* Unfreeze video logic and enable DF toggle */ /* Unfreeze video logic and enable DF toggle */
VidCtrl1 &= ~(ENFREEZEFRAME | DFMODE); outl(inl(TX3912_VIDEO_CTRL1) &
~(TX3912_VIDEO_CTRL1_ENFREEZEFRAME | TX3912_VIDEO_CTRL1_DFMODE),
TX3912_VIDEO_CTRL1);
udelay(200); udelay(200);
/* Clear the framebuffer */ /* Clear the framebuffer */
memset((void *) tx3912fb_vaddr, 0xff, tx3912fb_size); memset((void *) tx3912fb_fix.smem_start, 0xff, tx3912fb_fix.smem_len);
udelay(200); udelay(200);
/* Enable the video logic */ /* Enable the video logic */
VidCtrl1 |= (DISPON | ENVID); outl(inl(TX3912_VIDEO_CTRL1) |
(TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON),
TX3912_VIDEO_CTRL1);
strcpy(fb_info.modename, TX3912FB_NAME); /*
* Memory limit
*/
tx3912fb_fix.line_length =
get_line_length(tx3912fb_var.xres_virtual, tx3912fb_var.bits_per_pixel);
if ((tx3912fb_fix.line_length * tx3912fb_var.yres_virtual) > tx3912fb_fix.smem_len)
return -ENOMEM;
strcpy(fb_info.modename, tx3912fb_fix.id);
fb_info.changevar = NULL; fb_info.changevar = NULL;
fb_info.node = NODEV; fb_info.node = NODEV;
fb_info.fbops = &tx3912fb_ops;
fb_info.screen_base = (u_char *) tx3912fb_vaddr;
fb_info.disp = &global_disp;
fb_info.currcon = -1; fb_info.currcon = -1;
fb_info.switch_con = &tx3912fbcon_switch; fb_info.fbops = &tx3912fb_ops;
fb_info.updatevar = &tx3912fbcon_updatevar; fb_info.var = tx3912fb_var;
fb_info.fix = tx3912fb_fix;
fb_info.pseudo_palette = pseudo_palette;
fb_info.disp = &disp;
fb_info.switch_con = gen_switch;
fb_info.updatevar = gen_update_var;
fb_info.flags = FBINFO_FLAG_DEFAULT; fb_info.flags = FBINFO_FLAG_DEFAULT;
tx3912fb_set_var(&tx3912fb_info, -1, &fb_info); /* Clear the framebuffer */
memset((void *) fb_info.fix.smem_start, 0xff, fb_info.fix.smem_len);
udelay(200);
fb_alloc_cmap(&info->cmap, size, 0);
gen_set_disp(-1, &disp);
if (register_framebuffer(&fb_info) < 0) if (register_framebuffer(&fb_info) < 0)
return -1; return -1;
printk (KERN_INFO "fb%d: TX3912 frame buffer using %uKB.\n", printk(KERN_INFO "fb%d: TX3912 frame buffer using %uKB.\n",
GET_FB_IDX(fb_info.node), (u_int) (tx3912fb_size >> 10)); GET_FB_IDX(fb_info.node), (u_int) (fb_info.fix.smem_len >> 10));
return 0; return 0;
} }
/* int __init tx3912fb_setup(char *options)
* Switch the console to be the framebuffer
*/
static int tx3912fbcon_switch(int con, struct fb_info *info)
{ {
/* Save off the color map if needed */ char *this_opt;
if (fb_display[info->currcon].cmap.len)
fb_get_cmap(&fb_display[info->currcon].cmap, 1,
tx3912fb_getcolreg, info);
/* Make the switch */ if (!options || !*options)
info->currcon = con; return 0;
/* Install new colormap */ while ((this_opt = strsep(&options, ","))) {
do_install_cmap(con, info); if (!strncmp(options, "bpp:", 4))
return 0; tx3912fb_var.bits_per_pixel = simple_strtoul(options+4, NULL, 0);
} }
/*
* Update variable structure
*/
static int tx3912fbcon_updatevar(int con, struct fb_info *info)
{
/* Nothing */
return 0;
}
/*
* Read a single color register
*/
static int tx3912fb_getcolreg(u_int regno, u_int *red, u_int *green,
u_int *blue, u_int *transp, struct fb_info *info)
{
if (regno > 255)
return 1;
#if FB_IS_GREY
{
u_int grey;
grey = regno * 255 / 15;
#if FB_IS_INVERSE
grey ^= 255;
#endif
grey |= grey << 8;
*red = grey;
*green = grey;
*blue = grey;
}
#else
*red = (palette[regno].red<<8) | palette[regno].red;
*green = (palette[regno].green<<8) | palette[regno].green;
*blue = (palette[regno].blue<<8) | palette[regno].blue;
#endif
*transp = 0;
return 0;
}
/*
* Set a single color register
*/
static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
if (regno > 255)
return 1;
#ifdef FBCON_HAS_CFB8
if( regno < 16 )
fbcon_cmap.cfb8[regno] = ((red & 0xe000) >> 8)
| ((green & 0xe000) >> 11)
| ((blue & 0xc000) >> 14);
#endif
red >>= 8;
green >>= 8;
blue >>= 8;
palette[regno].red = red;
palette[regno].green = green;
palette[regno].blue = blue;
return 0;
} }
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -90,7 +90,7 @@ static int vfb_check_var(struct fb_var_screeninfo *var, ...@@ -90,7 +90,7 @@ static int vfb_check_var(struct fb_var_screeninfo *var,
static int vfb_set_par(struct fb_info *info); static int vfb_set_par(struct fb_info *info);
static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info); u_int transp, struct fb_info *info);
static int vfb_pan_display(struct fb_var_screeninfo *var, static int vfb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info); struct fb_info *info);
static int vfb_mmap(struct fb_info *info, struct file *file, static int vfb_mmap(struct fb_info *info, struct file *file,
struct vm_area_struct *vma); struct vm_area_struct *vma);
...@@ -358,7 +358,7 @@ static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, ...@@ -358,7 +358,7 @@ static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
*/ */
static int vfb_pan_display(struct fb_var_screeninfo *var, static int vfb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info) struct fb_info *info)
{ {
if (var->vmode & FB_VMODE_YWRAP) { if (var->vmode & FB_VMODE_YWRAP) {
......
/* /*
* linux/drivers/video/neofb.h -- NeoMagic Framebuffer Driver * linux/include/video/neo_reg.h -- NeoMagic Framebuffer Driver
* *
* Copyright (c) 2001 Denis Oliver Kropp <dok@convergence.de> * Copyright (c) 2001 Denis Oliver Kropp <dok@convergence.de>
* *
...@@ -8,6 +8,54 @@ ...@@ -8,6 +8,54 @@
* archive for more details. * archive for more details.
*/ */
#define NEO_BS0_BLT_BUSY 0x00000001
#define NEO_BS0_FIFO_AVAIL 0x00000002
#define NEO_BS0_FIFO_PEND 0x00000004
#define NEO_BC0_DST_Y_DEC 0x00000001
#define NEO_BC0_X_DEC 0x00000002
#define NEO_BC0_SRC_TRANS 0x00000004
#define NEO_BC0_SRC_IS_FG 0x00000008
#define NEO_BC0_SRC_Y_DEC 0x00000010
#define NEO_BC0_FILL_PAT 0x00000020
#define NEO_BC0_SRC_MONO 0x00000040
#define NEO_BC0_SYS_TO_VID 0x00000080
#define NEO_BC1_DEPTH8 0x00000100
#define NEO_BC1_DEPTH16 0x00000200
#define NEO_BC1_X_320 0x00000400
#define NEO_BC1_X_640 0x00000800
#define NEO_BC1_X_800 0x00000c00
#define NEO_BC1_X_1024 0x00001000
#define NEO_BC1_X_1152 0x00001400
#define NEO_BC1_X_1280 0x00001800
#define NEO_BC1_X_1600 0x00001c00
#define NEO_BC1_DST_TRANS 0x00002000
#define NEO_BC1_MSTR_BLT 0x00004000
#define NEO_BC1_FILTER_Z 0x00008000
#define NEO_BC2_WR_TR_DST 0x00800000
#define NEO_BC3_SRC_XY_ADDR 0x01000000
#define NEO_BC3_DST_XY_ADDR 0x02000000
#define NEO_BC3_CLIP_ON 0x04000000
#define NEO_BC3_FIFO_EN 0x08000000
#define NEO_BC3_BLT_ON_ADDR 0x10000000
#define NEO_BC3_SKIP_MAPPING 0x80000000
#define NEO_MODE1_DEPTH8 0x0100
#define NEO_MODE1_DEPTH16 0x0200
#define NEO_MODE1_DEPTH24 0x0300
#define NEO_MODE1_X_320 0x0400
#define NEO_MODE1_X_640 0x0800
#define NEO_MODE1_X_800 0x0c00
#define NEO_MODE1_X_1024 0x1000
#define NEO_MODE1_X_1152 0x1400
#define NEO_MODE1_X_1280 0x1800
#define NEO_MODE1_X_1600 0x1c00
#define NEO_MODE1_BLT_ON_ADDR 0x2000
#ifdef __KERNEL__
#ifdef NEOFB_DEBUG #ifdef NEOFB_DEBUG
# define DBG(x) printk (KERN_DEBUG "neofb: %s\n", (x)); # define DBG(x) printk (KERN_DEBUG "neofb: %s\n", (x));
...@@ -15,7 +63,6 @@ ...@@ -15,7 +63,6 @@
# define DBG(x) # define DBG(x)
#endif #endif
#define PCI_CHIP_NM2070 0x0001 #define PCI_CHIP_NM2070 0x0001
#define PCI_CHIP_NM2090 0x0002 #define PCI_CHIP_NM2090 0x0002
#define PCI_CHIP_NM2093 0x0003 #define PCI_CHIP_NM2093 0x0003
...@@ -77,9 +124,7 @@ typedef volatile struct { ...@@ -77,9 +124,7 @@ typedef volatile struct {
#define NEO_EXT_GR_MAX 0xC7 #define NEO_EXT_GR_MAX 0xC7
struct neofb_par { struct neofb_par {
int depth;
unsigned char MiscOutReg; /* Misc */ unsigned char MiscOutReg; /* Misc */
unsigned char CRTC[25]; /* Crtc Controller */ unsigned char CRTC[25]; /* Crtc Controller */
unsigned char Sequencer[5]; /* Video Sequencer */ unsigned char Sequencer[5]; /* Video Sequencer */
...@@ -113,31 +158,11 @@ struct neofb_par { ...@@ -113,31 +158,11 @@ struct neofb_par {
unsigned char VCLK3NumeratorHigh; unsigned char VCLK3NumeratorHigh;
unsigned char VCLK3Denominator; unsigned char VCLK3Denominator;
unsigned char VerticalExt; unsigned char VerticalExt;
};
struct neofb_info {
struct fb_info fb;
struct display_switch *dispsw;
struct pci_dev *pcidev;
int accel;
char *name;
struct {
u8 *vbase;
u32 pbase;
u32 len;
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
int mtrr; int mtrr;
#endif #endif
} video; u8 *mmio_vbase;
struct {
u8 *vbase;
u32 pbase;
u32 len;
} mmio;
Neo2200 *neo2200; Neo2200 *neo2200;
...@@ -151,20 +176,14 @@ struct neofb_info { ...@@ -151,20 +176,14 @@ struct neofb_info {
int lcd_stretch; int lcd_stretch;
int internal_display; int internal_display;
int external_display; int external_display;
struct {
u16 red, green, blue, transp;
} palette[NR_PALETTE];
}; };
typedef struct { typedef struct {
int x_res; int x_res;
int y_res; int y_res;
int mode; int mode;
} biosMode; } biosMode;
/* vga IO functions */ /* vga IO functions */
static inline u8 VGArCR (u8 index) static inline u8 VGArCR (u8 index)
{ {
...@@ -241,51 +260,5 @@ static inline void VGAwMISC (u8 value) ...@@ -241,51 +260,5 @@ static inline void VGAwMISC (u8 value)
{ {
outb (value, 0x3c2); outb (value, 0x3c2);
} }
#endif
#define NEO_BS0_BLT_BUSY 0x00000001
#define NEO_BS0_FIFO_AVAIL 0x00000002
#define NEO_BS0_FIFO_PEND 0x00000004
#define NEO_BC0_DST_Y_DEC 0x00000001
#define NEO_BC0_X_DEC 0x00000002
#define NEO_BC0_SRC_TRANS 0x00000004
#define NEO_BC0_SRC_IS_FG 0x00000008
#define NEO_BC0_SRC_Y_DEC 0x00000010
#define NEO_BC0_FILL_PAT 0x00000020
#define NEO_BC0_SRC_MONO 0x00000040
#define NEO_BC0_SYS_TO_VID 0x00000080
#define NEO_BC1_DEPTH8 0x00000100
#define NEO_BC1_DEPTH16 0x00000200
#define NEO_BC1_X_320 0x00000400
#define NEO_BC1_X_640 0x00000800
#define NEO_BC1_X_800 0x00000c00
#define NEO_BC1_X_1024 0x00001000
#define NEO_BC1_X_1152 0x00001400
#define NEO_BC1_X_1280 0x00001800
#define NEO_BC1_X_1600 0x00001c00
#define NEO_BC1_DST_TRANS 0x00002000
#define NEO_BC1_MSTR_BLT 0x00004000
#define NEO_BC1_FILTER_Z 0x00008000
#define NEO_BC2_WR_TR_DST 0x00800000
#define NEO_BC3_SRC_XY_ADDR 0x01000000
#define NEO_BC3_DST_XY_ADDR 0x02000000
#define NEO_BC3_CLIP_ON 0x04000000
#define NEO_BC3_FIFO_EN 0x08000000
#define NEO_BC3_BLT_ON_ADDR 0x10000000
#define NEO_BC3_SKIP_MAPPING 0x80000000
#define NEO_MODE1_DEPTH8 0x0100
#define NEO_MODE1_DEPTH16 0x0200
#define NEO_MODE1_DEPTH24 0x0300
#define NEO_MODE1_X_320 0x0400
#define NEO_MODE1_X_640 0x0800
#define NEO_MODE1_X_800 0x0c00
#define NEO_MODE1_X_1024 0x1000
#define NEO_MODE1_X_1152 0x1400
#define NEO_MODE1_X_1280 0x1800
#define NEO_MODE1_X_1600 0x1c00
#define NEO_MODE1_BLT_ON_ADDR 0x2000
/*
* Permedia2 framebuffer driver definitions.
* Copyright (c) 1998-2000 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
* --------------------------------------------------------------------------
* $Id: pm2fb.h,v 1.26 2000/09/19 00:11:53 illo Exp $
* --------------------------------------------------------------------------
* 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 PM2FB_H
#define PM2FB_H
#define PM2_REFERENCE_CLOCK 14318 /* in KHz */
#define PM2_MAX_PIXCLOCK 230000 /* in KHz */
#define PM2_REGS_SIZE 0x10000
#define PM2TAG(r) (u32 )(((r)-0x8000)>>3)
/*****************************************************************************
* Permedia2 registers used in the framebuffer
*****************************************************************************/
#define PM2R_RESET_STATUS 0x0000
#define PM2R_IN_FIFO_SPACE 0x0018
#define PM2R_OUT_FIFO_WORDS 0x0020
#define PM2R_APERTURE_ONE 0x0050
#define PM2R_APERTURE_TWO 0x0058
#define PM2R_FIFO_DISCON 0x0068
#define PM2R_CHIP_CONFIG 0x0070
#define PM2R_REBOOT 0x1000
#define PM2R_MEM_CONTROL 0x1040
#define PM2R_BOOT_ADDRESS 0x1080
#define PM2R_MEM_CONFIG 0x10c0
#define PM2R_BYPASS_WRITE_MASK 0x1100
#define PM2R_FRAMEBUFFER_WRITE_MASK 0x1140
#define PM2R_OUT_FIFO 0x2000
#define PM2R_SCREEN_BASE 0x3000
#define PM2R_SCREEN_STRIDE 0x3008
#define PM2R_H_TOTAL 0x3010
#define PM2R_HG_END 0x3018
#define PM2R_HB_END 0x3020
#define PM2R_HS_START 0x3028
#define PM2R_HS_END 0x3030
#define PM2R_V_TOTAL 0x3038
#define PM2R_VB_END 0x3040
#define PM2R_VS_START 0x3048
#define PM2R_VS_END 0x3050
#define PM2R_VIDEO_CONTROL 0x3058
#define PM2R_LINE_COUNT 0x3070
#define PM2R_FIFO_CONTROL 0x3078
#define PM2R_RD_PALETTE_WRITE_ADDRESS 0x4000
#define PM2R_RD_PALETTE_DATA 0x4008
#define PM2R_RD_PIXEL_MASK 0x4010
#define PM2R_RD_PALETTE_READ_ADDRESS 0x4018
#define PM2R_RD_INDEXED_DATA 0x4050
#define PM2R_START_X_DOM 0x8000
#define PM2R_D_X_DOM 0x8008
#define PM2R_START_X_SUB 0x8010
#define PM2R_D_X_SUB 0x8018
#define PM2R_START_Y 0x8020
#define PM2R_D_Y 0x8028
#define PM2R_COUNT 0x8030
#define PM2R_RENDER 0x8038
#define PM2R_RASTERIZER_MODE 0x80a0
#define PM2R_RECTANGLE_ORIGIN 0x80d0
#define PM2R_RECTANGLE_SIZE 0x80d8
#define PM2R_PACKED_DATA_LIMITS 0x8150
#define PM2R_SCISSOR_MODE 0x8180
#define PM2R_SCREEN_SIZE 0x8198
#define PM2R_AREA_STIPPLE_MODE 0x81a0
#define PM2R_WINDOW_ORIGIN 0x81c8
#define PM2R_TEXTURE_ADDRESS_MODE 0x8380
#define PM2R_TEXTURE_MAP_FORMAT 0x8588
#define PM2R_TEXTURE_DATA_FORMAT 0x8590
#define PM2R_TEXTURE_READ_MODE 0x8670
#define PM2R_TEXEL_LUT_MODE 0x8678
#define PM2R_TEXTURE_COLOR_MODE 0x8680
#define PM2R_FOG_MODE 0x8690
#define PM2R_COLOR_DDA_MODE 0x87e0
#define PM2R_ALPHA_BLEND_MODE 0x8810
#define PM2R_DITHER_MODE 0x8818
#define PM2R_FB_SOFT_WRITE_MASK 0x8820
#define PM2R_LOGICAL_OP_MODE 0x8828
#define PM2R_LB_READ_MODE 0x8880
#define PM2R_LB_READ_FORMAT 0x8888
#define PM2R_LB_SOURCE_OFFSET 0x8890
#define PM2R_LB_WINDOW_BASE 0x88b8
#define PM2R_LB_WRITE_FORMAT 0x88c8
#define PM2R_STENCIL_MODE 0x8988
#define PM2R_DEPTH_MODE 0x89a0
#define PM2R_FB_READ_MODE 0x8a80
#define PM2R_FB_SOURCE_OFFSET 0x8a88
#define PM2R_FB_PIXEL_OFFSET 0x8a90
#define PM2R_FB_WINDOW_BASE 0x8ab0
#define PM2R_FB_WRITE_MODE 0x8ab8
#define PM2R_FB_HARD_WRITE_MASK 0x8ac0
#define PM2R_FB_BLOCK_COLOR 0x8ac8
#define PM2R_FB_READ_PIXEL 0x8ad0
#define PM2R_FILTER_MODE 0x8c00
#define PM2R_SYNC 0x8c40
#define PM2R_YUV_MODE 0x8f00
#define PM2R_STATISTICS_MODE 0x8c08
#define PM2R_FB_SOURCE_DELTA 0x8d88
#define PM2R_CONFIG 0x8d90
#define PM2R_DELTA_MODE 0x9300
/* Permedia2v */
#define PM2VR_RD_INDEX_LOW 0x4020
#define PM2VR_RD_INDEX_HIGH 0x4028
#define PM2VR_RD_INDEXED_DATA 0x4030
/* Permedia2 RAMDAC indexed registers */
#define PM2I_RD_CURSOR_CONTROL 0x06
#define PM2I_RD_COLOR_MODE 0x18
#define PM2I_RD_MODE_CONTROL 0x19
#define PM2I_RD_MISC_CONTROL 0x1e
#define PM2I_RD_PIXEL_CLOCK_A1 0x20
#define PM2I_RD_PIXEL_CLOCK_A2 0x21
#define PM2I_RD_PIXEL_CLOCK_A3 0x22
#define PM2I_RD_PIXEL_CLOCK_STATUS 0x29
#define PM2I_RD_MEMORY_CLOCK_1 0x30
#define PM2I_RD_MEMORY_CLOCK_2 0x31
#define PM2I_RD_MEMORY_CLOCK_3 0x32
#define PM2I_RD_MEMORY_CLOCK_STATUS 0x33
#define PM2I_RD_COLOR_KEY_CONTROL 0x40
#define PM2I_RD_OVERLAY_KEY 0x41
#define PM2I_RD_RED_KEY 0x42
#define PM2I_RD_GREEN_KEY 0x43
#define PM2I_RD_BLUE_KEY 0x44
/* Permedia2v extensions */
#define PM2VI_RD_MISC_CONTROL 0x000
#define PM2VI_RD_SYNC_CONTROL 0x001
#define PM2VI_RD_DAC_CONTROL 0x002
#define PM2VI_RD_PIXEL_SIZE 0x003
#define PM2VI_RD_COLOR_FORMAT 0x004
#define PM2VI_RD_CURSOR_MODE 0x005
#define PM2VI_RD_CURSOR_X_LOW 0x007
#define PM2VI_RD_CURSOR_X_HIGH 0x008
#define PM2VI_RD_CURSOR_Y_LOW 0x009
#define PM2VI_RD_CURSOR_Y_HIGH 0x00A
#define PM2VI_RD_CURSOR_X_HOT 0x00B
#define PM2VI_RD_CURSOR_Y_HOT 0x00C
#define PM2VI_RD_CLK0_PRESCALE 0x201
#define PM2VI_RD_CLK0_FEEDBACK 0x202
#define PM2VI_RD_CLK0_POSTSCALE 0x203
#define PM2VI_RD_CLK1_PRESCALE 0x204
#define PM2VI_RD_CLK1_FEEDBACK 0x205
#define PM2VI_RD_CLK1_POSTSCALE 0x206
#define PM2VI_RD_CURSOR_PALETTE 0x303
#define PM2VI_RD_CURSOR_PATTERN 0x400
/* Fields and flags */
#define PM2F_RENDER_AREASTIPPLE (1L<<0)
#define PM2F_RENDER_FASTFILL (1L<<3)
#define PM2F_RENDER_PRIMITIVE_MASK (3L<<6)
#define PM2F_RENDER_LINE 0
#define PM2F_RENDER_TRAPEZOID (1L<<6)
#define PM2F_RENDER_POINT (2L<<6)
#define PM2F_RENDER_RECTANGLE (3L<<6)
#define PM2F_SYNCHRONIZATION (1L<<10)
#define PM2F_PLL_LOCKED 0x10
#define PM2F_BEING_RESET (1L<<31)
#define PM2F_DATATYPE_COLOR 0x8000
#define PM2F_VGA_ENABLE 0x02
#define PM2F_VGA_FIXED 0x04
#define PM2F_FB_WRITE_ENABLE 0x01
#define PM2F_FB_READ_SOURCE_ENABLE 0x0200
#define PM2F_RD_PALETTE_WIDTH_8 0x02
#define PM2F_PART_PROD_MASK 0x01ff
#define PM2F_SCREEN_SCISSOR_ENABLE 0x02
#define PM2F_DATA_64_ENABLE 0x00010000
#define PM2F_BLANK_LOW 0x02
#define PM2F_HSYNC_MASK 0x18
#define PM2F_VSYNC_MASK 0x60
#define PM2F_HSYNC_ACT_HIGH 0x08
#define PM2F_HSYNC_FORCED_LOW 0x10
#define PM2F_HSYNC_ACT_LOW 0x18
#define PM2F_VSYNC_ACT_HIGH 0x20
#define PM2F_VSYNC_FORCED_LOW 0x40
#define PM2F_VSYNC_ACT_LOW 0x60
#define PM2F_LINE_DOUBLE 0x04
#define PM2F_VIDEO_ENABLE 0x01
#define PM2F_RD_GUI_ACTIVE 0x10
#define PM2F_RD_COLOR_MODE_RGB 0x20
#define PM2F_DELTA_ORDER_RGB (1L<<18)
#define PM2F_RD_TRUECOLOR 0x80
#define PM2F_NO_ALPHA_BUFFER 0x10
#define PM2F_TEXTEL_SIZE_16 0x00080000
#define PM2F_TEXTEL_SIZE_32 0x00100000
#define PM2F_TEXTEL_SIZE_4 0x00180000
#define PM2F_TEXTEL_SIZE_24 0x00200000
#define PM2F_INCREASE_X (1L<<21)
#define PM2F_INCREASE_Y (1L<<22)
#define PM2F_CONFIG_FB_WRITE_ENABLE (1L<<3)
#define PM2F_CONFIG_FB_PACKED_DATA (1L<<2)
#define PM2F_CONFIG_FB_READ_DEST_ENABLE (1L<<1)
#define PM2F_CONFIG_FB_READ_SOURCE_ENABLE (1L<<0)
#define PM2F_COLOR_KEY_TEST_OFF (1L<<4)
#define PM2F_MEM_CONFIG_RAM_MASK (3L<<29)
#define PM2F_MEM_BANKS_1 0L
#define PM2F_MEM_BANKS_2 (1L<<29)
#define PM2F_MEM_BANKS_3 (2L<<29)
#define PM2F_MEM_BANKS_4 (3L<<29)
typedef enum {
PM2_TYPE_PERMEDIA2,
PM2_TYPE_PERMEDIA2V
} pm2type_t;
#endif /* PM2FB_H */
/*****************************************************************************
* That's all folks!
*****************************************************************************/
/* /*
* linux/drivers/video/tx3912fb.h * linux/include/video/tx3912.h
* *
* Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com) * Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com)
* *
...@@ -60,69 +60,3 @@ ...@@ -60,69 +60,3 @@
/* Video Control 4 Register */ /* Video Control 4 Register */
#define TX3912_VIDCTRL4_VIDBASELO_MASK 0x000ffff0 #define TX3912_VIDCTRL4_VIDBASELO_MASK 0x000ffff0
/*
* Begin platform specific configurations
*/
#if defined(CONFIG_NINO_4MB) || defined(CONFIG_NINO_8MB)
#define FB_X_RES 240
#define FB_Y_RES 320
#if defined(CONFIG_FBCON_CFB4)
#define FB_BPP 4
#else
#if defined(CONFIG_FBCON_CFB2)
#define FB_BPP 2
#else
#define FB_BPP 1
#endif
#endif
#define FB_IS_GREY 1
#define FB_IS_INVERSE 0
#endif
#ifdef CONFIG_NINO_16MB
#define FB_X_RES 240
#define FB_Y_RES 320
#define FB_BPP 8
#define FB_IS_GREY 0
#define FB_IS_INVERSE 0
#endif
/*
* Define virtual resolutions if necessary
*/
#ifndef FB_X_VIRTUAL_RES
#define FB_X_VIRTUAL_RES FB_X_RES
#endif
#ifndef FB_Y_VIRTUAL_RES
#define FB_Y_VIRTUAL_RES FB_Y_RES
#endif
/*
* Framebuffer address and size
*/
u_long tx3912fb_paddr = 0;
u_long tx3912fb_vaddr = 0;
u_long tx3912fb_size = (FB_X_RES * FB_Y_RES * FB_BPP / 8);
/*
* Framebuffer info structure
*/
static struct fb_var_screeninfo tx3912fb_info = {
FB_X_RES, FB_Y_RES,
FB_X_VIRTUAL_RES, FB_Y_VIRTUAL_RES,
0, 0,
FB_BPP, FB_IS_GREY,
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
0, FB_ACTIVATE_NOW,
-1, -1, 0, 20000,
64, 64, 32, 32, 64, 2,
0, FB_VMODE_NONINTERLACED,
{0,0,0,0,0,0}
};
/*
* Framebuffer name
*/
static char TX3912FB_NAME[16] = "tx3912fb";
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment