Commit e970606b authored by James Simmons's avatar James Simmons

Merge heisenberg.transvirtual.com:/tmp/linus-2.5

into heisenberg.transvirtual.com:/tmp/fbdev-2.5
parents d0f0cde1 b30e6e18
Tridentfb is a framebuffer driver for some Trident chip based cards.
The following list of chips is thought to be supported although not all are
tested:
those from the Image series with Cyber in their names - accelerated
those with Blade in their names (Blade3D,CyberBlade...) - accelerated
the newer CyberBladeXP family - nonaccelerated
Only PCI/AGP based cards are supported, none of the older Tridents.
How to use it?
==============
Just do your usual console work :)
When booting you can pass the following parameters
==================================================
noaccel - turns off acceleration (when it doesn't work for your card)
accel - force text acceleration (for boards which by default are noacceled)
fp - use flat panel related stuff
crt - assume monitor is present instead of fp
center - for flat panels and resolutions smaller than native size center the
image, otherwise use
stretch
memsize - integer value in Kb, use if your card's memory size is misdetected.
look at the driver output to see what it says when initializing.
memdiff - integer value in Kb,should be nonzero if your card reports
more memory than it actually has.For instance mine is 192K less than
detection says in all three BIOS selectable situations 2M, 4M, 8M.
Only use if your video memory is taken from main memory hence of
configurable size.Otherwise use memsize.
If in some modes which barely fit the memory you see garbage at the bottom
this might help by not letting change to that mode anymore.
nativex - the width in pixels of the flat panel.If you know it (usually 1024
800 or 1280) and it is not what the driver seems to detect use it.
bpp - bits per pixel (8,16 or 32)
mode - a mode name like 800x600 (as described in Documentation/fb/modedb.txt)
Using insane values for the above parameters will probably result in driver
misbehaviour so take care(for instance memsize=12345678 or memdiff=23784 or
nativex=93)
Contact: jani@astechnix.ro
......@@ -10,9 +10,6 @@ bool 'Support for frame buffer devices (EXPERIMENTAL)' CONFIG_FB
if [ "$CONFIG_FB" = "y" ]; then
define_bool CONFIG_DUMMY_CONSOLE y
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
if [ "$CONFIG_PCI" = "y" ]; then
tristate ' nVidia Riva support (EXPERIMENTAL)' CONFIG_FB_RIVA
fi
if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_PCI" = "y" ]; then
tristate ' Cirrus Logic support (EXPERIMENTAL)' CONFIG_FB_CLGEN
tristate ' Permedia2 support (EXPERIMENTAL)' CONFIG_FB_PM2
......@@ -127,6 +124,7 @@ if [ "$CONFIG_FB" = "y" ]; then
fi
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
if [ "$CONFIG_PCI" != "n" ]; then
tristate ' nVidia Riva support (EXPERIMENTAL)' CONFIG_FB_RIVA
tristate ' Matrox acceleration (EXPERIMENTAL)' CONFIG_FB_MATROX
if [ "$CONFIG_FB_MATROX" != "n" ]; then
bool ' Millennium I/II support' CONFIG_FB_MATROX_MILLENIUM
......@@ -156,6 +154,8 @@ if [ "$CONFIG_FB" = "y" ]; then
tristate ' NeoMagic display support (EXPERIMENTAL)' CONFIG_FB_NEOMAGIC
tristate ' 3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)' CONFIG_FB_3DFX
tristate ' 3Dfx Voodoo Graphics (sst1) support (EXPERIMENTAL)' CONFIG_FB_VOODOO1
tristate ' Trident support (EXPERIMENTAL)' CONFIG_FB_TRIDENT
tristate ' Permedia3 support (EXPERIMENTAL)' CONFIG_FB_PM3
fi
fi
if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
......@@ -220,6 +220,7 @@ if [ "$CONFIG_FB" = "y" ]; then
tristate ' 16 bpp packed pixels support' CONFIG_FBCON_CFB16
tristate ' 24 bpp packed pixels support' CONFIG_FBCON_CFB24
tristate ' 32 bpp packed pixels support' CONFIG_FBCON_CFB32
tristate ' Hardware acceleration support' CONFIG_FBCON_ACCEL
tristate ' Amiga bitplanes support' CONFIG_FBCON_AFB
tristate ' Amiga interleaved bitplanes support' CONFIG_FBCON_ILBM
tristate ' Atari interleaved bitplanes (2 planes) support' CONFIG_FBCON_IPLAN2P2
......@@ -265,10 +266,10 @@ if [ "$CONFIG_FB" = "y" ]; then
if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_ATARI" = "y" -o \
"$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
"$CONFIG_FB_OF" = "y" -o "$CONFIG_FB_TGA" = "y" -o \
"$CONFIG_FB_VESA" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
"$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_TCX" = "y" -o "$CONFIG_FB_CGTHREE" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_G364" = "y" -o \
"$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_TRIDENT" = "y" -o \
"$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
"$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
"$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
......@@ -279,16 +280,16 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_3DFX" = "y" -o \
"$CONFIG_FB_PMAG_BA" = "y" -o "$CONFIG_FB_PMAGB_B" = "y" -o \
"$CONFIG_FB_MAXINE" = "y" -o "$CONFIG_FB_TX3912" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" ]; then
"$CONFIG_FB_SIS" = "y" ]; then
define_tristate CONFIG_FBCON_CFB8 y
else
if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
"$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_MAC" = "m" -o \
"$CONFIG_FB_OF" = "m" -o "$CONFIG_FB_TGA" = "m" -o \
"$CONFIG_FB_VESA" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
"$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_PM3" = "m" -o \
"$CONFIG_FB_TCX" = "m" -o "$CONFIG_FB_CGTHREE" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_G364" = "m" -o \
"$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_TRIDENT" = "m" -o \
"$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
"$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
"$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
......@@ -299,14 +300,14 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_PMAG_BA" = "m" -o "$CONFIG_FB_PMAGB_B" = "m" -o \
"$CONFIG_FB_MAXINE" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
"$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_NEOMAGIC" = "m" ]; then
"$CONFIG_FB_TX3912" = "m" ]; then
define_tristate CONFIG_FBCON_CFB8 m
fi
fi
if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \
"$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_VESA" = "y" -o \
"$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \
"$CONFIG_FB_Q40" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \
"$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" -o \
"$CONFIG_FB_TRIDENT" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \
"$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
"$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
......@@ -315,14 +316,13 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
"$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_3DFX" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \
"$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_VOODOO1" = "y" -o \
"$CONFIG_FB_NEOMAGIC" = "y" ]; then
"$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_PM3" = "y" ]; then
define_tristate CONFIG_FBCON_CFB16 y
else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
"$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_VESA" = "m" -o \
"$CONFIG_FB_VIRTUAL" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \
"$CONFIG_FB_Q40" = "m" -o "$CONFIG_FB_3DFX" = "m" -o \
"$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_NEOMAGIC" = "m" -o \
"$CONFIG_FB_TRIDENT" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \
"$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_3DFX" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
"$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
......@@ -331,8 +331,7 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_VOODOO1" = "m" -o \
"$CONFIG_FB_NEOMAGIC" = "m" ]; then
"$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_PM3" = "m" ]; then
define_tristate CONFIG_FBCON_CFB16 m
fi
fi
......@@ -354,29 +353,39 @@ if [ "$CONFIG_FB" = "y" ]; then
fi
fi
if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \
"$CONFIG_FB_VESA" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
"$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_TRIDENT" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_TGA" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
"$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
"$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
"$CONFIG_FB_FM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \
"$CONFIG_FB_RADEON" = "y" -o "$CONFIG_FB_PVR2" = "y" -o \
"$CONFIG_FB_3DFX" = "y" -o "$CONFIG_FB_SIS" = "y" -o \
"$CONFIG_FB_VOODOO1" = "y" ]; then
"$CONFIG_FB_3DFX" = "y" -o "$CONFIG_FB_PM3" = "y" ]; then
define_tristate CONFIG_FBCON_CFB32 y
else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
"$CONFIG_FB_VESA" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
"$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_TRIDENT" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_TGA" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
"$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
"$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_3DFX" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
"$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_VOODOO1" = "m" ]; then
"$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_PM3" = "y" ]; then
define_tristate CONFIG_FBCON_CFB32 m
fi
fi
if [ "$CONFIG_FB_VESA" = "y" -o "$CONFIG_FB_Q40" = "y" -o \
"$CONFIG_FB_FM2" = "y" -o "$CONFIG_FB_HIT" = "y" -o \
"$CONFIG_FB_ANAKIN" = "y" -o "$CONFIG_FB_G364" = "y" -o \
"$CONFIG_FB_VIRTUAL" = "y" ]; then
define_tristate CONFIG_FBCON_ACCEL y
else
if [ "$CONFIG_FB_HIT" = "m" -o "$CONFIG_FB_G364" = "m" -o \
"$CONFIG_FB_VIRTUAL" = "m" ]; then
define_tristate CONFIG_FBCON_ACCEL m
fi
fi
if [ "$CONFIG_FB_AMIGA" = "y" ]; then
define_tristate CONFIG_FBCON_AFB y
define_tristate CONFIG_FBCON_ILBM y
......@@ -399,10 +408,10 @@ if [ "$CONFIG_FB" = "y" ]; then
# define_tristate CONFIG_FBCON_IPLAN2P16 m
fi
fi
if [ "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" ]; then
if [ "$CONFIG_FB_MAC" = "y" ]; then
define_tristate CONFIG_FBCON_MAC y
else
if [ "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then
if [ "$CONFIG_FB_MAC" = "m" ]; then
define_tristate CONFIG_FBCON_MAC m
fi
fi
......
......@@ -44,8 +44,9 @@ endif
obj-$(CONFIG_FB_ACORN) += acornfb.o
obj-$(CONFIG_FB_AMIGA) += amifb.o
obj-$(CONFIG_FB_PM2) += pm2fb.o
obj-$(CONFIG_FB_PM3) += pm3fb.o
obj-$(CONFIG_FB_APOLLO) += dnfb.o
obj-$(CONFIG_FB_Q40) += q40fb.o
obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_ATARI) += atafb.o
obj-$(CONFIG_FB_ATY128) += aty128fb.o
obj-$(CONFIG_FB_RADEON) += radeonfb.o
......@@ -67,13 +68,14 @@ obj-$(CONFIG_FB_OF) += offb.o
obj-$(CONFIG_FB_IMSTT) += imsttfb.o
obj-$(CONFIG_FB_RETINAZ3) += retz3fb.o
obj-$(CONFIG_FB_CLGEN) += clgenfb.o
obj-$(CONFIG_FB_TRIDENT) += tridentfb.o
obj-$(CONFIG_FB_S3TRIO) += S3triofb.o
obj-$(CONFIG_FB_TGA) += tgafb.o
obj-$(CONFIG_FB_VESA) += vesafb.o
obj-$(CONFIG_FB_VESA) += vesafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_VGA16) += vga16fb.o fbcon-vga-planes.o
obj-$(CONFIG_FB_VIRGE) += virgefb.o
obj-$(CONFIG_FB_G364) += g364fb.o
obj-$(CONFIG_FB_FM2) += fm2fb.o
obj-$(CONFIG_FB_FM2) += fm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_CREATOR) += creatorfb.o sbusfb.o
obj-$(CONFIG_FB_CGSIX) += cgsixfb.o sbusfb.o
obj-$(CONFIG_FB_BWTWO) += bwtwofb.o sbusfb.o
......@@ -114,7 +116,7 @@ obj-$(CONFIG_FB_BWTWO) += bwtwofb.o
obj-$(CONFIG_FB_HGA) += hgafb.o
obj-$(CONFIG_FB_SA1100) += sa1100fb.o
obj-$(CONFIG_FB_VIRTUAL) += vfb.o
obj-$(CONFIG_FB_HIT) += hitfb.o
obj-$(CONFIG_FB_HIT) += hitfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_E1355) += epson1355fb.o
obj-$(CONFIG_FB_PVR2) += pvr2fb.o
obj-$(CONFIG_FB_VOODOO1) += sstfb.o
......@@ -138,6 +140,7 @@ obj-$(CONFIG_FBCON_MFB) += fbcon-mfb.o
obj-$(CONFIG_FBCON_VGA) += fbcon-vga.o
obj-$(CONFIG_FBCON_HGA) += fbcon-hga.o
obj-$(CONFIG_FBCON_STI) += fbcon-sti.o
obj-$(CONFIG_FBCON_ACCEL) += fbcon-accel.o
include $(TOPDIR)/Rules.make
......
......@@ -601,13 +601,13 @@ acornfb_adjust_timing(struct fb_var_screeninfo *var, int con)
/* Find int 'y', such that y * fll == s * sam < maxsize
* y = s * sam / fll; s = maxsize / sam
*/
for (size = current_par.screen_size; min_size <= size;
for (size = current_par.screen_size;
nr_y = size / font_line_len, min_size <= size;
size -= sam_size) {
nr_y = size / font_line_len;
if (nr_y * font_line_len == size)
break;
}
nr_y *= fontht;
if (var->accel_flags & FB_ACCELF_TEXT) {
if (min_size > size) {
......@@ -617,8 +617,9 @@ acornfb_adjust_timing(struct fb_var_screeninfo *var, int con)
size = current_par.screen_size;
var->yres_virtual = size / (font_line_len / fontht);
} else
var->yres_virtual = nr_y * fontht;
}
var->yres_virtual = nr_y;
} else if (var->yres_virtual > nr_y)
var->yres_virtual = nr_y;
current_par.screen_end = current_par.screen_base_p + size;
......@@ -1100,6 +1101,41 @@ acornfb_pan_display(struct fb_var_screeninfo *var, int con,
return 0;
}
static int
acornfb_blank(int blank, struct fb_info *info)
{
union palette p;
int i, bpp = fb_display[info->currcon].var.bits_per_pixel;
#ifdef FBCON_HAS_CFB16
if (bpp == 16) {
p.p = 0;
for (i = 0; i < 256; i++) {
if (blank)
p = acornfb_palette_encode(i, 0, 0, 0, 0);
else {
p.vidc20.red = current_par.palette[ i & 31].vidc20.red;
p.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;
p.vidc20.blue = current_par.palette[(i >> 2) & 31].vidc20.blue;
}
acornfb_palette_write(i, current_par.palette[i]);
}
} else
#endif
{
for (i = 0; i < current_par.palette_size; i++) {
if (blank)
p = acornfb_palette_encode(i, 0, 0, 0, 0);
else
p = current_par.palette[i];
acornfb_palette_write(i, p);
}
}
return 0;
}
/*
* Note that we are entered with the kernel locked.
*/
......@@ -1146,7 +1182,7 @@ static struct fb_ops acornfb_ops = {
fb_set_var: acornfb_set_var,
fb_get_cmap: acornfb_get_cmap,
fb_set_cmap: gen_set_cmap,
fb_set_colreg: acornfb_setcolreg,
fb_setcolreg: acornfb_setcolreg,
fb_pan_display: acornfb_pan_display,
fb_blank: acornfb_blank,
fb_mmap: acornfb_mmap,
......@@ -1182,41 +1218,6 @@ acornfb_switch(int con, struct fb_info *info)
return 0;
}
static int
acornfb_blank(int blank, struct fb_info *info)
{
union palette p;
int i, bpp = fb_display[info->currcon].var.bits_per_pixel;
#ifdef FBCON_HAS_CFB16
if (bpp == 16) {
p.p = 0;
for (i = 0; i < 256; i++) {
if (blank)
p = acornfb_palette_encode(i, 0, 0, 0, 0);
else {
p.vidc20.red = current_par.palette[ i & 31].vidc20.red;
p.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;
p.vidc20.blue = current_par.palette[(i >> 2) & 31].vidc20.blue;
}
acornfb_palette_write(i, current_par.palette[i]);
}
} else
#endif
{
for (i = 0; i < current_par.palette_size; i++) {
if (blank)
p = acornfb_palette_encode(i, 0, 0, 0, 0);
else
p = current_par.palette[i];
acornfb_palette_write(i, p);
}
}
return 0;
}
/*
* Everything after here is initialisation!!!
*/
......
......@@ -23,23 +23,34 @@
#include <video/fbcon.h>
#include <video/fbcon-cfb16.h>
static u16 colreg[16];
static u32 colreg[16];
static struct fb_info fb_info;
static struct display display;
static int
anakinfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info)
{
if (regno > 15)
return 1;
static struct fb_var_screeninfo anakinfb_var = {
xres: 400,
yres: 234,
xres_virtual: 400,
yres_virtual: 234,
bits_per_pixel: 16,
red: { 11, 5, 0 },
green: { 5, 6, 0 },
blue: { 0, 5, 0 },
activate: FB_ACTIVATE_NOW,
height: -1,
width: -1,
vmode: FB_VMODE_NONINTERLACED,
};
*red = colreg[regno] & 0xf800;
*green = colreg[regno] & 0x7e0 << 5;
*blue = colreg[regno] & 0x1f << 11;
*transp = 0;
return 0;
}
static struct fb_fix_screeninfo anakinfb_fix = {
id: "AnakinFB",
smem_start: VGA_START,
smem_len: VGA_SIZE,
type: FB_TYPE_PACKED_PIXELS,
visual: FB_VISUAL_TRUECOLOR,
line_length: 400*2,
accel: FB_ACCEL_NONE,
};
static int
anakinfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
......@@ -53,153 +64,48 @@ anakinfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
return 0;
}
static int
anakinfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, "AnakinFB");
fix->smem_start = VGA_START;
fix->smem_len = VGA_SIZE;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
fix->visual = FB_VISUAL_TRUECOLOR;
fix->xpanstep = 0;
fix->ypanstep = 0;
fix->ywrapstep = 0;
fix->line_length = 400 * 2;
fix->accel = FB_ACCEL_NONE;
return 0;
}
static int
anakinfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
memset(var, 0, sizeof(struct fb_var_screeninfo));
var->xres = 400;
var->yres = 234;
var->xres_virtual = 400;
var->yres_virtual = 234;
var->xoffset = 0;
var->yoffset = 0;
var->bits_per_pixel = 16;
var->grayscale = 0;
var->red.offset = 11;
var->red.length = 5;
var->green.offset = 5;
var->green.length = 6;
var->blue.offset = 0;
var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
var->nonstd = 0;
var->activate = FB_ACTIVATE_NOW;
var->height = -1;
var->width = -1;
var->pixclock = 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;
var->sync = 0;
var->vmode = FB_VMODE_NONINTERLACED;
return 0;
}
static int
anakinfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
return -EINVAL;
}
static int
anakinfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
if (con == info->currcon)
return fb_get_cmap(cmap, kspc, anakinfb_getcolreg, info);
else if (fb_display[con].cmap.len)
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
fb_copy_cmap(fb_default_cmap(16), cmap, kspc ? 0 : 2);
return 0;
}
static int
anakinfb_switch_con(int con, struct fb_info *info)
{
info->currcon = con;
return 0;
}
static int
anakinfb_updatevar(int con, struct fb_info *info)
{
return 0;
}
static void
anakinfb_blank(int blank, struct fb_info *info)
{
/*
* TODO: use I2C to blank/unblank the screen
*/
}
static struct fb_ops anakinfb_ops = {
owner: THIS_MODULE,
fb_get_fix: anakinfb_get_fix,
fb_get_var: anakinfb_get_var,
fb_set_var: anakinfb_set_var,
fb_get_cmap: anakinfb_get_cmap,
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_setcolreg: anakinfb_setcolreg,
fb_blank: anakinfb_blank,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
};
int __init
anakinfb_init(void)
{
memset(&fb_info, 0, sizeof(struct fb_info));
strcpy(fb_info.modename, "AnakinFB");
fb_info.node = NODEV;
memset(&display, 0, sizeof(struct display));
strcpy(fb_info.modename, anakinfb_fix.id);
fb_info.node = fb_info.currcon = -1;
fb_info.flags = FBINFO_FLAG_DEFAULT;
fb_info.fbops = &anakinfb_ops;
fb_info.currcon = -1;
fb_info.var = anakinfb_var;
fb_info.fix = anakinfb_fix;
fb_info.disp = &display;
strcpy(fb_info.fontname, "VGA8x16");
fb_info.changevar = NULL;
fb_info.switch_con = &anakinfb_switch_con;
fb_info.updatevar = &anakinfb_updatevar;
memset(&display, 0, sizeof(struct display));
anakinfb_get_var(&display.var, 0, &fb_info);
fb_info.switch_con = gen_switch_con;
fb_info.updatevar = gen_update_var;
if (!(request_mem_region(VGA_START, VGA_SIZE, "vga")))
return -ENOMEM;
if (!(fb_info.screen_base = ioremap(VGA_START, VGA_SIZE))) {
if (fb_info.screen_base = ioremap(VGA_START, VGA_SIZE)) {
release_mem_region(VGA_START, VGA_SIZE);
return -EIO;
}
display.visual = FB_VISUAL_TRUECOLOR;
display.type = FB_TYPE_PACKED_PIXELS;
display.type_aux = 0;
display.ypanstep = 0;
display.ywrapstep = 0;
display.line_length = 400 * 2;
display.can_soft_blank = 1;
display.inverse = 0;
#ifdef FBCON_HAS_CFB16
display.dispsw = &fbcon_cfb16;
display.dispsw_data = colreg;
#else
display.dispsw = &fbcon_dummy;
#endif
fb_alloc_cmap(&fb_info.cmap, 16, 0);
gen_set_disp(-1, &fb_info);
if (register_framebuffer(&fb_info) < 0) {
iounmap(fb_info.screen_base);
iounmap(display.screen_base);
release_mem_region(VGA_START, VGA_SIZE);
return -EINVAL;
}
......
/*
* Generic function for frame buffer with packed pixels of any depth.
*
* Copyright (C) June 1999 James Simmons
*
* 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.
*
* NOTES:
*
* This is for cfb packed pixels. Iplan and such are incorporated in the
* drivers that need them.
*
* FIXME
* The code for 24 bit is horrible. It copies byte by byte size instead of
* longs like the other sizes. Needs to be optimized.
*
* Also need to add code to deal with cards endians that are different than
* the native cpu endians. I also need to deal with MSB position in the word.
*
*/
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/fb.h>
#include <linux/slab.h>
#include <asm/types.h>
#include <asm/io.h>
#include <video/fbcon.h>
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 n, j, linesize = p->fix.line_length, bpl = sizeof(unsigned long);
unsigned long start_index, end_index, start_mask, end_mask, last;
unsigned long *dst = NULL, *src = NULL;
char *src1, *dst1;
int tmp, height;
/* clip the destination */
old_dx = area->dx;
old_dy = area->dy;
/*
* We could use hardware clipping but on many cards you get around
* hardware clipping by writing to framebuffer directly.
*/
x2 = area->dx + area->width;
y2 = area->dy + area->height;
area->dx = area->dx > 0 ? area->dx : 0;
area->dy = area->dy > 0 ? area->dy : 0;
x2 = x2 < p->var.xres_virtual ? x2 : p->var.xres_virtual;
y2 = y2 < p->var.yres_virtual ? y2 : p->var.yres_virtual;
area->width = x2 - area->dx;
area->height = y2 - area->dy;
/* update sx1,sy1 */
area->sx += (area->dx - old_dx);
area->sy += (area->dy - old_dy);
height = area->height;
/* the source must be completely inside the virtual screen */
if (area->sx < 0 || area->sy < 0 ||
(area->sx + area->width) > p->var.xres_virtual ||
(area->sy + area->height) > p->var.yres_virtual)
return;
if (area->dy < area->sy
|| (area->dy == area->sy && area->dx < area->sx)) {
/* start at the top */
src1 = p->screen_base + area->sy * linesize +
((area->sx * p->var.bits_per_pixel) >> 3);
dst1 = p->screen_base + area->dy * linesize +
((area->dx * p->var.bits_per_pixel) >> 3);
lineincr = linesize;
} else {
/* start at the bottom */
src1 = p->screen_base + (area->sy + area->height-1) * linesize
+ (((area->sx + area->width - 1) * p->var.bits_per_pixel) >> 3);
dst1 = p->screen_base + (area->dy + area->height-1) * linesize
+ (((area->dx + area->width - 1) * p->var.bits_per_pixel) >> 3);
lineincr = -linesize;
}
if ((BITS_PER_LONG % p->var.bits_per_pixel) == 0) {
int ppw = BITS_PER_LONG / p->var.bits_per_pixel;
int n = ((area->width * p->var.bits_per_pixel) >> 3);
start_index = ((unsigned long) src1 & (bpl - 1));
end_index = ((unsigned long) (src1 + n) & (bpl - 1));
shift = ((unsigned long) dst1 & (bpl - 1)) -
((unsigned long) src1 & (bpl - 1));
start_mask = end_mask = 0;
if (start_index) {
start_mask = -1 >> (start_index << 3);
n -= (bpl - start_index);
}
if (end_index) {
end_mask = -1 << ((bpl - end_index) << 3);
n -= end_index;
}
n = n / bpl;
if (n <= 0) {
if (start_mask) {
if (end_mask)
end_mask &= start_mask;
else
end_mask = start_mask;
start_mask = 0;
}
n = 0;
}
if (shift) {
if (shift > 0) {
/* dest is over to right more */
shift_right =
shift * p->var.bits_per_pixel;
shift_left =
(ppw - shift) * p->var.bits_per_pixel;
} else {
/* source is to the right more */
shift_right =
(ppw + shift) * p->var.bits_per_pixel;
shift_left =
-shift * p->var.bits_per_pixel;
}
/* general case, positive increment */
if (lineincr > 0) {
if (shift < 0)
n++;
do {
dst = (unsigned long *) dst1;
src = (unsigned long *) src1;
last = (fb_readl(src) & start_mask);
if (shift > 0)
fb_writel(fb_readl(dst) | (last >> shift_right), dst);
for (j = 0; j < n; j++) {
dst++;
tmp = fb_readl(src);
src++;
fb_writel((last << shift_left) | (tmp >> shift_right), dst);
last = tmp;
src++;
}
fb_writel(fb_readl(dst) | (last << shift_left), dst);
src1 += lineincr;
dst1 += lineincr;
} while (--height);
} else {
/* general case, negative increment */
if (shift > 0)
n++;
do {
dst = (unsigned long *) dst1;
src = (unsigned long *) src1;
last = (fb_readl(src) & end_mask);
if (shift < 0)
fb_writel(fb_readl(dst) | (last >> shift_right), dst);
for (j = 0; j < n; j++) {
dst--;
tmp = fb_readl(src);
src--;
fb_writel((tmp << shift_left) | (last >> shift_right), dst);
last = tmp;
src--;
}
fb_writel(fb_readl(dst) | (last >> shift_right), dst);
src1 += lineincr;
dst1 += lineincr;
} while (--height);
}
} else {
/* no shift needed */
if (lineincr > 0) {
/* positive increment */
do {
dst = (unsigned long *) (dst1 - start_index);
src = (unsigned long *) (src1 - start_index);
if (start_mask)
fb_writel(fb_readl(src) | start_mask, dst);
for (j = 0; j < n; j++) {
fb_writel(fb_readl(src), dst);
dst++;
src++;
}
if (end_mask)
fb_writel(fb_readl(src) | end_mask, dst);
src1 += lineincr;
dst1 += lineincr;
} while (--height);
} else {
/* negative increment */
do {
dst = (unsigned long *) dst1;
src = (unsigned long *) src1;
if (start_mask)
fb_writel(fb_readl(src) | start_mask, dst);
for (j = 0; j < n; j++) {
fb_writel(fb_readl(src), dst);
dst--;
src--;
}
src1 += lineincr;
dst1 += lineincr;
} while (--height);
}
}
}
}
/*
* Generic fillrect for frame buffers with packed pixels of any depth.
*
* Copyright (C) 2000 James Simmons (jsimmons@linux-fbdev.org)
*
* 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.
*
* NOTES:
*
* The code for depths like 24 that don't have integer number of pixels per
* long is broken and needs to be fixed. For now I turned these types of
* mode off.
*
* Also need to add code to deal with cards endians that are different than
* the native cpu endians. I also need to deal with MSB position in the word.
*
*/
#include <linux/string.h>
#include <linux/fb.h>
#include <asm/types.h>
#include <video/fbcon.h>
void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect)
{
unsigned long start_index, end_index, start_mask = 0, end_mask = 0;
unsigned long height, ppw, fg, fgcolor;
int i, n, x2, y2, linesize = p->fix.line_length;
int bpl = sizeof(unsigned long);
unsigned long *dst;
char *dst1;
if (!rect->width || !rect->height)
return;
/* We could use hardware clipping but on many cards you get around
* hardware clipping by writing to framebuffer directly. */
x2 = rect->dx + rect->width;
y2 = rect->dy + rect->height;
x2 = x2 < p->var.xres_virtual ? x2 : p->var.xres_virtual;
y2 = y2 < p->var.yres_virtual ? y2 : p->var.yres_virtual;
rect->width = x2 - rect->dx;
height = y2 - rect->dy;
/* Size of the scanline in bytes */
n = (rect->width * (p->var.bits_per_pixel >> 3));
ppw = BITS_PER_LONG / p->var.bits_per_pixel;
dst1 = p->screen_base + (rect->dy * linesize) +
(rect->dx * (p->var.bits_per_pixel >> 3));
start_index = ((unsigned long) dst1 & (bpl - 1));
end_index = ((unsigned long) (dst1 + n) & (bpl - 1));
if (p->fix.visual == FB_VISUAL_TRUECOLOR)
fg = fgcolor = ((u32 *) (p->pseudo_palette))[rect->color];
else
fg = fgcolor = rect->color;
for (i = 0; i < ppw - 1; i++) {
fg <<= p->var.bits_per_pixel;
fg |= fgcolor;
}
if (start_index) {
start_mask = fg << (start_index << 3);
n -= (bpl - start_index);
}
if (end_index) {
end_mask = fg >> ((bpl - end_index) << 3);
n -= end_index;
}
n = n / bpl;
if (n <= 0) {
if (start_mask) {
if (end_mask)
end_mask &= start_mask;
else
end_mask = start_mask;
start_mask = 0;
}
n = 0;
}
if ((BITS_PER_LONG % p->var.bits_per_pixel) == 0) {
switch (rect->rop) {
case ROP_COPY:
do {
/* Word align to increases performace :-) */
dst = (unsigned long *) (dst1 - start_index);
if (start_mask) {
#if BITS_PER_LONG == 32
fb_writel(fb_readl(dst) |
start_mask, dst);
#else
fb_writeq(fb_readq(dst) |
start_mask, dst);
#endif
dst++;
}
for (i = 0; i < n; i++) {
#if BITS_PER_LONG == 32
fb_writel(fg, dst);
#else
fb_writeq(fg, dst);
#endif
dst++;
}
if (end_mask)
#if BITS_PER_LONG == 32
fb_writel(fb_readl(dst) | end_mask,
dst);
#else
fb_writeq(fb_readq(dst) | end_mask,
dst);
#endif
dst1 += linesize;
} while (--height);
break;
case ROP_XOR:
do {
dst = (unsigned long *) (dst1 - start_index);
if (start_mask) {
#if BITS_PER_LONG == 32
fb_writel(fb_readl(dst) ^
start_mask, dst);
#else
fb_writeq(fb_readq(dst) ^
start_mask, dst);
#endif
dst++;
}
for (i = 0; i < n; i++) {
#if BITS_PER_LONG == 32
fb_writel(fb_readl(dst) ^ fg, dst);
#else
fb_writeq(fb_readq(dst) ^ fg, dst);
#endif
dst++;
}
if (end_mask) {
#if BITS_PER_LONG == 32
fb_writel(fb_readl(dst) ^ end_mask,
dst);
#else
fb_writeq(fb_readq(dst) ^ end_mask,
dst);
#endif
}
dst1 += linesize;
} while (--height);
break;
}
} else {
/* Odd modes like 24 or 80 bits per pixel */
start_mask = fg >> (start_index * p->var.bits_per_pixel);
end_mask = fg << (end_index * p->var.bits_per_pixel);
/* start_mask =& PFILL24(x1,fg);
end_mask_or = end_mask & PFILL24(x1+width-1,fg); */
n = (rect->width - start_index - end_index) / ppw;
switch (rect->rop) {
case ROP_COPY:
do {
dst = (unsigned long *) dst1;
if (start_mask)
*dst |= start_mask;
if ((start_index + rect->width) > ppw)
dst++;
/* XXX: slow */
for (i = 0; i < n; i++) {
*dst++ = fg;
}
if (end_mask)
*dst |= end_mask;
dst1 += linesize;
} while (--height);
break;
case ROP_XOR:
do {
dst = (unsigned long *) dst1;
if (start_mask)
*dst ^= start_mask;
if ((start_mask + rect->width) > ppw)
dst++;
for (i = 0; i < n; i++) {
*dst++ ^= fg; /* PFILL24(fg,x1+i); */
}
if (end_mask)
*dst ^= end_mask;
dst1 += linesize;
} while (--height);
break;
}
}
return;
}
/*
* Generic BitBLT function for frame buffer with packed pixels of any depth.
*
* Copyright (C) June 1999 James Simmons
*
* 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.
*
* NOTES:
*
* This function copys a image from system memory to video memory. The
* image can be a bitmap where each 0 represents the background color and
* each 1 represents the foreground color. Great for font handling. It can
* also be a color image. This is determined by image_depth. The color image
* must be laid out exactly in the same format as the framebuffer. Yes I know
* their are cards with hardware that coverts images of various depths to the
* framebuffer depth. But not every card has this. All images must be rounded
* up to the nearest byte. For example a bitmap 12 bits wide must be two
* bytes width.
*
* FIXME
* The code for 24 bit is horrible. It copies byte by byte size instead of
* longs like the other sizes. Needs to be optimized.
*
* Also need to add code to deal with cards endians that are different than
* the native cpu endians. I also need to deal with MSB position in the word.
*
*/
#include <linux/string.h>
#include <linux/fb.h>
#include <asm/types.h>
#include <video/fbcon.h>
#define DEBUG
#ifdef DEBUG
#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__FUNCTION__,## args)
#else
#define DPRINTK(fmt, args...)
#endif
void cfb_imageblit(struct fb_info *p, struct fb_image *image)
{
int pad, ppw, shift, shift_right, shift_left, x2, y2, n, i, j, k, l = 7;
unsigned long tmp = ~0 << (BITS_PER_LONG - p->var.bits_per_pixel);
unsigned long fgx, bgx, fgcolor, bgcolor, eorx;
unsigned long end_index, end_mask, mask;
unsigned long *dst = NULL;
u8 *dst1, *src;
/*
* We could use hardware clipping but on many cards you get around hardware
* clipping by writing to framebuffer directly like we are doing here.
*/
x2 = image->dx + image->width;
y2 = image->dy + image->height;
image->dx = image->dx > 0 ? image->dx : 0;
image->dy = image->dy > 0 ? image->dy : 0;
x2 = x2 < p->var.xres_virtual ? x2 : p->var.xres_virtual;
y2 = y2 < p->var.yres_virtual ? y2 : p->var.yres_virtual;
image->width = x2 - image->dx;
image->height = y2 - image->dy;
dst1 = p->screen_base + image->dy * p->fix.line_length +
((image->dx * p->var.bits_per_pixel) >> 3);
ppw = BITS_PER_LONG/p->var.bits_per_pixel;
src = image->data;
if (image->depth == 1) {
if (p->fix.visual == FB_VISUAL_TRUECOLOR) {
fgx = fgcolor = ((u32 *)(p->pseudo_palette))[image->fg_color];
bgx = bgcolor = ((u32 *)(p->pseudo_palette))[image->bg_color];
} else {
fgx = fgcolor = image->fg_color;
bgx = bgcolor = image->bg_color;
}
for (i = 0; i < ppw-1; i++) {
fgx <<= p->var.bits_per_pixel;
bgx <<= p->var.bits_per_pixel;
fgx |= fgcolor;
bgx |= bgcolor;
}
eorx = fgx ^ bgx;
n = ((image->width + 7) >> 3);
pad = (n << 3) - image->width;
for (i = 0; i < image->height; i++) {
dst = (unsigned long *) dst1;
for (j = image->width/ppw; j > 0; j--) {
mask = 0;
for (k = ppw; k > 0; k--) {
if (test_bit(l, src))
mask |= (tmp >> (p->var.bits_per_pixel*(k-1)));
l--;
if (l < 0) { l = 7; src++; }
}
fb_writel((mask & eorx)^bgx, dst);
dst++;
}
l =- pad;
dst1 += p->fix.line_length;
}
}
}
......@@ -74,10 +74,10 @@ struct fb_info_chips {
#define write_ind(num, val, ap, dp) do { \
outb((num), (ap)); outb((val), (dp)); \
} while (0);
} while (0)
#define read_ind(num, var, ap, dp) do { \
outb((num), (ap)); var = inb((dp)); \
} while (0);
} while (0)
/* extension registers */
#define write_xr(num, val) write_ind(num, val, 0x3d6, 0x3d7)
......
......@@ -211,6 +211,53 @@ clps7111fb_set_var(struct fb_var_screeninfo *var, int con,
return 0;
}
static int clps7111fb_blank(int blank, struct fb_info *info)
{
if (blank) {
if (machine_is_edb7211()) {
int i;
/* Turn off the LCD backlight. */
clps_writeb(clps_readb(PDDR) & ~EDB_PD3_LCDBL, PDDR);
/* Power off the LCD DC-DC converter. */
clps_writeb(clps_readb(PDDR) & ~EDB_PD1_LCD_DC_DC_EN, PDDR);
/* Delay for a little while (half a second). */
for (i=0; i<65536*4; i++);
/* Power off the LCD panel. */
clps_writeb(clps_readb(PDDR) & ~EDB_PD2_LCDEN, PDDR);
/* Power off the LCD controller. */
clps_writel(clps_readl(SYSCON1) & ~SYSCON1_LCDEN,
SYSCON1);
}
} else {
if (machine_is_edb7211()) {
int i;
/* Power up the LCD controller. */
clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN,
SYSCON1);
/* Power up the LCD panel. */
clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
/* Delay for a little while. */
udelay(100);
/* Power up the LCD DC-DC converter. */
clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN,
PDDR);
/* Turn on the LCD backlight. */
clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
}
}
return 0;
}
static struct fb_ops clps7111fb_ops = {
owner: THIS_MODULE,
fb_set_var: clps7111fb_set_var,
......@@ -266,53 +313,6 @@ static int clps7111fb_updatevar(int con, struct fb_info *info)
return -EINVAL;
}
static int clps7111fb_blank(int blank, struct fb_info *info)
{
if (blank) {
if (machine_is_edb7211()) {
int i;
/* Turn off the LCD backlight. */
clps_writeb(clps_readb(PDDR) & ~EDB_PD3_LCDBL, PDDR);
/* Power off the LCD DC-DC converter. */
clps_writeb(clps_readb(PDDR) & ~EDB_PD1_LCD_DC_DC_EN, PDDR);
/* Delay for a little while (half a second). */
for (i=0; i<65536*4; i++);
/* Power off the LCD panel. */
clps_writeb(clps_readb(PDDR) & ~EDB_PD2_LCDEN, PDDR);
/* Power off the LCD controller. */
clps_writel(clps_readl(SYSCON1) & ~SYSCON1_LCDEN,
SYSCON1);
}
} else {
if (machine_is_edb7211()) {
int i;
/* Power up the LCD controller. */
clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN,
SYSCON1);
/* Power up the LCD panel. */
clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
/* Delay for a little while. */
for (i=0; i<65536*4; i++);
/* Power up the LCD DC-DC converter. */
clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN,
PDDR);
/* Turn on the LCD backlight. */
clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
}
}
return 0;
}
static int
clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
......@@ -366,8 +366,9 @@ clps7111fb_proc_backlight_write(struct file *file, const char *buffer,
int __init clps711xfb_init(void)
{
int err = -ENOMEM;
int err;
err = -ENOMEM;
cfb = kmalloc(sizeof(*cfb) + sizeof(struct display), GFP_KERNEL);
if (!cfb)
goto out;
......@@ -430,7 +431,7 @@ int __init clps711xfb_init(void)
clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
/* Delay for a little while. */
for (i=0; i<65536*4; i++);
udelay(100);
/* Power up the LCD DC-DC converter. */
clps_writeb(clps_readb(PDDR) | EDB_PD1_LCD_DC_DC_EN, PDDR);
......@@ -463,3 +464,7 @@ static void __exit clps711xfb_exit(void)
module_init(clps711xfb_init);
#endif
module_exit(clps711xfb_exit);
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
MODULE_DESCRIPTION("CLPS711x framebuffer driver");
MODULE_LICENSE("GPL");
......@@ -1729,9 +1729,8 @@ static int cyberpro_pci_resume(struct pci_dev *dev)
}
static struct pci_device_id cyberpro_pci_table[] __devinitdata = {
// Not yet
// { 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_1682,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_IGA_1682 },
{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_CYBERPRO_2000 },
{ PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010,
......
......@@ -152,7 +152,7 @@ void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
size = to->len-tooff;
if (size > from->len-fromoff)
size = from->len-fromoff;
if (size < 0)
if (size <= 0)
return;
size *= sizeof(u16);
......
......@@ -61,6 +61,8 @@ extern int cyberfb_init(void);
extern int cyberfb_setup(char*);
extern int pm2fb_init(void);
extern int pm2fb_setup(char*);
extern int pm3fb_init(void);
extern int pm3fb_setup(char*);
extern int clps711xfb_init(void);
extern int cyber2000fb_init(void);
extern int cyber2000fb_setup(char*);
......@@ -120,10 +122,16 @@ extern int rivafb_init(void);
extern int rivafb_setup(char*);
extern int tdfxfb_init(void);
extern int tdfxfb_setup(char*);
extern int tridentfb_init(void);
extern int tridentfb_setup(char*);
extern int sisfb_init(void);
extern int sisfb_setup(char*);
extern int stifb_init(void);
extern int stifb_setup(char*);
extern int pmagbafb_init(void);
extern int pmagbbfb_init(void);
extern void maxinefb_init(void);
extern int tx3912fb_init(void);
extern int radeonfb_init(void);
extern int radeonfb_setup(char*);
extern int e1355fb_init(void);
......@@ -172,6 +180,9 @@ static struct {
#ifdef CONFIG_FB_PM2
{ "pm2fb", pm2fb_init, pm2fb_setup },
#endif
#ifdef CONFIG_FB_PM3
{ "pm3fb", pm3fb_init, pm3fb_setup },
#endif
#ifdef CONFIG_FB_CLGEN
{ "clgen", clgenfb_init, clgenfb_setup },
#endif
......@@ -220,6 +231,9 @@ static struct {
#ifdef CONFIG_FB_SIS
{ "sisfb", sisfb_init, sisfb_setup },
#endif
#ifdef CONFIG_FB_TRIDENT
{ "trident", tridentfb_init, tridentfb_setup },
#endif
/*
* Generic drivers that are used as fallbacks
......@@ -285,12 +299,24 @@ static struct {
#ifdef CONFIG_FB_HIT
{ "hitfb", hitfb_init, NULL },
#endif
#ifdef CONFIG_FB_TX3912
{ "tx3912", tx3912fb_init, NULL },
#endif
#ifdef CONFIG_FB_E1355
{ "e1355fb", e1355fb_init, e1355fb_setup },
#endif
#ifdef CONFIG_FB_PVR2
{ "pvr2", pvr2fb_init, pvr2fb_setup },
#endif
#ifdef CONFIG_FB_PMAG_BA
{ "pmagbafb", pmagbafb_init, NULL },
#endif
#ifdef CONFIG_FB_PMAGB_B
{ "pmagbbfb", pmagbbfb_init, NULL },
#endif
#ifdef CONFIG_FB_MAXINE
{ "maxinefb", maxinefb_init, NULL },
#endif
#ifdef CONFIG_FB_VOODOO1
{ "sst", sstfb_init, sstfb_setup },
#endif
......
......@@ -7,6 +7,7 @@
*
* Written for 2.0.x by Steffen A. Mork
* Ported to 2.1.x by Geert Uytterhoeven
* Ported to new api by James Simmons
*
* 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
......@@ -18,12 +19,9 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/zorro.h>
#include <asm/io.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb32.h>
/*
* Some technical notes:
......@@ -117,7 +115,6 @@
*
*/
/*
* definitions
*/
......@@ -130,29 +127,22 @@
#define FRAMEMASTER_COMPL 4
#define FRAMEMASTER_ROM 8
struct FrameMaster_fb_par
{
int xres;
int yres;
int bpp;
int pixclock;
};
static unsigned long fm2fb_mem_phys;
static void *fm2fb_mem;
static unsigned long fm2fb_reg_phys;
static volatile unsigned char *fm2fb_reg;
static struct display disp;
static struct fb_info fb_info;
static struct { u_char red, green, blue, pad; } palette[16];
#ifdef FBCON_HAS_CFB32
static u32 fbcon_cfb32_cmap[16];
#endif
#define arraysize(x) (sizeof(x)/sizeof(*(x)))
static struct fb_fix_screeninfo fb_fix;
static struct fb_var_screeninfo fb_var;
static struct fb_info fb_info;
static u32 pseudo_palette[17];
static struct display display;
static struct fb_fix_screeninfo fb_fix __initdata = {
smem_len: FRAMEMASTER_REG,
type: FB_TYPE_PACKED_PIXELS,
visual: FB_VISUAL_TRUECOLOR,
line_length: (768 << 2),
mmio_len: (8),
accel: FB_ACCEL_NONE,
};
static int fm2fb_mode __initdata = -1;
......@@ -174,125 +164,58 @@ static struct fb_var_screeninfo fb_var_modes[] __initdata = {
33333, 10, 102, 10, 5, 80, 34, FB_SYNC_COMP_HIGH_ACT, 0
}
};
/*
* Interface used by the world
*/
int fm2fb_init(void);
static int fm2fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
static int fm2fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int fm2fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int fm2fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info);
static int fm2fb_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 fm2fb_blank(int blank, struct fb_info *info);
/*
* Interface to the low level console driver
*/
int fm2fb_init(void);
static int fm2fbcon_switch(int con, struct fb_info *info);
static int fm2fbcon_updatevar(int con, struct fb_info *info);
/*
* Internal routines
*/
static int fm2fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info);
static struct fb_ops fm2fb_ops = {
owner: THIS_MODULE,
fb_get_fix: fm2fb_get_fix,
fb_get_var: fm2fb_get_var,
fb_set_var: fm2fb_set_var,
fb_get_cmap: fm2fb_get_cmap,
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_setcolreg: fm2fb_setcolreg,
fb_blank: fm2fb_blank,
fb_blank: fm2fb_blank,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
};
/*
* Get the Fixed Part of the Display
* Blank the display.
*/
static int fm2fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
static int fm2fb_blank(int blank, struct fb_info *info)
{
memcpy(fix, &fb_fix, sizeof(fb_fix));
return 0;
}
/*
* Get the User Defined Part of the Display
*/
unsigned char t = FRAMEMASTER_ROM;
static int fm2fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
memcpy(var, &fb_var, sizeof(fb_var));
return 0;
if (!blank)
t |= FRAMEMASTER_ENABLE | FRAMEMASTER_NOLACE;
fm2fb_reg[0] = t;
}
/*
* Set the User Defined Part of the Display
* Set a single color register. The values supplied are already
* rounded down to the hardware's capabilities (according to the
* entries in the var structure). Return != 0 for invalid regno.
*/
static int fm2fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
struct display *display;
int oldbpp = -1, err;
if (con >= 0)
display = &fb_display[con];
else
display = &disp; /* used during initialization */
if (var->xres > fb_var.xres || var->yres > fb_var.yres ||
var->xres_virtual > fb_var.xres_virtual ||
var->yres_virtual > fb_var.yres_virtual ||
var->bits_per_pixel > fb_var.bits_per_pixel ||
var->nonstd ||
(var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
return -EINVAL;
memcpy(var, &fb_var, sizeof(fb_var));
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
oldbpp = display->var.bits_per_pixel;
display->var = *var;
}
if (oldbpp != var->bits_per_pixel) {
if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
return err;
do_install_cmap(con, info);
}
return 0;
}
/*
* Get the Colormap
*/
if (regno > 15)
return 1;
red >>= 8;
green >>= 8;
blue >>= 8;
static int fm2fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
if (con == info->currcon) /* current console? */
return fb_get_cmap(cmap, kspc, fm2fb_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
fb_copy_cmap(fb_default_cmap(256), cmap, kspc ? 0 : 2);
return 0;
((u32*)(info->pseudo_palette))[regno] = (red << 16) | (green << 8) | blue;
return 0;
}
/*
......@@ -301,194 +224,89 @@ static int fm2fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
int __init fm2fb_init(void)
{
int is_fm;
struct zorro_dev *z = NULL;
unsigned long *ptr;
int x, y;
while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
if (z->id == ZORRO_PROD_BSC_FRAMEMASTER_II)
is_fm = 1;
else if (z->id == ZORRO_PROD_HELFRICH_RAINBOW_II)
is_fm = 0;
else
continue;
if (!request_mem_region(z->resource.start, FRAMEMASTER_SIZE, "fm2fb"))
continue;
/* assigning memory to kernel space */
fm2fb_mem_phys = z->resource.start;
fm2fb_mem = ioremap(fm2fb_mem_phys, FRAMEMASTER_SIZE);
fm2fb_reg_phys = fm2fb_mem_phys+FRAMEMASTER_REG;
fm2fb_reg = (unsigned char *)(fm2fb_mem+FRAMEMASTER_REG);
/* make EBU color bars on display */
ptr = (unsigned long *)fm2fb_mem;
for (y = 0; y < 576; y++) {
for (x = 0; x < 96; x++) *ptr++ = 0xffffff; /* white */
for (x = 0; x < 96; x++) *ptr++ = 0xffff00; /* yellow */
for (x = 0; x < 96; x++) *ptr++ = 0x00ffff; /* cyan */
for (x = 0; x < 96; x++) *ptr++ = 0x00ff00; /* green */
for (x = 0; x < 96; x++) *ptr++ = 0xff00ff; /* magenta */
for (x = 0; x < 96; x++) *ptr++ = 0xff0000; /* red */
for (x = 0; x < 96; x++) *ptr++ = 0x0000ff; /* blue */
for (x = 0; x < 96; x++) *ptr++ = 0x000000; /* black */
struct zorro_dev *z = NULL;
unsigned long *ptr;
int is_fm;
int x, y;
while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
if (z->id == ZORRO_PROD_BSC_FRAMEMASTER_II)
is_fm = 1;
else if (z->id == ZORRO_PROD_HELFRICH_RAINBOW_II)
is_fm = 0;
else
continue;
if (!request_mem_region(z->resource.start, FRAMEMASTER_SIZE, "fm2fb"))
continue;
/* assigning memory to kernel space */
fb_fix.smem_start = z->resource.start;
fb_info.screen_base = ioremap(fb_fix.smem_start, FRAMEMASTER_SIZE);
fb_fix.mmio_start = fb_fix.smem_start + FRAMEMASTER_REG;
fm2fb_reg = (unsigned char *)(fb_info.screen_base+FRAMEMASTER_REG);
strcpy(fb_fix.id, is_fm ? "FrameMaster II" : "Rainbow II");
/* make EBU color bars on display */
ptr = (unsigned long *)fb_fix.smem_start;
for (y = 0; y < 576; y++) {
for (x = 0; x < 96; x++) *ptr++ = 0xffffff;/* white */
for (x = 0; x < 96; x++) *ptr++ = 0xffff00;/* yellow */
for (x = 0; x < 96; x++) *ptr++ = 0x00ffff;/* cyan */
for (x = 0; x < 96; x++) *ptr++ = 0x00ff00;/* green */
for (x = 0; x < 96; x++) *ptr++ = 0xff00ff;/* magenta */
for (x = 0; x < 96; x++) *ptr++ = 0xff0000;/* red */
for (x = 0; x < 96; x++) *ptr++ = 0x0000ff;/* blue */
for (x = 0; x < 96; x++) *ptr++ = 0x000000;/* black */
}
fm2fb_blank(0, NULL);
if (fm2fb_mode == -1)
fm2fb_mode = FM2FB_MODE_PAL;
strcpy(fb_info.modename, fb_fix.id);
fb_info.node = NODEV;
fb_info.fbops = &fm2fb_ops;
fb_info.var = fb_var_modes[fm2fb_mode];
fb_info.screen_base = (char *)fb_fix.smem_start;
fb_info.pseudo_palette = pseudo_palette;
fb_info.fix = fb_fix;
fb_info.flags = FBINFO_FLAG_DEFAULT;
/* The below feilds will go away !!!! */
fb_info.currcon = -1;
strcpy(fb_info.modename, fb_info.fix.id);
fb_info.disp = &display;
fb_info.switch_con = gen_switch;
fb_info.updatevar = gen_update_var;
fb_alloc_cmap(&fb_info.cmap, 16, 0);
gen_set_disp(-1, &fb_info);
if (register_framebuffer(&fb_info) < 0)
return -EINVAL;
printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node), fb_fix.id);
return 0;
}
fm2fb_blank(0, NULL);
if (fm2fb_mode == -1)
fm2fb_mode = FM2FB_MODE_PAL;
fb_var = fb_var_modes[fm2fb_mode];
strcpy(fb_fix.id, is_fm ? "FrameMaster II" : "Rainbow II");
fb_fix.smem_start = fm2fb_mem_phys;
fb_fix.smem_len = FRAMEMASTER_REG;
fb_fix.type = FB_TYPE_PACKED_PIXELS;
fb_fix.type_aux = 0;
fb_fix.visual = FB_VISUAL_TRUECOLOR;
fb_fix.line_length = 768<<2;
fb_fix.mmio_start = fm2fb_reg_phys;
fb_fix.mmio_len = 8;
fb_fix.accel = FB_ACCEL_NONE;
disp.var = fb_var;
disp.cmap.start = 0;
disp.cmap.len = 0;
disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL;
disp.visual = fb_fix.visual;
disp.type = fb_fix.type;
disp.type_aux = fb_fix.type_aux;
disp.ypanstep = 0;
disp.ywrapstep = 0;
disp.line_length = fb_fix.line_length;
disp.can_soft_blank = 1;
disp.inverse = 0;
#ifdef FBCON_HAS_CFB32
disp.dispsw = &fbcon_cfb32;
disp.dispsw_data = &fbcon_cfb32_cmap;
#else
disp.dispsw = &fbcon_dummy;
#endif
disp.scrollmode = SCROLL_YREDRAW;
strcpy(fb_info.modename, fb_fix.id);
fb_info.node = NODEV;
fb_info.fbops = &fm2fb_ops;
fb_info.screen_base = (char *)fm2fb_mem;
fb_info.currcon = -1;
fb_info.disp = &disp;
fb_info.fontname[0] = '\0';
fb_info.changevar = NULL;
fb_info.switch_con = &fm2fbcon_switch;
fb_info.updatevar = &fm2fbcon_updatevar;
fb_info.flags = FBINFO_FLAG_DEFAULT;
fm2fb_set_var(&fb_var, -1, &fb_info);
if (register_framebuffer(&fb_info) < 0)
return -EINVAL;
printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node),
fb_fix.id);
return 0;
}
return -ENXIO;
return -ENXIO;
}
int __init fm2fb_setup(char *options)
{
char *this_opt;
if (!options || !*options)
return 0;
char *this_opt;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!strncmp(this_opt, "pal", 3))
fm2fb_mode = FM2FB_MODE_PAL;
else if (!strncmp(this_opt, "ntsc", 4))
fm2fb_mode = FM2FB_MODE_NTSC;
}
return 0;
}
static int fm2fbcon_switch(int con, struct fb_info *info)
{
/* Do we have to save the colormap? */
if (fb_display[info->currcon].cmap.len)
fb_get_cmap(&fb_display[info->currcon].cmap, 1, fm2fb_getcolreg, info);
info->currcon = con;
/* Install new colormap */
do_install_cmap(con, info);
return 0;
}
if (!options || !*options)
return 0;
/*
* Update the `var' structure (called by fbcon.c)
*/
static int fm2fbcon_updatevar(int con, struct fb_info *info)
{
/* Nothing */
return 0;
}
/*
* Blank the display.
*/
static int fm2fb_blank(int blank, struct fb_info *info)
{
unsigned char t = FRAMEMASTER_ROM;
if (!blank)
t |= FRAMEMASTER_ENABLE | FRAMEMASTER_NOLACE;
fm2fb_reg[0] = t;
return 0;
}
/*
* Read a single color register and split it into
* colors/transparent. Return != 0 for invalid regno.
*/
static int fm2fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info)
{
if (regno > 15)
return 1;
*red = (palette[regno].red<<8) | palette[regno].red;
*green = (palette[regno].green<<8) | palette[regno].green;
*blue = (palette[regno].blue<<8) | palette[regno].blue;
*transp = 0;
return 0;
}
/*
* Set a single color register. The values supplied are already
* rounded down to the hardware's capabilities (according to the
* entries in the var structure). Return != 0 for invalid regno.
*/
static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
if (regno > 15)
return 1;
red >>= 8;
green >>= 8;
blue >>= 8;
palette[regno].red = red;
palette[regno].green = green;
palette[regno].blue = blue;
#ifdef FBCON_HAS_CFB32
fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue;
#endif
return 0;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!strncmp(this_opt, "pal", 3))
fm2fb_mode = FM2FB_MODE_PAL;
else if (!strncmp(this_opt, "ntsc", 4))
fm2fb_mode = FM2FB_MODE_NTSC;
}
return 0;
}
MODULE_LICENSE("GPL");
......@@ -28,22 +28,19 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/selection.h>
#include <linux/console.h>
#include <asm/io.h>
#include <asm/jazz.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
/*
* Various defines for the G364
*/
#define G364_MEM_BASE 0xe4400000
#define G364_PORT_BASE 0xe4000000
#define ID_REG 0xe4000000 /* Read only */
#define ID_REG 0xe4000000 /* Read only */
#define BOOT_REG 0xe4080000
#define TIMING_REG 0xe4080108 /* to 0x080170 - DON'T TOUCH! */
#define TIMING_REG 0xe4080108 /* to 0x080170 - DON'T TOUCH! */
#define DISPLAY_REG 0xe4080118
#define VDISPLAY_REG 0xe4080150
#define MASK_REG 0xe4080200
......@@ -67,155 +64,90 @@
#define OP_MODE 0x000008
#define INTL_STAND 0x000004
#define SCRN_FORM 0x000002
#define ENABLE_VTG 0x000001
#define ENABLE_VTG 0x000001
#define TOP_REG 0xe4080400
#define CURS_PAL_REG 0xe4080508 /* to 0x080518 */
#define CHKSUM_REG 0xe4080600 /* to 0x080610 - unused */
#define CURS_PAL_REG 0xe4080508 /* to 0x080518 */
#define CHKSUM_REG 0xe4080600 /* to 0x080610 - unused */
#define CURS_POS_REG 0xe4080638
#define CLR_PAL_REG 0xe4080800 /* to 0x080ff8 */
#define CURS_PAT_REG 0xe4081000 /* to 0x081ff8 */
#define MON_ID_REG 0xe4100000 /* unused */
#define RESET_REG 0xe4180000 /* Write only */
#define MON_ID_REG 0xe4100000 /* unused */
#define RESET_REG 0xe4180000 /* Write only */
static struct display disp;
static struct fb_info fb_info;
static struct { u_char red, green, blue, pad; } palette[256];
static struct fb_fix_screeninfo fb_fix = { { "G364 8plane", } };
static struct fb_var_screeninfo fb_var = { 0, };
static struct fb_fix_screeninfo fb_fix __initdata = {
id: "G364 8plane",
smem_start: 0x40000000, /* physical address */
type: FB_TYPE_PACKED_PIXELS,
visual: FB_VISUAL_PSEUDOCOLOR,
ypanstep: 1,
accel: FB_ACCEL_NONE,
};
static struct fb_var_screeninfo fb_var __initdata = {
bits_per_pixel: 8,
red: { 0, 8, 0 },
green: { 0, 8, 0 },
blue: { 0, 8, 0 },
activate: FB_ACTIVATE_NOW,
height: -1,
width: -1,
pixclock: 39722,
left_margin: 40,
right_margin: 24,
upper_margin: 32,
lower_margin: 11,
hsync_len: 96,
vsync_len: 2,
vmode: FB_VMODE_NONINTERLACED,
};
/*
* Interface used by the world
*/
static int g364fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
static int g364fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int g364fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
int g364fb_init(void);
static int g364fb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int g364fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info);
static int g364fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int g364fb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp,
struct fb_info *info);
static int g364fb_blank(int blank, struct fb_info *info);
/*
* Interface to the low level console driver
*/
int g364fb_init(void);
static int g364fbcon_switch(int con, struct fb_info *info);
static int g364fbcon_updatevar(int con, struct fb_info *info);
/*
* Internal routines
*/
static int g364fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info);
static struct fb_ops g364fb_ops = {
owner: THIS_MODULE,
fb_get_fix: g364fb_get_fix,
fb_get_var: g364fb_get_var,
fb_set_var: g364fb_set_var,
fb_get_cmap: g364fb_get_cmap,
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_setcolreg: g364fb_setcolreg,
fb_pan_display: g364fb_pan_display,
fb_blank: g364fb_blank,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
};
void fbcon_g364fb_cursor(struct display *p, int mode, int x, int y)
{
switch (mode) {
case CM_ERASE:
*(unsigned int *) CTLA_REG |= CURS_TOGGLE;
break;
case CM_MOVE:
case CM_DRAW:
*(unsigned int *) CTLA_REG &= ~CURS_TOGGLE;
*(unsigned int *) CURS_POS_REG = ((x * fontwidth(p)) << 12) | ((y * fontheight(p))-p->var.yoffset);
break;
}
switch (mode) {
case CM_ERASE:
*(unsigned int *) CTLA_REG |= CURS_TOGGLE;
break;
case CM_MOVE:
case CM_DRAW:
*(unsigned int *) CTLA_REG &= ~CURS_TOGGLE;
*(unsigned int *) CURS_POS_REG =
((x * fontwidth(p)) << 12) | ((y * fontheight(p)) -
p->var.yoffset);
break;
}
}
static struct display_switch fbcon_g364cfb8 = {
setup: fbcon_cfb8_setup,
bmove: fbcon_cfb8_bmove,
clear: fbcon_cfb8_clear,
putc: fbcon_cfb8_putc,
putcs: fbcon_cfb8_putcs,
revc: fbcon_cfb8_revc,
cursor: fbcon_g364fb_cursor,
clear_margins: fbcon_cfb8_clear_margins,
fontwidthmask: FONTWIDTH(8)
};
/*
* Get the Fixed Part of the Display
*/
static int g364fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
{
memcpy(fix, &fb_fix, sizeof(fb_fix));
return 0;
}
/*
* Get the User Defined Part of the Display
*/
static int g364fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
memcpy(var, &fb_var, sizeof(fb_var));
return 0;
}
/*
* Set the User Defined Part of the Display
*/
static int g364fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
struct display *display;
int oldbpp = -1, err;
if (con >= 0)
display = &fb_display[con];
else
display = &disp; /* used during initialization */
if (var->xres > fb_var.xres || var->yres > fb_var.yres ||
var->xres_virtual > fb_var.xres_virtual ||
var->yres_virtual > fb_var.yres_virtual ||
var->bits_per_pixel > fb_var.bits_per_pixel ||
var->nonstd ||
(var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
return -EINVAL;
memcpy(var, &fb_var, sizeof(fb_var));
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
oldbpp = display->var.bits_per_pixel;
display->var = *var;
*(unsigned int *)TOP_REG = var->yoffset * var->xres;
}
if (oldbpp != var->bits_per_pixel) {
if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
return err;
do_install_cmap(con, info);
}
return 0;
}
/*
* Pan or Wrap the Display
*
......@@ -224,232 +156,115 @@ static int g364fb_set_var(struct fb_var_screeninfo *var, int con,
static int g364fb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
if (var->xoffset || var->yoffset+var->yres > var->yres_virtual)
return -EINVAL;
*(unsigned int *)TOP_REG = var->yoffset * var->xres;
return 0;
}
if (var->xoffset || var->yoffset + var->yres > var->yres_virtual)
return -EINVAL;
/*
* Get the Colormap
*/
static int g364fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
if (con == info->currcon) /* current console? */
return fb_get_cmap(cmap, kspc, g364fb_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
cmap, kspc ? 0 : 2);
return 0;
*(unsigned int *) TOP_REG = var->yoffset * var->xres;
return 0;
}
/*
* Initialisation
* Blank the display.
*/
int __init g364fb_init(void)
{
int i,j;
volatile unsigned int *pal_ptr = (volatile unsigned int *) CLR_PAL_REG;
volatile unsigned int *curs_pal_ptr = (volatile unsigned int *) CURS_PAL_REG;
unsigned int xres, yres;
int mem;
/* TBD: G364 detection */
/* get the resolution set by ARC console */
*(volatile unsigned int *)CTLA_REG &= ~ENABLE_VTG;
xres = (*((volatile unsigned int*)DISPLAY_REG) & 0x00ffffff) * 4;
yres = (*((volatile unsigned int*)VDISPLAY_REG) & 0x00ffffff) / 2;
*(volatile unsigned int *)CTLA_REG |= ENABLE_VTG;
/* initialise color palette */
for (i = 0; i < 16; i++) {
j = color_table[i];
palette[i].red=default_red[j];
palette[i].green=default_grn[j];
palette[i].blue=default_blu[j];
pal_ptr[i << 1] = (palette[i].red << 16) | (palette[i].green << 8) | palette[i].blue;
}
/* setup cursor */
curs_pal_ptr[0] |= 0x00ffffff;
curs_pal_ptr[2] |= 0x00ffffff;
curs_pal_ptr[4] |= 0x00ffffff;
/*
* first set the whole cursor to transparent
*/
for (i = 0; i < 512; i++)
*(unsigned short *)(CURS_PAT_REG+i*8) = 0;
/*
* switch the last two lines to cursor palette 3
* we assume here, that FONTSIZE_X is 8
*/
*(unsigned short *)(CURS_PAT_REG + 14*64) = 0xffff;
*(unsigned short *)(CURS_PAT_REG + 15*64) = 0xffff;
fb_var.bits_per_pixel = 8;
fb_var.xres = fb_var.xres_virtual = xres;
fb_var.yres = yres;
fb_fix.line_length = (xres / 8) * fb_var.bits_per_pixel;
fb_fix.smem_start = 0x40000000; /* physical address */
/* get size of video memory; this is special for the JAZZ hardware */
mem = (r4030_read_reg32(JAZZ_R4030_CONFIG) >> 8) & 3;
fb_fix.smem_len = (1 << (mem*2)) * 512 * 1024;
fb_fix.type = FB_TYPE_PACKED_PIXELS;
fb_fix.type_aux = 0;
fb_fix.visual = FB_VISUAL_PSEUDOCOLOR;
fb_fix.xpanstep = 0;
fb_fix.ypanstep = 1;
fb_fix.ywrapstep = 0;
fb_fix.mmio_start = 0;
fb_fix.mmio_len = 0;
fb_fix.accel = FB_ACCEL_NONE;
fb_var.yres_virtual = fb_fix.smem_len / xres;
fb_var.xoffset = fb_var.yoffset = 0;
fb_var.grayscale = 0;
fb_var.red.offset = 0;
fb_var.green.offset = 0;
fb_var.blue.offset = 0;
fb_var.red.length = fb_var.green.length = fb_var.blue.length = 8;
fb_var.red.msb_right = fb_var.green.msb_right = fb_var.blue.msb_right = 0;
fb_var.transp.offset = fb_var.transp.length = fb_var.transp.msb_right = 0;
fb_var.nonstd = 0;
fb_var.activate = 0;
fb_var.height = fb_var.width = -1;
fb_var.accel_flags = 0;
fb_var.pixclock = 39722;
fb_var.left_margin = 40;
fb_var.right_margin = 24;
fb_var.upper_margin = 32;
fb_var.lower_margin = 11;
fb_var.hsync_len = 96;
fb_var.vsync_len = 2;
fb_var.sync = 0;
fb_var.vmode = FB_VMODE_NONINTERLACED;
disp.var = fb_var;
disp.cmap.start = 0;
disp.cmap.len = 0;
disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL;
disp.visual = fb_fix.visual;
disp.type = fb_fix.type;
disp.type_aux = fb_fix.type_aux;
disp.ypanstep = fb_fix.ypanstep;
disp.ywrapstep = fb_fix.ywrapstep;
disp.line_length = fb_fix.line_length;
disp.can_soft_blank = 1;
disp.inverse = 0;
disp.dispsw = &fbcon_g364cfb8;
strcpy(fb_info.modename, fb_fix.id);
fb_info.node = NODEV;
fb_info.fbops = &g364fb_ops;
fb_info.screen_base = (char *)G364_MEM_BASE; /* virtual kernel address */
fb_info.disp = &disp;
fb_info.currcon = -1;
fb_info.fontname[0] = '\0';
fb_info.changevar = NULL;
fb_info.switch_con = &g364fbcon_switch;
fb_info.updatevar = &g364fbcon_updatevar;
fb_info.flags = FBINFO_FLAG_DEFAULT;
g364fb_set_var(&fb_var, -1, &fb_info);
if (register_framebuffer(&fb_info) < 0)
return -EINVAL;
printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node),
fb_fix.id);
return 0;
}
static int g364fbcon_switch(int con, struct fb_info *info)
static int g364fb_blank(int blank, struct fb_info *info)
{
/* Do we have to save the colormap? */
if (fb_display[info->currcon].cmap.len)
fb_get_cmap(&fb_display[info->currcon].cmap, 1, g364fb_getcolreg, info);
info->currcon = con;
/* Install new colormap */
do_install_cmap(con, info);
g364fbcon_updatevar(con, info);
return 0;
if (blank)
*(unsigned int *) CTLA_REG |= FORCE_BLANK;
else
*(unsigned int *) CTLA_REG &= ~FORCE_BLANK;
return 0;
}
/*
* Update the `var' structure (called by fbcon.c)
* Set a single color register. Return != 0 for invalid regno.
*/
static int g364fbcon_updatevar(int con, struct fb_info *info)
static int g364fb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp, struct fb_info *info)
{
if (con == info->currcon) {
struct fb_var_screeninfo *var = &fb_display[info->currcon].var;
volatile unsigned int *ptr = (volatile unsigned int *) CLR_PAL_REG;
/* hardware scrolling */
*(unsigned int *)TOP_REG = var->yoffset * var->xres;
}
return 0;
}
if (regno > 255)
return 1;
/*
* Blank the display.
*/
static int g364fb_blank(int blank, struct fb_info *info)
{
if (blank)
*(unsigned int *) CTLA_REG |= FORCE_BLANK;
else
*(unsigned int *) CTLA_REG &= ~FORCE_BLANK;
return 0;
}
red >>= 8;
green >>= 8;
blue >>= 8;
/*
* Read a single color register and split it into
* colors/transparent. Return != 0 for invalid regno.
*/
static int g364fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info)
{
if (regno > 255)
return 1;
*red = (palette[regno].red << 8) | palette[regno].red;
*green = (palette[regno].green << 8) | palette[regno].green;
*blue = (palette[regno].blue << 8) | palette[regno].blue;
*transp = 0;
return 0;
ptr[regno << 1] = (red << 16) | (green << 8) | blue;
return 0;
}
/*
* Set a single color register. Return != 0 for invalid regno.
* Initialisation
*/
static int g364fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
int __init g364fb_init(void)
{
volatile unsigned int *ptr = (volatile unsigned int *) CLR_PAL_REG;
if (regno > 255)
return 1;
red >>= 8;
green >>= 8;
blue >>=8;
palette[regno].red = red;
palette[regno].green = green;
palette[regno].blue = blue;
ptr[regno << 1] = (red << 16) | (green << 8) | blue;
return 0;
volatile unsigned int *pal_ptr =
(volatile unsigned int *) CLR_PAL_REG;
volatile unsigned int *curs_pal_ptr =
(volatile unsigned int *) CURS_PAL_REG;
int mem, i, j;
/* TBD: G364 detection */
/* get the resolution set by ARC console */
*(volatile unsigned int *) CTLA_REG &= ~ENABLE_VTG;
fb_var.xres =
(*((volatile unsigned int *) DISPLAY_REG) & 0x00ffffff) * 4;
fb_var.yres =
(*((volatile unsigned int *) VDISPLAY_REG) & 0x00ffffff) / 2;
*(volatile unsigned int *) CTLA_REG |= ENABLE_VTG;
/* setup cursor */
curs_pal_ptr[0] |= 0x00ffffff;
curs_pal_ptr[2] |= 0x00ffffff;
curs_pal_ptr[4] |= 0x00ffffff;
/*
* first set the whole cursor to transparent
*/
for (i = 0; i < 512; i++)
*(unsigned short *) (CURS_PAT_REG + i * 8) = 0;
/*
* switch the last two lines to cursor palette 3
* we assume here, that FONTSIZE_X is 8
*/
*(unsigned short *) (CURS_PAT_REG + 14 * 64) = 0xffff;
*(unsigned short *) (CURS_PAT_REG + 15 * 64) = 0xffff;
fb_var.xres_virtual = fbvar.xres;
fb_fix.line_length = (xres / 8) * fb_var.bits_per_pixel;
fb_fix.smem_start = 0x40000000; /* physical address */
/* get size of video memory; this is special for the JAZZ hardware */
mem = (r4030_read_reg32(JAZZ_R4030_CONFIG) >> 8) & 3;
fb_fix.smem_len = (1 << (mem * 2)) * 512 * 1024;
fb_var.yres_virtual = fb_fix.smem_len / fb_var.xres;
strcpy(fb_info.modename, fb_fix.id);
fb_info.node = NODEV;
fb_info.fbops = &g364fb_ops;
fb_info.screen_base = (char *) G364_MEM_BASE; /* virtual kernel address */
fb_info.var = fb_var;
fb_info.fix = fb_fix;
fb_info.flags = FBINFO_FLAG_DEFAULT;
fb_info.disp = &disp;
fb_info.currcon = -1;
fb_info.fontname[0] = '\0';
fb_info.changevar = NULL;
fb_info.switch_con = gen_switch;
fb_info.updatevar = gen_update_var;
fb_alloc_cmap(&fb_info.cmap, 255, 0);
gen_set_disp(-1, &fb_info);
if (register_framebuffer(&fb_info) < 0)
return -EINVAL;
printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node),
fb_info.fix.id);
return 0;
}
MODULE_LICENSE("GPL");
......@@ -386,44 +386,6 @@ static int __init hga_card_detect(void)
*
* ------------------------------------------------------------------------- */
/**
* hga_get_fix - get the fixed part of the display
* @fix:struct fb_fix_screeninfo to fill in
* @con:unused
* @info:pointer to fb_info object containing info for current hga board
*
* This wrapper function copies @info->fix to @fix.
* A zero is returned on success and %-EINVAL for failure.
*/
int hga_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
{
CHKINFO(-EINVAL);
DPRINTK("hga_get_fix: con:%d, info:%x, fb_info:%x\n", con, (unsigned)info, (unsigned)&fb_info);
*fix = info->fix;
return 0;
}
/**
* hga_get_var - get the user defined part of the display
* @var:struct fb_var_screeninfo to fill in
* @con:unused
* @info:pointer to fb_info object containing info for current hga board
*
* This wrapper function copies @info->var to @var.
* A zero is returned on success and %-EINVAL for failure.
*/
int hga_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
CHKINFO(-EINVAL);
DPRINTK("hga_get_var: con:%d, info:%x, fb_info:%x\n", con, (unsigned)info, (unsigned)&fb_info);
*var = info->var;
return 0;
}
/**
* hga_set_var - set the user defined part of the display
* @var:new video mode
......@@ -596,8 +558,8 @@ static int hgafb_blank(int blank_mode, struct fb_info *info)
static struct fb_ops hgafb_ops = {
owner: THIS_MODULE,
fb_get_fix: hga_get_fix,
fb_get_var: hga_get_var,
fb_get_fix: gen_get_fix,
fb_get_var: gen_get_var,
fb_set_var: hga_set_var,
fb_get_cmap: hga_get_cmap,
fb_set_cmap: gen_set_cmap,
......
......@@ -21,6 +21,7 @@
#include <linux/delay.h>
#include <linux/nubus.h>
#include <linux/init.h>
#include <linux/fb.h>
#include <asm/machvec.h>
#include <asm/uaccess.h>
......@@ -28,347 +29,165 @@
#include <asm/io.h>
#include <asm/hd64461.h>
#include <linux/fb.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
struct hitfb_par
{
int x, y;
int bpp;
static struct fb_var_screeninfo hitfb_var __initdata = {
activate: FB_ACTIVATE_NOW,
height: -1,
width: -1,
vmode: FB_VMODE_NONINTERLACED,
};
struct hitfb_info {
struct fb_info_gen gen;
struct display disp;
struct hitfb_par current_par;
struct fb_var_screeninfo default_var;
int current_par_valid;
unsigned long hit_videobase, hit_videosize;
union {
#ifdef FBCON_HAS_CFB16
u16 cfb16[16];
#endif
} fbcon_cmap;
} fb_info = {
{},
{},
{},
{},
0, 0, 0,
{},
static struct fb_fix_screeninfo hitfb_fix __initdata = {
id: "Hitachi HD64461",
type: FB_TYPE_PACKED_PIXELS,
visual: FB_VISUAL_TRUECOLOR,
accel_flags: FB_ACCEL_NONE,
};
static void hitfb_set_par(const void *fb_par, struct fb_info_gen *info);
static int hitfb_encode_var(struct fb_var_screeninfo *var, const void *fb_par,
struct fb_info_gen *info);
static void hitfb_detect(void)
{
struct hitfb_par par;
unsigned short lcdclor, ldr3, ldvntr;
fb_info.hit_videobase = CONFIG_HD64461_IOBASE + 0x02000000;
fb_info.hit_videosize = (MACH_HP680 || MACH_HP690) ? 1024*1024 : 512*1024;
lcdclor = inw(HD64461_LCDCLOR);
ldvntr = inw(HD64461_LDVNTR);
ldr3 = inw(HD64461_LDR3);
switch(ldr3&15) {
default:
case 4:
par.bpp = 8;
par.x = lcdclor;
break;
case 8:
par.bpp = 16;
par.x = lcdclor/2;
break;
}
par.y = ldvntr+1;
hitfb_set_par(&par, NULL);
hitfb_encode_var(&fb_info.default_var, &par, NULL);
}
static int hitfb_encode_fix(struct fb_fix_screeninfo *fix, const void *fb_par,
struct fb_info_gen *info)
{
const struct hitfb_par *par = fb_par;
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, "Hitachi HD64461");
fix->smem_start = fb_info.hit_videobase;
fix->smem_len = fb_info.hit_videosize;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
fix->visual = (par->bpp == 8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
fix->xpanstep = 0;
fix->ypanstep = 0;
fix->ywrapstep = 0;
switch(par->bpp) {
default:
case 8:
fix->line_length = par->x;
break;
case 16:
fix->line_length = par->x*2;
break;
}
return 0;
}
static int hitfb_decode_var(const struct fb_var_screeninfo *var, void *fb_par,
struct fb_info_gen *info)
{
struct hitfb_par *par = fb_par;
par->x = var->xres;
par->y = var->yres;
par->bpp = var->bits_per_pixel;
return 0;
}
static int hitfb_encode_var(struct fb_var_screeninfo *var, const void *fb_par,
struct fb_info_gen *info)
{
const struct hitfb_par *par = fb_par;
memset(var, 0, sizeof(*var));
var->xres = par->x;
var->yres = par->y;
var->xres_virtual = var->xres;
var->yres_virtual = var->yres;
var->xoffset = 0;
var->yoffset = 0;
var->bits_per_pixel = par->bpp;
var->grayscale = 0;
var->transp.offset = 0;
var->transp.length = 0;
var->transp.msb_right = 0;
var->nonstd = 0;
var->activate = 0;
var->height = -1;
var->width = -1;
var->vmode = FB_VMODE_NONINTERLACED;
var->pixclock = 0;
var->sync = 0;
var->left_margin = 0;
var->right_margin = 0;
var->upper_margin = 0;
var->lower_margin = 0;
var->hsync_len = 0;
var->vsync_len = 0;
switch (var->bits_per_pixel) {
case 8:
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 0;
var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break;
case 16: /* RGB 565 */
var->red.offset = 11;
var->red.length = 5;
var->green.offset = 5;
var->green.length = 6;
var->blue.offset = 0;
var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
break;
}
var->red.msb_right = 0;
var->green.msb_right = 0;
var->blue.msb_right = 0;
var->transp.msb_right = 0;
return 0;
}
static void hitfb_get_par(void *par, struct fb_info_gen *info)
{
*(struct hitfb_par *)par = fb_info.current_par;
}
static void hitfb_set_par(const void *fb_par, struct fb_info_gen *info)
{
const struct hitfb_par *par = fb_par;
fb_info.current_par = *par;
fb_info.current_par_valid = 1;
static u16 pseudo_palette[17];
static struct display display;
struct fb_info fb_info;
static int hitfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
var->xres_virtual = var->xres;
var->yres_virtual = var->yres;
switch (var->bits_per_pixel) {
case 8:
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 0;
var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break;
case 16: /* RGB 565 */
var->red.offset = 11;
var->red.length = 5;
var->green.offset = 5;
var->green.length = 6;
var->blue.offset = 0;
var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
break;
}
return 0;
}
static int hitfb_getcolreg(unsigned regno, unsigned *red, unsigned *green,
unsigned *blue, unsigned *transp,
struct fb_info *info)
static int hitfb_set_par(struct fb_info *info)
{
if (regno > 255)
return 1;
info->fix.visual = (info->var.bits_per_pixel == 8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
outw(regno<<8, HD64461_CPTRAR);
*red = inw(HD64461_CPTRDR)<<10;
*green = inw(HD64461_CPTRDR)<<10;
*blue = inw(HD64461_CPTRDR)<<10;
*transp = 0;
return 0;
switch(info->var.bits_per_pixel) {
default:
case 8:
info->fix.line_length = info->var.xres;
break;
case 16:
info->fix.line_length = info->var.xres*2;
break;
}
return 0;
}
static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
if (regno > 255)
return 1;
if (regno > 255)
return 1;
outw(regno<<8, HD64461_CPTWAR);
outw(red>>10, HD64461_CPTWDR);
outw(green>>10, HD64461_CPTWDR);
outw(blue>>10, HD64461_CPTWDR);
outw(regno << 8, HD64461_CPTWAR);
outw(red >> 10, HD64461_CPTWDR);
outw(green >> 10, HD64461_CPTWDR);
outw(blue >> 10, HD64461_CPTWDR);
if(regno<16) {
switch(fb_info.current_par.bpp) {
if (regno < 16) {
switch(info->var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB16
case 16:
fb_info.fbcon_cmap.cfb16[regno] =
((red & 0xf800) ) |
((green & 0xfc00) >> 5) |
((blue & 0xf800) >> 11);
break;
case 16:
((u16 *)(info->pseudo_palette))[regno] =
((red & 0xf800) ) |
((green & 0xfc00) >> 5) |
((blue & 0xf800) >> 11);
break;
#endif
}
}
}
return 0;
}
static int hitfb_pan_display(const struct fb_var_screeninfo *var,
struct fb_info_gen *info)
{
if (!fb_info.current_par_valid)
return -EINVAL;
return 0;
}
static int hitfb_blank(int blank_mode, struct fb_info_gen *info)
{
if (!fb_info.current_par_valid)
return 1;
return 0;
return 0;
}
static void hitfb_set_disp(const void *fb_par, struct display *disp,
struct fb_info_gen *info)
{
const struct hitfb_par *par = fb_par;
disp->scrollmode = SCROLL_YREDRAW;
switch(((struct hitfb_par *)par)->bpp) {
#ifdef FBCON_HAS_CFB8
case 8:
disp->dispsw = &fbcon_cfb8;
break;
#endif
#ifdef FBCON_HAS_CFB16
case 16:
disp->dispsw = &fbcon_cfb16;
disp->dispsw_data = fb_info.fbcon_cmap.cfb16;
break;
#endif
default:
disp->dispsw = &fbcon_dummy;
}
}
struct fbgen_hwswitch hitfb_switch = {
hitfb_detect,
hitfb_encode_fix,
hitfb_decode_var,
hitfb_encode_var,
hitfb_get_par,
hitfb_set_par,
hitfb_getcolreg,
hitfb_pan_display,
hitfb_blank,
hitfb_set_disp
};
static struct fb_ops hitfb_ops = {
owner: THIS_MODULE,
fb_get_fix: fbgen_get_fix,
fb_get_var: fbgen_get_var,
fb_set_var: fbgen_set_var,
fb_get_cmap: fbgen_get_cmap,
fb_set_cmap: fbgen_set_cmap,
fb_setcolreg: hitfb_setcolreg,
fb_pan_display: fbgen_pan_display,
fb_blank: fbgen_blank,
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: hitfb_check_var,
fb_set_par: hitfb_set_par,
fb_setcolreg: hitfb_setcolreg,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
};
int __init hitfb_init(void)
{
strcpy(fb_info.gen.info.modename, "Hitachi HD64461");
fb_info.gen.info.node = NODEV;
fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
fb_info.gen.info.fbops = &hitfb_ops;
fb_info.gen.info.disp = &fb_info.disp;
fb_info.gen.info.currcon = 1;
fb_info.gen.info.changevar = NULL;
fb_info.gen.info.switch_con = &fbgen_switch;
fb_info.gen.info.updatevar = &fbgen_update_var;
fb_info.gen.parsize = sizeof(struct hitfb_par);
fb_info.gen.fbhw = &hitfb_switch;
fb_info.gen.fbhw->detect();
fb_info.screen_base = (void *)fb_info.hit_videobase;
fbgen_get_var(&fb_info.disp.var, -1, &fb_info.gen.info);
fb_info.disp.var.activate = FB_ACTIVATE_NOW;
fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen);
fbgen_set_disp(-1, &fb_info.gen);
do_install_cmap(0, &fb_info.gen);
if(register_framebuffer(&fb_info.gen.info)<0) return -EINVAL;
unsigned short lcdclor, ldr3, ldvntr;
hitfb_fix.smem_start = CONFIG_HD64461_IOBASE + 0x02000000;
hitfb_fix.smem_len = (MACH_HP680 || MACH_HP690) ? 1024*1024 : 512*1024;
lcdclor = inw(HD64461_LCDCLOR);
ldvntr = inw(HD64461_LDVNTR);
ldr3 = inw(HD64461_LDR3);
switch (ldr3&15) {
default:
case 4:
hitfb_var.bits_per_pixel = 8;
hitfb_var.xres = lcdclor;
break;
case 8:
hitfb_var.bits_per_pixel = 16;
hitfb_var.xres = lcdclor/2;
break;
}
hitfb_var.yres = ldvntr+1;
fb_info.node = NODEV;
fb_info.fbops = &hitfb_ops;
fb_info.var = hitfb_var;
fb_info.fix = hitfb_fix;
fb_info.pseudo_palette = pseudo_palette;
fb_info.flags = FBINFO_FLAG_DEFAULT;
strcpy(fb_info.modename, fb_info.fix.id);
fb_info.currcon = -1;
fb_info.disp = &display;
fb_info.changevar = NULL;
fb_info.switch_con = gen_switch;
fb_info.updatevar = gen_update_var;
fb_info.screen_base = (void *) hitfb_fix.smem_start;
size = (fb_info.var.bits_per_pixel == 8) ? 256 : 16;
fb_alloc_cmap(&fb_info.cmap, size, 0);
gen_set_var(&fb_info.var, -1, &fb_info);
printk(KERN_INFO "fb%d: %s frame buffer device\n",
GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename);
if (register_framebuffer(&fb_info) < 0)
return -EINVAL;
return 0;
printk(KERN_INFO "fb%d: %s frame buffer device\n",
GET_FB_IDX(fb_info.node), fb_info.fix.id);
return 0;
}
......@@ -392,7 +211,6 @@ void cleanup_module(void)
}
#endif
/*
* Local variables:
* c-basic-offset: 4
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* linux/drivers/video/pm3fb.h -- 3DLabs Permedia3 frame buffer device
*
* Copyright (C) 2001 Romain Dolbeau <dolbeau@irisa.fr>
* Copyright (C) 2001 Sven Luther, <luther@dpt-info.u-strasbg.fr>
*
* 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.
*
* $Header: /cvsroot/linux/drivers/video/pm3fb.h,v 1.1 2002/02/25 19:11:06 marcelo Exp $
*
*/
#ifndef PM3FB_H
#define PM3FB_H
/**********************************************
* GLINT Permedia3 Control Status registers *
***********************************************/
/* Control Status Registers */
#define PM3ResetStatus 0x0000
#define PM3IntEnable 0x0008
#define PM3IntFlags 0x0010
#define PM3InFIFOSpace 0x0018
#define PM3OutFIFOWords 0x0020
#define PM3DMAAddress 0x0028
#define PM3DMACount 0x0030
#define PM3ErrorFlags 0x0038
#define PM3VClkCtl 0x0040
#define PM3TestRegister 0x0048
#define PM3Aperture0 0x0050
#define PM3Aperture1 0x0058
#define PM3DMAControl 0x0060
#define PM3FIFODis 0x0068
#define PM3ChipConfig 0x0070
#define PM3AGPControl 0x0078
#define PM3GPOutDMAAddress 0x0080
#define PM3PCIFeedbackCount 0x0088
#define PM3PCIAbortStatus 0x0090
#define PM3PCIAbortAddress 0x0098
#define PM3PCIPLLStatus 0x00f0
#define PM3HostTextureAddress 0x0100
#define PM3TextureDownloadControl 0x0108
#define PM3TextureOperation 0x0110
#define PM3LogicalTexturePage 0x0118
#define PM3TexDMAAddress 0x0120
#define PM3TexFIFOSpace 0x0128
/**********************************************
* GLINT Permedia3 Region 0 Bypass Controls *
***********************************************/
#define PM3ByAperture1Mode 0x0300
#define PM3ByApertureMode_BYTESWAP_ABCD (0<<0)
#define PM3ByApertureMode_BYTESWAP_BADC (1<<0)
#define PM3ByApertureMode_BYTESWAP_CDAB (2<<0)
#define PM3ByApertureMode_BYTESWAP_DCBA (3<<0)
#define PM3ByApertureMode_PATCH_DISABLE (0<<2)
#define PM3ByApertureMode_PATCH_ENABLE (1<<2)
#define PM3ByApertureMode_FORMAT_RAW (0<<3)
#define PM3ByApertureMode_FORMAT_YUYV (1<<3)
#define PM3ByApertureMode_FORMAT_UYVY (2<<3)
#define PM3ByApertureMode_PIXELSIZE_8BIT (0<<5)
#define PM3ByApertureMode_PIXELSIZE_16BIT (1<<5)
#define PM3ByApertureMode_PIXELSIZE_32BIT (2<<5)
#define PM3ByApertureMode_PIXELSIZE_MASK (3<<5)
#define PM3ByApertureMode_EFFECTIVE_STRIDE_1024 (0<<7)
#define PM3ByApertureMode_EFFECTIVE_STRIDE_2048 (1<<7)
#define PM3ByApertureMode_EFFECTIVE_STRIDE_4096 (2<<7)
#define PM3ByApertureMode_EFFECTIVE_STRIDE_8192 (3<<7)
#define PM3ByApertureMode_PATCH_OFFSET_X(off) (((off)&7f)<<9)
#define PM3ByApertureMode_PATCH_OFFSET_Y(off) (((off)&7f)<<16)
#define PM3ByApertureMode_FRAMEBUFFER (0<<21)
#define PM3ByApertureMode_LOCALBUFFER (1<<21)
#define PM3ByApertureMode_DOUBLE_WRITE_OFF (0<<22)
#define PM3ByApertureMode_DOUBLE_WRITE_1MB (1<<22)
#define PM3ByApertureMode_DOUBLE_WRITE_2MB (2<<22)
#define PM3ByApertureMode_DOUBLE_WRITE_4MB (3<<22)
#define PM3ByApertureMode_DOUBLE_WRITE_8MB (4<<22)
#define PM3ByApertureMode_DOUBLE_WRITE_16MB (5<<22)
#define PM3ByApertureMode_DOUBLE_WRITE_32MB (6<<22)
#define PM3ByAperture2Mode 0x0328
/**********************************************
* GLINT Permedia3 Memory Control (0x1000) *
***********************************************/
#define PM3MemCounter 0x1000
#define PM3MemBypassWriteMask 0x1008
#define PM3MemScratch 0x1010
#define PM3LocalMemCaps 0x1018
#define PM3LocalMemCaps_NoWriteMask (1 << 28)
#define PM3LocalMemTimings 0x1020
#define PM3LocalMemControl 0x1028
#define PM3LocalMemRefresh 0x1030
#define PM3LocalMemPowerDown 0x1038
#define PM3RemoteMemControl 0x1100
/**********************************************
* GLINT Permedia3 Video Control (0x3000) *
***********************************************/
#define PM3ScreenBase 0x3000
#define PM3ScreenStride 0x3008
#define PM3HTotal 0x3010
#define PM3HgEnd 0x3018
#define PM3HbEnd 0x3020
#define PM3HsStart 0x3028
#define PM3HsEnd 0x3030
#define PM3VTotal 0x3038
#define PM3VbEnd 0x3040
#define PM3VsStart 0x3048
#define PM3VsEnd 0x3050
#define PM3VideoControl 0x3058
#define PM3VideoControl_DISABLE (0<<0)
#define PM3VideoControl_ENABLE (1<<0)
#define PM3VideoControl_BLANK_ACTIVE_HIGH (0<<1)
#define PM3VideoControl_BLANK_ACTIVE_LOW (1<<1)
#define PM3VideoControl_LINE_DOUBLE_OFF (0<<2)
#define PM3VideoControl_LINE_DOUBLE_ON (1<<2)
#define PM3VideoControl_HSYNC_FORCE_HIGH (0<<3)
#define PM3VideoControl_HSYNC_ACTIVE_HIGH (1<<3)
#define PM3VideoControl_HSYNC_FORCE_LOW (2<<3)
#define PM3VideoControl_HSYNC_ACTIVE_LOW (3<<3)
#define PM3VideoControl_HSYNC_MASK (3<<3)
#define PM3VideoControl_VSYNC_FORCE_HIGH (0<<5)
#define PM3VideoControl_VSYNC_ACTIVE_HIGH (1<<5)
#define PM3VideoControl_VSYNC_FORCE_LOW (2<<5)
#define PM3VideoControl_VSYNC_ACTIVE_LOW (3<<5)
#define PM3VideoControl_VSYNC_MASK (3<<5)
#define PM3VideoControl_BYTE_DOUBLE_OFF (0<<7)
#define PM3VideoControl_BYTE_DOUBLE_ON (1<<7)
#define PM3VideoControl_BUFFER_SWAP_SYNCON_FRAMEBLANK (0<<9)
#define PM3VideoControl_BUFFER_SWAP_FREE_RUNNING (1<<9)
#define PM3VideoControl_BUFFER_SWAP_LIMITETO_FRAMERATE (2<<9)
#define PM3VideoControl_STEREO_DISABLE (0<<11)
#define PM3VideoControl_STEREO_ENABLE (1<<11)
#define PM3VideoControl_RIGHT_EYE_ACTIVE_HIGH (0<<12)
#define PM3VideoControl_RIGHT_EYE_ACTIVE_LOW (1<<12)
#define PM3VideoControl_VIDEO_EXT_LOW (0<<14)
#define PM3VideoControl_VIDEO_EXT_HIGH (1<<14)
#define PM3VideoControl_SYNC_MODE_INDEPENDENT (0<<16)
#define PM3VideoControl_SYNC_MODE_SYNCTO_VSA (1<<16)
#define PM3VideoControl_SYNC_MODE_SYNCTO_VSB (2<<16)
#define PM3VideoControl_PATCH_DISABLE (0<<18)
#define PM3VideoControl_PATCH_ENABLE (1<<18)
#define PM3VideoControl_PIXELSIZE_8BIT (0<<19)
#define PM3VideoControl_PIXELSIZE_16BIT (1<<19)
#define PM3VideoControl_PIXELSIZE_32BIT (2<<19)
#define PM3VideoControl_DISPLAY_DISABLE (0<<21)
#define PM3VideoControl_DISPLAY_ENABLE (1<<21)
#define PM3VideoControl_PATCH_OFFSET_X(off) (((off)&0x3f)<<22)
#define PM3VideoControl_PATCH_OFFSET_Y(off) (((off)&0x3f)<<28)
#define PM3InterruptLine 0x3060
#define PM3DisplayData 0x3068
#define PM3VerticalLineCount 0x3070
#define PM3FifoControl 0x3078
#define PM3ScreenBaseRight 0x3080
#define PM3MiscControl 0x3088
#define PM3VideoOverlayUpdate 0x3100
#define PM3VideoOverlayUpdate_DISABLE (0<<0)
#define PM3VideoOverlayUpdate_ENABLE (1<<0)
#define PM3VideoOverlayMode 0x3108
#define PM3VideoOverlayMode_DISABLE (0<<0)
#define PM3VideoOverlayMode_ENABLE (1<<0)
#define PM3VideoOverlayMode_BUFFERSYNC_MANUAL (0<<1)
#define PM3VideoOverlayMode_BUFFERSYNC_VIDEOSTREAMA (1<<1)
#define PM3VideoOverlayMode_BUFFERSYNC_VIDEOSTREAMB (2<<1)
#define PM3VideoOverlayMode_FIELDPOLARITY_NORMAL (0<<4)
#define PM3VideoOverlayMode_FIELDPOLARITY_INVERT (1<<4)
#define PM3VideoOverlayMode_PIXELSIZE_8BIT (0<<5)
#define PM3VideoOverlayMode_PIXELSIZE_16BIT (1<<5)
#define PM3VideoOverlayMode_PIXELSIZE_32BIT (2<<5)
#define PM3VideoOverlayMode_COLORFORMAT_RGB8888 ((0<<7)|(1<<12)|(2<<5))
#define PM3VideoOverlayMode_COLORFORMAT_RGB4444 ((1<<7)|(1<<12)|(1<<5))
#define PM3VideoOverlayMode_COLORFORMAT_RGB5551 ((2<<7)|(1<<12)|(1<<5))
#define PM3VideoOverlayMode_COLORFORMAT_RGB565 ((3<<7)|(1<<12)|(1<<5))
#define PM3VideoOverlayMode_COLORFORMAT_RGB332 ((4<<7)|(1<<12)|(0<<5))
#define PM3VideoOverlayMode_COLORFORMAT_BGR8888 ((0<<7)|(2<<5))
#define PM3VideoOverlayMode_COLORFORMAT_BGR4444 ((1<<7)|(1<<5))
#define PM3VideoOverlayMode_COLORFORMAT_BGR5551 ((2<<7)|(1<<5))
#define PM3VideoOverlayMode_COLORFORMAT_BGR565 ((3<<7)|(1<<5))
#define PM3VideoOverlayMode_COLORFORMAT_BGR332 ((4<<7)|(0<<5))
#define PM3VideoOverlayMode_COLORFORMAT_CI8 ((5<<7)|(1<<12)|(0<<5))
#define PM3VideoOverlayMode_COLORFORMAT_VUY444 ((2<<10)|(1<<12)|(2<<5))
#define PM3VideoOverlayMode_COLORFORMAT_YUV444 ((2<<10)|(2<<5))
#define PM3VideoOverlayMode_COLORFORMAT_VUY422 ((1<<10)|(1<<12)|(1<<5))
#define PM3VideoOverlayMode_COLORFORMAT_YUV422 ((1<<10)|(1<<5))
#define PM3VideoOverlayMode_COLORORDER_BGR (0<<12)
#define PM3VideoOverlayMode_COLORORDER_RGB (1<<12)
#define PM3VideoOverlayMode_LINEARCOLOREXT_OFF (0<<13)
#define PM3VideoOverlayMode_LINEARCOLOREXT_ON (1<<13)
#define PM3VideoOverlayMode_FILTER_MASK (3<<14)
#define PM3VideoOverlayMode_FILTER_OFF (0<<14)
#define PM3VideoOverlayMode_FILTER_FULL (1<<14)
#define PM3VideoOverlayMode_FILTER_PARTIAL (2<<14)
#define PM3VideoOverlayMode_DEINTERLACE_OFF (0<<16)
#define PM3VideoOverlayMode_DEINTERLACE_BOB (1<<16)
#define PM3VideoOverlayMode_PATCHMODE_OFF (0<<18)
#define PM3VideoOverlayMode_PATCHMODE_ON (1<<18)
#define PM3VideoOverlayMode_FLIP_VIDEO (0<<20)
#define PM3VideoOverlayMode_FLIP_VIDEOSTREAMA (1<<20)
#define PM3VideoOverlayMode_FLIP_VIDEOSTREAMB (2<<20)
#define PM3VideoOverlayMode_MIRROR_MASK (3<<23)
#define PM3VideoOverlayMode_MIRRORX_OFF (0<<23)
#define PM3VideoOverlayMode_MIRRORX_ON (1<<23)
#define PM3VideoOverlayMode_MIRRORY_OFF (0<<24)
#define PM3VideoOverlayMode_MIRRORY_ON (1<<24)
#define PM3VideoOverlayFifoControl 0x3110
#define PM3VideoOverlayIndex 0x3118
#define PM3VideoOverlayBase0 0x3120
#define PM3VideoOverlayBase1 0x3128
#define PM3VideoOverlayBase2 0x3130
#define PM3VideoOverlayStride 0x3138
#define PM3VideoOverlayStride_STRIDE(s) (((s)&0xfff)<<0)
#define PM3VideoOverlayWidth 0x3140
#define PM3VideoOverlayWidth_WIDTH(w) (((w)&0xfff)<<0)
#define PM3VideoOverlayHeight 0x3148
#define PM3VideoOverlayHeight_HEIGHT(h) (((h)&0xfff)<<0)
#define PM3VideoOverlayOrigin 0x3150
#define PM3VideoOverlayOrigin_XORIGIN(x) (((x)&0xfff)<<0)
#define PM3VideoOverlayOrigin_YORIGIN(y) (((y)&0xfff)<<16)
#define PM3VideoOverlayShrinkXDelta 0x3158
#define PM3VideoOverlayShrinkXDelta_NONE (1<<16)
#define PM3VideoOverlayShrinkXDelta_DELTA(s,d) \
((((s)<<16)/(d))&0x0ffffff0)
#define PM3VideoOverlayZoomXDelta 0x3160
#define PM3VideoOverlayZoomXDelta_NONE (1<<16)
#define PM3VideoOverlayZoomXDelta_DELTA(s,d) \
((((s)<<16)/(d))&0x0001fff0)
#define PM3VideoOverlayYDelta 0x3168
#define PM3VideoOverlayYDelta_NONE (1<<16)
#define PM3VideoOverlayYDelta_DELTA(s,d) \
((((s)<<16)/(d))&0x0ffffff0)
#define PM3VideoOverlayFieldOffset 0x3170
#define PM3VideoOverlayStatus 0x3178
/**********************************************
* GLINT Permedia3 RAMDAC Registers (0x4000) *
***********************************************/
/* Direct Registers */
#define PM3RD_PaletteWriteAddress 0x4000
#define PM3RD_PaletteData 0x4008
#define PM3RD_PixelMask 0x4010
#define PM3RD_PaletteReadAddress 0x4018
#define PM3RD_IndexLow 0x4020
#define PM3RD_IndexHigh 0x4028
#define PM3RD_IndexedData 0x4030
#define PM3RD_IndexControl 0x4038
#define PM3RD_IndexControl_AUTOINCREMENT_ENABLE (1<<0)
#define PM3RD_IndexControl_AUTOINCREMENT_DISABLE (0<<0)
/* Indirect Registers */
#define PM3RD_MiscControl 0x000
#define PM3RD_MiscControl_HIGHCOLOR_RES_DISABLE (0<<0)
#define PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE (1<<0)
#define PM3RD_MiscControl_PIXELDOUBLE_DISABLE (0<<1)
#define PM3RD_MiscControl_PIXELDOUBLE_ENABLE (1<<1)
#define PM3RD_MiscControl_LASTREAD_ADDR_DISABLE (0<<2)
#define PM3RD_MiscControl_LASTREAD_ADDR_ENABLE (1<<2)
#define PM3RD_MiscControl_DIRECTCOLOR_DISABLE (0<<3)
#define PM3RD_MiscControl_DIRECTCOLOR_ENABLE (1<<3)
#define PM3RD_MiscControl_OVERLAY_DISABLE (0<<4)
#define PM3RD_MiscControl_OVERLAY_ENABLE (1<<4)
#define PM3RD_MiscControl_PIXELDOUBLE_BUFFER_DISABLE (0<<5)
#define PM3RD_MiscControl_PIXELDOUBLE_BUFFER_ENABLE (1<<5)
#define PM3RD_MiscControl_VSB_OUTPUT_DISABLE (0<<6)
#define PM3RD_MiscControl_VSB_OUTPUT_ENABLE (1<<6)
#define PM3RD_MiscControl_STEREODOUBLE_BUFFER_DISABLE (0<<7)
#define PM3RD_MiscControl_STEREODOUBLE_BUFFER_ENABLE (1<<7)
#define PM3RD_SyncControl 0x001
#define PM3RD_SyncControl_HSYNC_ACTIVE_LOW (0<<0)
#define PM3RD_SyncControl_HSYNC_ACTIVE_HIGH (1<<0)
#define PM3RD_SyncControl_HSYNC_FORCE_ACTIVE (3<<0)
#define PM3RD_SyncControl_HSYNC_FORCE_INACTIVE (4<<0)
#define PM3RD_SyncControl_HSYNC_TRI_STATE (2<<0)
#define PM3RD_SyncControl_VSYNC_ACTIVE_LOW (0<<3)
#define PM3RD_SyncControl_VSYNC_ACTIVE_HIGH (1<<3)
#define PM3RD_SyncControl_VSYNC_TRI_STATE (2<<3)
#define PM3RD_SyncControl_VSYNC_FORCE_ACTIVE (3<<3)
#define PM3RD_SyncControl_VSYNC_FORCE_INACTIVE (4<<3)
#define PM3RD_SyncControl_HSYNC_OVERRIDE_SETBY_HSYNC (0<<6)
#define PM3RD_SyncControl_HSYNC_OVERRIDE_FORCE_HIGH (1<<6)
#define PM3RD_SyncControl_VSYNC_OVERRIDE_SETBY_VSYNC (0<<7)
#define PM3RD_SyncControl_VSYNC_OVERRIDE_FORCE_HIGH (1<<7)
#define PM3RD_DACControl 0x002
#define PM3RD_DACControl_DAC_POWER_ON (0<<0)
#define PM3RD_DACControl_DAC_POWER_OFF (1<<0)
#define PM3RD_DACControl_SYNC_ON_GREEN_DISABLE (0<<3)
#define PM3RD_DACControl_SYNC_ON_GREEN_ENABLE (1<<3)
#define PM3RD_DACControl_BLANK_RED_DAC_DISABLE (0<<4)
#define PM3RD_DACControl_BLANK_RED_DAC_ENABLE (1<<4)
#define PM3RD_DACControl_BLANK_GREEN_DAC_DISABLE (0<<5)
#define PM3RD_DACControl_BLANK_GREEN_DAC_ENABLE (1<<5)
#define PM3RD_DACControl_BLANK_BLUE_DAC_DISABLE (0<<6)
#define PM3RD_DACControl_BLANK_BLUE_DAC_ENABLE (1<<6)
#define PM3RD_DACControl_BLANK_PEDESTAL_DISABLE (0<<7)
#define PM3RD_DACControl_BLANK_PEDESTAL_ENABLE (1<<7)
#define PM3RD_PixelSize 0x003
#define PM3RD_PixelSize_24_BIT_PIXELS (4<<0)
#define PM3RD_PixelSize_32_BIT_PIXELS (2<<0)
#define PM3RD_PixelSize_16_BIT_PIXELS (1<<0)
#define PM3RD_PixelSize_8_BIT_PIXELS (0<<0)
#define PM3RD_ColorFormat 0x004
#define PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE (1<<6)
#define PM3RD_ColorFormat_LINEAR_COLOR_EXT_DISABLE (0<<6)
#define PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW (1<<5)
#define PM3RD_ColorFormat_COLOR_ORDER_RED_LOW (0<<5)
#define PM3RD_ColorFormat_COLOR_FORMAT_MASK (0x1f<<0)
#define PM3RD_ColorFormat_8888_COLOR (0<<0)
#define PM3RD_ColorFormat_5551_FRONT_COLOR (1<<0)
#define PM3RD_ColorFormat_4444_COLOR (2<<0)
#define PM3RD_ColorFormat_332_FRONT_COLOR (5<<0)
#define PM3RD_ColorFormat_332_BACK_COLOR (6<<0)
#define PM3RD_ColorFormat_2321_FRONT_COLOR (9<<0)
#define PM3RD_ColorFormat_2321_BACK_COLOR (10<<0)
#define PM3RD_ColorFormat_232_FRONTOFF_COLOR (11<<0)
#define PM3RD_ColorFormat_232_BACKOFF_COLOR (12<<0)
#define PM3RD_ColorFormat_5551_BACK_COLOR (13<<0)
#define PM3RD_ColorFormat_CI8_COLOR (14<<0)
#define PM3RD_ColorFormat_565_FRONT_COLOR (16<<0)
#define PM3RD_ColorFormat_565_BACK_COLOR (17<<0)
#define PM3RD_CursorMode 0x005
#define PM3RD_CursorMode_CURSOR_DISABLE (0<<0)
#define PM3RD_CursorMode_CURSOR_ENABLE (1<<0)
#define PM3RD_CursorMode_FORMAT_64x64_2BPE_P0123 (0<<2)
#define PM3RD_CursorMode_FORMAT_32x32_2BPE_P0 (1<<2)
#define PM3RD_CursorMode_FORMAT_32x32_2BPE_P1 (2<<2)
#define PM3RD_CursorMode_FORMAT_32x32_2BPE_P2 (3<<2)
#define PM3RD_CursorMode_FORMAT_32x32_2BPE_P3 (4<<2)
#define PM3RD_CursorMode_FORMAT_32x32_4BPE_P01 (5<<2)
#define PM3RD_CursorMode_FORMAT_32x32_4BPE_P23 (6<<2)
#define PM3RD_CursorMode_TYPE_MS (0<<4)
#define PM3RD_CursorMode_TYPE_X (1<<4)
#define PM3RD_CursorMode_REVERSE_PIXEL_ORDER_DISABLE (0<<6)
#define PM3RD_CursorMode_REVERSE_PIXEL_ORDER_ENABLE (1<<6)
#define PM3RD_CursorMode_REVERSE_PIXEL_ORDER_3_COLOR (2<<6)
#define PM3RD_CursorMode_REVERSE_PIXEL_ORDER_15_COLOR (3<<6)
#define PM3RD_CursorControl 0x006
#define PM3RD_CursorControl_DOUBLE_X_DISABLED (0<<0)
#define PM3RD_CursorControl_DOUBLE_X_ENABLED (1<<0)
#define PM3RD_CursorControl_DOUBLE_Y_DISABLED (0<<1)
#define PM3RD_CursorControl_DOUBLE_Y_ENABLED (1<<1)
#define PM3RD_CursorControl_READBACK_POS_DISABLED (0<<2)
#define PM3RD_CursorControl_READBACK_POS_ENABLED (1<<2)
#define PM3RD_CursorXLow 0x007
#define PM3RD_CursorXHigh 0x008
#define PM3RD_CursorYLow 0x009
#define PM3RD_CursorYHigh 0x00a
#define PM3RD_CursorHotSpotX 0x00b
#define PM3RD_CursorHotSpotY 0x00c
#define PM3RD_OverlayKey 0x00d
#define PM3RD_Pan 0x00e
#define PM3RD_Pan_DISABLE (0<<0)
#define PM3RD_Pan_ENABLE (1<<0)
#define PM3RD_Pan_GATE_DISABLE (0<<1)
#define PM3RD_Pan_GATE_ENABLE (1<<1)
#define PM3RD_Sense 0x00f
#define PM3RD_CheckControl 0x018
#define PM3RD_CheckControl_PIXEL_DISABLED (0<<0)
#define PM3RD_CheckControl_PIXEL_ENABLED (1<<0)
#define PM3RD_CheckControl_LUT_DISABLED (0<<1)
#define PM3RD_CheckControl_LUT_ENABLED (1<<1)
#define PM3RD_CheckPixelRed 0x019
#define PM3RD_CheckPixelGreen 0x01a
#define PM3RD_CheckPixelBlue 0x01b
#define PM3RD_CheckLUTRed 0x01c
#define PM3RD_CheckLUTGreen 0x01d
#define PM3RD_CheckLUTBlue 0x01e
#define PM3RD_Scratch 0x01f
#define PM3RD_VideoOverlayControl 0x020
#define PM3RD_VideoOverlayControl_DISABLE (0<<0)
#define PM3RD_VideoOverlayControl_ENABLE (1<<0)
#define PM3RD_VideoOverlayControl_MODE_MASK (3<<1)
#define PM3RD_VideoOverlayControl_MODE_MAINKEY (0<<1)
#define PM3RD_VideoOverlayControl_MODE_OVERLAYKEY (1<<1)
#define PM3RD_VideoOverlayControl_MODE_ALWAYS (2<<1)
#define PM3RD_VideoOverlayControl_MODE_BLEND (3<<1)
#define PM3RD_VideoOverlayControl_DIRECTCOLOR_DISABLED (0<<3)
#define PM3RD_VideoOverlayControl_DIRECTCOLOR_ENABLED (1<<3)
#define PM3RD_VideoOverlayControl_BLENDSRC_MAIN (0<<4)
#define PM3RD_VideoOverlayControl_BLENDSRC_REGISTER (1<<4)
#define PM3RD_VideoOverlayControl_KEY_COLOR (0<<5)
#define PM3RD_VideoOverlayControl_KEY_ALPHA (1<<5)
#define PM3RD_VideoOverlayXStartLow 0x021
#define PM3RD_VideoOverlayXStartHigh 0x022
#define PM3RD_VideoOverlayYStartLow 0x023
#define PM3RD_VideoOverlayYStartHigh 0x024
#define PM3RD_VideoOverlayXEndLow 0x025
#define PM3RD_VideoOverlayXEndHigh 0x026
#define PM3RD_VideoOverlayYEndLow 0x027
#define PM3RD_VideoOverlayYEndHigh 0x028
#define PM3RD_VideoOverlayKeyR 0x029
#define PM3RD_VideoOverlayKeyG 0x02a
#define PM3RD_VideoOverlayKeyB 0x02b
#define PM3RD_VideoOverlayBlend 0x02c
#define PM3RD_VideoOverlayBlend_FACTOR_0_PERCENT (0<<6)
#define PM3RD_VideoOverlayBlend_FACTOR_25_PERCENT (1<<6)
#define PM3RD_VideoOverlayBlend_FACTOR_75_PERCENT (2<<6)
#define PM3RD_VideoOverlayBlend_FACTOR_100_PERCENT (3<<6)
#define PM3RD_DClkSetup1 0x1f0
#define PM3RD_DClkSetup2 0x1f1
#define PM3RD_KClkSetup1 0x1f2
#define PM3RD_KClkSetup2 0x1f3
#define PM3RD_DClkControl 0x200
#define PM3RD_DClkControl_SOURCE_PLL (0<<4)
#define PM3RD_DClkControl_SOURCE_VSA (1<<4)
#define PM3RD_DClkControl_SOURCE_VSB (2<<4)
#define PM3RD_DClkControl_SOURCE_EXT (3<<4)
#define PM3RD_DClkControl_STATE_RUN (2<<2)
#define PM3RD_DClkControl_STATE_HIGH (1<<2)
#define PM3RD_DClkControl_STATE_LOW (0<<2)
#define PM3RD_DClkControl_LOCKED (1<<1)
#define PM3RD_DClkControl_NOT_LOCKED (0<<1)
#define PM3RD_DClkControl_ENABLE (1<<0)
#define PM3RD_DClkControl_DISABLE (0<<0)
#define PM3RD_DClk0PreScale 0x201
#define PM3RD_DClk0FeedbackScale 0x202
#define PM3RD_DClk0PostScale 0x203
#define PM3_REF_CLOCK 14318
#define PM3RD_DClk1PreScale 0x204
#define PM3RD_DClk1FeedbackScale 0x205
#define PM3RD_DClk1PostScale 0x206
#define PM3RD_DClk2PreScale 0x207
#define PM3RD_DClk2FeedbackScale 0x208
#define PM3RD_DClk2PostScale 0x209
#define PM3RD_DClk3PreScale 0x20a
#define PM3RD_DClk3FeedbackScale 0x20b
#define PM3RD_DClk3PostScale 0x20c
#define PM3RD_KClkControl 0x20d
#define PM3RD_KClkControl_DISABLE (0<<0)
#define PM3RD_KClkControl_ENABLE (1<<0)
#define PM3RD_KClkControl_NOT_LOCKED (0<<1)
#define PM3RD_KClkControl_LOCKED (1<<1)
#define PM3RD_KClkControl_STATE_LOW (0<<2)
#define PM3RD_KClkControl_STATE_HIGH (1<<2)
#define PM3RD_KClkControl_STATE_RUN (2<<2)
#define PM3RD_KClkControl_STATE_LOW_POWER (3<<2)
#define PM3RD_KClkControl_SOURCE_PCLK (0<<4)
#define PM3RD_KClkControl_SOURCE_HALF_PCLK (1<<4)
#define PM3RD_KClkControl_SOURCE_PLL (2<<4)
#define PM3RD_KClkPreScale 0x20e
#define PM3RD_KClkFeedbackScale 0x20f
#define PM3RD_KClkPostScale 0x210
#define PM3RD_MClkControl 0x211
#define PM3RD_MClkControl_DISABLE (0<<0)
#define PM3RD_MClkControl_ENABLE (1<<0)
#define PM3RD_MClkControl_NOT_LOCKED (0<<1)
#define PM3RD_MClkControl_LOCKED (1<<1)
#define PM3RD_MClkControl_STATE_LOW (0<<2)
#define PM3RD_MClkControl_STATE_HIGH (1<<2)
#define PM3RD_MClkControl_STATE_RUN (2<<2)
#define PM3RD_MClkControl_STATE_LOW_POWER (3<<2)
#define PM3RD_MClkControl_SOURCE_PCLK (0<<4)
#define PM3RD_MClkControl_SOURCE_HALF_PCLK (1<<4)
#define PM3RD_MClkControl_SOURCE_HALF_EXT (3<<4)
#define PM3RD_MClkControl_SOURCE_EXT (4<<4)
#define PM3RD_MClkControl_SOURCE_HALF_KCLK (5<<4)
#define PM3RD_MClkControl_SOURCE_KCLK (6<<4)
#define PM3RD_MClkPreScale 0x212
#define PM3RD_MClkFeedbackScale 0x213
#define PM3RD_MClkPostScale 0x214
#define PM3RD_SClkControl 0x215
#define PM3RD_SClkControl_DISABLE (0<<0)
#define PM3RD_SClkControl_ENABLE (1<<0)
#define PM3RD_SClkControl_NOT_LOCKED (0<<1)
#define PM3RD_SClkControl_LOCKED (1<<1)
#define PM3RD_SClkControl_STATE_LOW (0<<2)
#define PM3RD_SClkControl_STATE_HIGH (1<<2)
#define PM3RD_SClkControl_STATE_RUN (2<<2)
#define PM3RD_SClkControl_STATE_LOW_POWER (3<<2)
#define PM3RD_SClkControl_SOURCE_PCLK (0<<4)
#define PM3RD_SClkControl_SOURCE_HALF_PCLK (1<<4)
#define PM3RD_SClkControl_SOURCE_HALF_EXT (3<<4)
#define PM3RD_SClkControl_SOURCE_EXT (4<<4)
#define PM3RD_SClkControl_SOURCE_HALF_KCLK (5<<4)
#define PM3RD_SClkControl_SOURCE_KCLK (6<<4)
#define PM3RD_SClkPreScale 0x216
#define PM3RD_SClkFeedbackScale 0x217
#define PM3RD_SClkPostScale 0x218
#define PM3RD_CursorPalette(p) (0x303+(p))
#define PM3RD_CursorPattern(p) (0x400+(p))
/******************************************************
* GLINT Permedia3 Video Streaming Registers (0x5000) *
*******************************************************/
#define PM3VSConfiguration 0x5800
/**********************************************
* GLINT Permedia3 Core Registers (0x8000+) *
***********************************************/
#define PM3AALineWidth 0x94c0
#define PM3AAPointsize 0x94a0
#define PM3AlphaBlendAlphaMode 0xafa8
#define PM3AlphaBlendAlphaModeAnd 0xad30
#define PM3AlphaBlendAlphaModeOr 0xad38
#define PM3AlphaBlendColorMode 0xafa0
#define PM3AlphaBlendColorModeAnd 0xacb0
#define PM3AlphaBlendColorModeOr 0xacb8
#define PM3AlphaDestColor 0xaf88
#define PM3AlphaSourceColor 0xaf80
#define PM3AlphaTestMode 0x8800
#define PM3AlphaTestModeAnd 0xabf0
#define PM3AlphaTestModeOr 0xabf8
#define PM3AntialiasMode 0x8808
#define PM3AntialiasModeAnd 0xac00
#define PM3AntialiasModeOr 0xac08
/* ... */
#define PM3BackgroundColor 0xb0c8
/* ... */
#define PM3ColorDDAMode 0x87e0
#define PM3ColorDDAModeAnd 0xabe0
#define PM3ColorDDAModeOr 0xabe8
#define PM3CommandInterrupt 0xa990
#define PM3ConstantColorDDA 0xafb0
#define PM3ConstantColorDDA_R(r) ((r)&0xff)
#define PM3ConstantColorDDA_G(g) (((g)&0xff)<<8)
#define PM3ConstantColorDDA_B(b) (((b)&0xff)<<16)
#define PM3ConstantColorDDA_A(a) (((a)&0xff)<<24)
#define PM3ContextData 0x8dd0
#define PM3ContextDump 0x8dc0
#define PM3ContextRestore 0x8dc8
#define PM3Continue 0x8058
#define PM3ContinueNewDom 0x8048
#define PM3ContinueNewLine 0x8040
#define PM3ContinueNewSub 0x8050
#define PM3Count 0x8030
/* ... */
#define PM3DeltaControl 0x9350
#define PM3DeltaControlAnd 0xab20
#define PM3DeltaControlOr 0xab28
#define PM3DeltaMode 0x9300
#define PM3DeltaModeAnd 0xaad0
#define PM3DeltaModeOr 0xaad8
/* ... */
#define PM3DitherMode 0x8818
#define PM3DitherModeAnd 0xacd0
#define PM3DitherModeOr 0xacd8
/* ... */
#define PM3dXDom 0x8008
#define PM3dXSub 0x8018
#define PM3dY 0x8028
/* ... */
#define PM3FBBlockColor 0x8ac8
#define PM3FBBlockColor0 0xb060
#define PM3FBBlockColor1 0xb068
#define PM3FBBlockColor2 0xb070
#define PM3FBBlockColor3 0xb078
#define PM3FBBlockColorBack 0xb0a0
#define PM3FBBlockColorBack0 0xb080
#define PM3FBBlockColorBack1 0xb088
#define PM3FBBlockColorBack2 0xb090
#define PM3FBBlockColorBack3 0xb098
#define PM3FBColor 0x8a98
#define PM3FBDestReadBufferAddr0 0xae80
#define PM3FBDestReadBufferAddr1 0xae88
#define PM3FBDestReadBufferAddr2 0xae90
#define PM3FBDestReadBufferAddr3 0xae98
#define PM3FBDestReadBufferOffset0 0xaea0
#define PM3FBDestReadBufferOffset1 0xaea8
#define PM3FBDestReadBufferOffset2 0xaeb0
#define PM3FBDestReadBufferOffset3 0xaeb8
#define PM3FBDestReadBufferOffset_XOffset(x) ((x)&0xffff)
#define PM3FBDestReadBufferOffset_YOffset(y) (((y)&0xffff)<<16)
#define PM3FBDestReadBufferWidth0 0xaec0
#define PM3FBDestReadBufferWidth1 0xaec8
#define PM3FBDestReadBufferWidth2 0xaed0
#define PM3FBDestReadBufferWidth3 0xaed8
#define PM3FBDestReadBufferWidth_Width(w) ((w)&0x0fff)
#define PM3FBDestReadEnables 0xaee8
#define PM3FBDestReadEnablesAnd 0xad20
#define PM3FBDestReadEnablesOr 0xad28
#define PM3FBDestReadEnables_E(e) ((e)&0xff)
#define PM3FBDestReadEnables_E0 1<<0
#define PM3FBDestReadEnables_E1 1<<1
#define PM3FBDestReadEnables_E2 1<<2
#define PM3FBDestReadEnables_E3 1<<3
#define PM3FBDestReadEnables_E4 1<<4
#define PM3FBDestReadEnables_E5 1<<5
#define PM3FBDestReadEnables_E6 1<<6
#define PM3FBDestReadEnables_E7 1<<7
#define PM3FBDestReadEnables_R(r) (((r)&0xff)<<8)
#define PM3FBDestReadEnables_R0 1<<8
#define PM3FBDestReadEnables_R1 1<<9
#define PM3FBDestReadEnables_R2 1<<10
#define PM3FBDestReadEnables_R3 1<<11
#define PM3FBDestReadEnables_R4 1<<12
#define PM3FBDestReadEnables_R5 1<<13
#define PM3FBDestReadEnables_R6 1<<14
#define PM3FBDestReadEnables_R7 1<<15
#define PM3FBDestReadEnables_ReferenceAlpha(a) (((a)&0xff)<<24)
#define PM3FBDestReadMode 0xaee0
#define PM3FBDestReadModeAnd 0xac90
#define PM3FBDestReadModeOr 0xac98
#define PM3FBDestReadMode_ReadDisable 0<<0
#define PM3FBDestReadMode_ReadEnable 1<<0
#define PM3FBDestReadMode_StripePitch(sp) (((sp)&0x7)<<2
#define PM3FBDestReadMode_StripeHeight(sh) (((sh)&0x7)<<7
#define PM3FBDestReadMode_Enable0 1<<8
#define PM3FBDestReadMode_Enable1 1<<9
#define PM3FBDestReadMode_Enable2 1<<10
#define PM3FBDestReadMode_Enable3 1<<11
#define PM3FBDestReadMode_Layout0(l) (((l)&0x3)<<12
#define PM3FBDestReadMode_Layout1(l) (((l)&0x3)<<14
#define PM3FBDestReadMode_Layout2(l) (((l)&0x3)<<16
#define PM3FBDestReadMode_Layout3(l) (((l)&0x3)<<18
#define PM3FBDestReadMode_Origin0 1<<20
#define PM3FBDestReadMode_Origin1 1<<21
#define PM3FBDestReadMode_Origin2 1<<22
#define PM3FBDestReadMode_Origin3 1<<23
#define PM3FBDestReadMode_Blocking 1<<24
#define PM3FBDestReadMode_UseReadEnabled 1<<26
#define PM3FBDestReadMode_AlphaFiltering 1<<27
#define PM3FBHardwareWriteMask 0x8ac0
#define PM3FBSoftwareWriteMask 0x8820
#define PM3FBData 0x8aa0
#define PM3FBSourceData 0x8aa8
#define PM3FBSourceReadBufferAddr 0xaf08
#define PM3FBSourceReadBufferOffset 0xaf10
#define PM3FBSourceReadBufferOffset_XOffset(x) ((x)&0xffff)
#define PM3FBSourceReadBufferOffset_YOffset(y) (((y)&0xffff)<<16)
#define PM3FBSourceReadBufferWidth 0xaf18
#define PM3FBSourceReadBufferWidth_Width(w) ((w)&0x0fff)
#define PM3FBSourceReadMode 0xaf00
#define PM3FBSourceReadModeAnd 0xaca0
#define PM3FBSourceReadModeOr 0xaca8
#define PM3FBSourceReadMode_ReadDisable (0<<0)
#define PM3FBSourceReadMode_ReadEnable (1<<0)
#define PM3FBSourceReadMode_StripePitch(sp) (((sp)&0x7)<<2
#define PM3FBSourceReadMode_StripeHeight(sh) (((sh)&0x7)<<7
#define PM3FBSourceReadMode_Layout(l) (((l)&0x3)<<8
#define PM3FBSourceReadMode_Origin 1<<10
#define PM3FBSourceReadMode_Blocking 1<<11
#define PM3FBSourceReadMode_UserTexelCoord 1<<13
#define PM3FBSourceReadMode_WrapXEnable 1<<14
#define PM3FBSourceReadMode_WrapYEnable 1<<15
#define PM3FBSourceReadMode_WrapX(w) (((w)&0xf)<<16
#define PM3FBSourceReadMode_WrapY(w) (((w)&0xf)<<20
#define PM3FBSourceReadMode_ExternalSourceData 1<<24
#define PM3FBWriteBufferAddr0 0xb000
#define PM3FBWriteBufferAddr1 0xb008
#define PM3FBWriteBufferAddr2 0xb010
#define PM3FBWriteBufferAddr3 0xb018
#define PM3FBWriteBufferOffset0 0xb020
#define PM3FBWriteBufferOffset1 0xb028
#define PM3FBWriteBufferOffset2 0xb030
#define PM3FBWriteBufferOffset3 0xb038
#define PM3FBWriteBufferOffset_XOffset(x) ((x)&0xffff)
#define PM3FBWriteBufferOffset_YOffset(y) (((y)&0xffff)<<16)
#define PM3FBWriteBufferWidth0 0xb040
#define PM3FBWriteBufferWidth1 0xb048
#define PM3FBWriteBufferWidth2 0xb050
#define PM3FBWriteBufferWidth3 0xb058
#define PM3FBWriteBufferWidth_Width(w) ((w)&0x0fff)
#define PM3FBWriteMode 0x8ab8
#define PM3FBWriteModeAnd 0xacf0
#define PM3FBWriteModeOr 0xacf8
#define PM3FBWriteMode_WriteDisable 0<<0
#define PM3FBWriteMode_WriteEnable 1<<0
#define PM3FBWriteMode_Replicate 1<<4
#define PM3FBWriteMode_OpaqueSpan 1<<5
#define PM3FBWriteMode_StripePitch(p) (((p)&0x7)<<6)
#define PM3FBWriteMode_StripeHeight(h) (((h)&0x7)<<9)
#define PM3FBWriteMode_Enable0 1<<12
#define PM3FBWriteMode_Enable1 1<<13
#define PM3FBWriteMode_Enable2 1<<14
#define PM3FBWriteMode_Enable3 1<<15
#define PM3FBWriteMode_Layout0(l) (((l)&0x3)<<16)
#define PM3FBWriteMode_Layout1(l) (((l)&0x3)<<18)
#define PM3FBWriteMode_Layout2(l) (((l)&0x3)<<20)
#define PM3FBWriteMode_Layout3(l) (((l)&0x3)<<22)
#define PM3FBWriteMode_Origin0 1<<24
#define PM3FBWriteMode_Origin1 1<<25
#define PM3FBWriteMode_Origin2 1<<26
#define PM3FBWriteMode_Origin3 1<<27
#define PM3ForegroundColor 0xb0c0
/* ... */
#define PM3GIDMode 0xb538
#define PM3GIDModeAnd 0xb5b0
#define PM3GIDModeOr 0xb5b8
/* ... */
#define PM3LBDestReadBufferAddr 0xb510
#define PM3LBDestReadBufferOffset 0xb518
#define PM3LBDestReadEnables 0xb508
#define PM3LBDestReadEnablesAnd 0xb590
#define PM3LBDestReadEnablesOr 0xb598
#define PM3LBDestReadMode 0xb500
#define PM3LBDestReadModeAnd 0xb580
#define PM3LBDestReadModeOr 0xb588
#define PM3LBDestReadMode_Disable 0<<0
#define PM3LBDestReadMode_Enable 1<<0
#define PM3LBDestReadMode_StripePitch(p) (((p)&0x7)<<2)
#define PM3LBDestReadMode_StripeHeight(h) (((h)&0x7)<<5)
#define PM3LBDestReadMode_Layout 1<<8
#define PM3LBDestReadMode_Origin 1<<9
#define PM3LBDestReadMode_UserReadEnables 1<<10
#define PM3LBDestReadMode_Packed16 1<<11
#define PM3LBDestReadMode_Width(w) (((w)&0xfff)<<12)
#define PM3LBReadFormat 0x8888
#define PM3LBReadFormat_DepthWidth(w) (((w)&0x3)<<0)
#define PM3LBReadFormat_StencilWidth(w) (((w)&0xf)<<2)
#define PM3LBReadFormat_StencilPosition(p) (((p)&0x1f)<<6)
#define PM3LBReadFormat_FCPWidth(w) (((w)&0xf)<<11)
#define PM3LBReadFormat_FCPPosition(p) (((p)&0x1f)<<15)
#define PM3LBReadFormat_GIDWidth(w) (((w)&0x7)<<20)
#define PM3LBReadFormat_GIDPosition(p) (((p)&0x1f)<<23)
#define PM3LBSourceReadBufferAddr 0xb528
#define PM3LBSourceReadBufferOffset 0xb530
#define PM3LBSourceReadMode 0xb520
#define PM3LBSourceReadModeAnd 0xb5a0
#define PM3LBSourceReadModeOr 0xb5a8
#define PM3LBSourceReadMode_Enable 1<<0
#define PM3LBSourceReadMode_StripePitch(p) (((p)&0x7)<<2)
#define PM3LBSourceReadMode_StripeHeight(h) (((h)&0x7)<<5)
#define PM3LBSourceReadMode_Layout 1<<8
#define PM3LBSourceReadMode_Origin 1<<9
#define PM3LBSourceReadMode_Packed16 1<<10
#define PM3LBSourceReadMode_Width(w) (((w)&0xfff)<<11)
#define PM3LBStencil 0x88a8
#define PM3LBWriteBufferAddr 0xb540
#define PM3LBWriteBufferOffset 0xb548
#define PM3LBWriteFormat 0x88c8
#define PM3LBWriteFormat_DepthWidth(w) (((w)&0x3)<<0)
#define PM3LBWriteFormat_StencilWidth(w) (((w)&0xf)<<2)
#define PM3LBWriteFormat_StencilPosition(p) (((p)&0x1f)<<6)
#define PM3LBWriteFormat_GIDWidth(w) (((w)&0x7)<<20)
#define PM3LBWriteFormat_GIDPosition(p) (((p)&0x1f)<<23)
#define PM3LBWriteMode 0x88c0
#define PM3LBWriteModeAnd 0xac80
#define PM3LBWriteModeOr 0xac88
#define PM3LBWriteMode_WriteDisable 0<<0
#define PM3LBWriteMode_WriteEnable 1<<0
#define PM3LBWriteMode_StripePitch(p) (((p)&0x7)<<3)
#define PM3LBWriteMode_StripeHeight(h) (((h)&0x7)<<6)
#define PM3LBWriteMode_Layout 1<<9
#define PM3LBWriteMode_Origin 1<<10
#define PM3LBWriteMode_Packed16 1<<11
#define PM3LBWriteMode_Width(w) (((w)&0xfff)<<12)
/* ... */
#define PM3LineStippleMode 0x81a8
#define PM3LineStippleModeAnd 0xabc0
#define PM3LineStippleModeOr 0xabc8
#define PM3LoadLineStippleCounters 0x81b0
/* ... */
#define PM3LogicalOpMode 0x8828
#define PM3LogicalOpModeAnd 0xace0
#define PM3LogicalOpModeOr 0xace8
#define PM3LogicalOpMode_Disable (0<<0)
#define PM3LogicalOpMode_Enable (1<<0)
#define PM3LogicalOpMode_LogicOp(op) (((op)&0xf)<<1)
#define PM3LogicalOpMode_UseConstantWriteData_Disable (0<<5)
#define PM3LogicalOpMode_UseConstantWriteData_Enable (1<<5)
#define PM3LogicalOpMode_Background_Disable (0<<6)
#define PM3LogicalOpMode_Background_Enable (1<<6)
#define PM3LogicalOpMode_Background_LogicOp(op) (((op)&0xf)<<7)
#define PM3LogicalOpMode_UseConstantSource_Disable (0<<11)
#define PM3LogicalOpMode_UseConstantSource_Enable (1<<11)
/* ... */
#define PM3LUT 0x8e80
/* ... */
#define PM3LUT 0x8e80
#define PM3LUTAddress 0x84d0
#define PM3LUTData 0x84c8
#define PM3LUTIndex 0x84c0
#define PM3LUTMode 0xb378
#define PM3LUTModeAnd 0xad70
#define PM3LUTModeOr 0xad78
#define PM3LUTTransfer 0x84d8
/* ... */
#define PM3PixelSize 0x80c0
#define PM3PixelSize_GLOBAL_32BIT (0<<0)
#define PM3PixelSize_GLOBAL_16BIT (1<<0)
#define PM3PixelSize_GLOBAL_8BIT (2<<0)
#define PM3PixelSize_RASTERIZER_32BIT (0<<2)
#define PM3PixelSize_RASTERIZER_16BIT (1<<2)
#define PM3PixelSize_RASTERIZER_8BIT (2<<2)
#define PM3PixelSize_SCISSOR_AND_STIPPLE_32BIT (0<<4)
#define PM3PixelSize_SCISSOR_AND_STIPPLE_16BIT (1<<4)
#define PM3PixelSize_SCISSOR_AND_STIPPLE_8BIT (2<<4)
#define PM3PixelSize_TEXTURE_32BIT (0<<6)
#define PM3PixelSize_TEXTURE_16BIT (1<<6)
#define PM3PixelSize_TEXTURE_8BIT (2<<6)
#define PM3PixelSize_LUT_32BIT (0<<8)
#define PM3PixelSize_LUT_16BIT (1<<8)
#define PM3PixelSize_LUT_8BIT (2<<8)
#define PM3PixelSize_FRAMEBUFFER_32BIT (0<<10)
#define PM3PixelSize_FRAMEBUFFER_16BIT (1<<10)
#define PM3PixelSize_FRAMEBUFFER_8BIT (2<<10)
#define PM3PixelSize_LOGICAL_OP_32BIT (0<<12)
#define PM3PixelSize_LOGICAL_OP_16BIT (1<<12)
#define PM3PixelSize_LOGICAL_OP_8BIT (2<<12)
#define PM3PixelSize_LOCALBUFFER_32BIT (0<<14)
#define PM3PixelSize_LOCALBUFFER_16BIT (1<<14)
#define PM3PixelSize_LOCALBUFFER_8BIT (2<<14)
#define PM3PixelSize_SETUP_32BIT (0<<16)
#define PM3PixelSize_SETUP_16BIT (1<<16)
#define PM3PixelSize_SETUP_8BIT (2<<16)
#define PM3PixelSize_GLOBAL (0<<31)
#define PM3PixelSize_INDIVIDUAL (1<<31)
/* ... */
#define PM3Render 0x8038
#define PM3Render_AreaStipple_Disable (0<<0)
#define PM3Render_AreaStipple_Enable (1<<0)
#define PM3Render_LineStipple_Disable (0<<1)
#define PM3Render_LineStipple_Enable (1<<1)
#define PM3Render_ResetLine_Disable (0<<2)
#define PM3Render_ResetLine_Enable (1<<2)
#define PM3Render_FastFill_Disable (0<<3)
#define PM3Render_FastFill_Enable (1<<3)
#define PM3Render_Primitive_Line (0<<6)
#define PM3Render_Primitive_Trapezoid (1<<6)
#define PM3Render_Primitive_Point (2<<6)
#define PM3Render_Antialias_Disable (0<<8)
#define PM3Render_Antialias_Enable (1<<8)
#define PM3Render_Antialias_SubPixelRes_4x4 (0<<9)
#define PM3Render_Antialias_SubPixelRes_8x8 (1<<9)
#define PM3Render_UsePointTable_Disable (0<<10)
#define PM3Render_UsePointTable_Enable (1<<10)
#define PM3Render_SyncOnbitMask_Disable (0<<11)
#define PM3Render_SyncOnBitMask_Enable (1<<11)
#define PM3Render_SyncOnHostData_Disable (0<<12)
#define PM3Render_SyncOnHostData_Enable (1<<12)
#define PM3Render_Texture_Disable (0<<13)
#define PM3Render_Texture_Enable (1<<13)
#define PM3Render_Fog_Disable (0<<14)
#define PM3Render_Fog_Enable (1<<14)
#define PM3Render_Coverage_Disable (0<<15)
#define PM3Render_Coverage_Enable (1<<15)
#define PM3Render_SubPixelCorrection_Disable (0<<16)
#define PM3Render_SubPixelCorrection_Enable (1<<16)
#define PM3Render_SpanOperation_Disable (0<<18)
#define PM3Render_SpanOperation_Enable (1<<18)
#define PM3Render_FBSourceRead_Disable (0<<27)
#define PM3Render_FBSourceRead_Enable (1<<27)
#define PM3RasterizerMode 0x80a0
#define PM3RasterizerModeAnd 0xaba0
#define PM3RasterizerModeOr 0xabb8
#define PM3RectangleHeight 0x94e0
#define PM3Render 0x8038
#define PM3RepeatLine 0x9328
#define PM3ResetPickResult 0x8c20
#define PM3RLEMask 0x8c48
#define PM3RouterMode 0x8840
#define PM3RStart 0x8780
#define PM3S1Start 0x8400
#define PM3aveLineStippleCounters 0x81c0
#define PM3ScissorMaxXY 0x8190
#define PM3ScissorMinXY 0x8188
#define PM3ScissorMode 0x8180
#define PM3ScissorModeAnd 0xabb0
#define PM3ScissorModeOr 0xabb8
#define PM3ScreenSize 0x8198
#define PM3Security 0x8908
#define PM3SetLogicalTexturePage 0xb360
#define PM3SizeOfFramebuffer 0xb0a8
#define PM3SStart 0x8388
#define PM3StartXDom 0x8000
#define PM3StartXSub 0x8010
#define PM3StartY 0x8020
/* ... */
#define PM3SpanColorMask 0x8168
/* ... */
#define PM3TextureApplicationMode 0x8680
#define PM3TextureApplicationModeAnd 0xac50
#define PM3TextureApplicationModeOr 0xac58
#define PM3TextureBaseAddr 0x8500
#define PM3TextureCacheControl 0x8490
#define PM3TextureChromaLower0 0x84f0
#define PM3TextureChromaLower1 0x8608
#define PM3TextureChromaUpper0 0x84e8
#define PM3TextureChromaUpper1 0x8600
#define PM3TextureCompositeAlphaMode0 0xb310
#define PM3TextureCompositeAlphaMode0And 0xb390
#define PM3TextureCompositeAlphaMode0Or 0xb398
#define PM3TextureCompositeAlphaMode1 0xb320
#define PM3TextureCompositeAlphaMode1And 0xb3b0
#define PM3TextureCompositeAlphaMode1Or 0xb3b8
#define PM3TextureCompositeColorMode0 0xb308
#define PM3TextureCompositeColorMode0And 0xb380
#define PM3TextureCompositeColorMode0Or 0xb388
#define PM3TextureCompositeColorMode1 0xb318
#define PM3TextureCompositeColorMode1And 0xb3a0
#define PM3TextureCompositeColorMode1Or 0xb3a8
#define PM3TextureCompositeFactor0 0xb328
#define PM3TextureCompositeFactor1 0xb330
#define PM3TextureCompositeMode 0xb300
#define PM3TextureCoordMode 0x8380
#define PM3TextureCoordModeAnd 0xac20
#define PM3TextureCoordModeOr 0xac28
#define PM3TextureData 0x88e8
/*
#define PM3TextureDownloadControl 0x0108
*/
#define PM3TextureDownloadOffset 0x88f0
#define PM3TextureEnvColor 0x8688
#define PM3TextureFilterMode 0x84e0
#define PM3TextureFilterModeAnd 0xad50
#define PM3TextureFilterModeOr 0xad58
#define PM3TextureIndexMode0 0xb338
#define PM3TextureIndexMode0And 0xb3c0
#define PM3TextureIndexMode0Or 0xb3c8
#define PM3TextureIndexMode1 0xb340
#define PM3TextureIndexMode1And 0xb3d0
#define PM3TextureIndexMode1Or 0xb3d8
/* ... */
#define PM3TextureMapSize 0xb428
#define PM3TextureMapWidth0 0x8580
#define PM3TextureMapWidth1 0x8588
#define PM3TextureMapWidth_Width(w) ((w&0xfff)<<0)
#define PM3TextureMapWidth_BorderLayout (1<<12)
#define PM3TextureMapWidth_Layout_Linear (0<<13)
#define PM3TextureMapWidth_Layout_Patch64 (1<<13)
#define PM3TextureMapWidth_Layout_Patch32_2 (2<<13)
#define PM3TextureMapWidth_Layout_Patch2 (3<<13)
#define PM3TextureMapWidth_HostTexture (1<<15)
#define PM3TextureReadMode0 0xb400
#define PM3TextureReadMode0And 0xac30
#define PM3TextureReadMode0Or 0xac38
#define PM3TextureReadMode1 0xb408
#define PM3TextureReadMode1And 0xad40
#define PM3TextureReadMode1Or 0xad48
/* ... */
#define PM3WaitForCompletion 0x80b8
#define PM3Window 0x8980
#define PM3Window_ForceLBUpdate 1<<3
#define PM3Window_LBUpdateSource 1<<4
#define PM3Window_FrameCount(c) (((c)&0xff)<<9
#define PM3Window_StencilFCP 1<<17
#define PM3Window_DepthFCP 1<<18
#define PM3Window_OverrideWriteFiltering 1<<19
#define PM3WindowAnd 0xab80
#define PM3WindowOr 0xab88
#define PM3WindowOrigin 0x81c8
#define PM3XBias 0x9480
#define PM3YBias 0x9488
#define PM3YLimits 0x80a8
#define PM3UVMode 0x8f00
#define PM3ZFogBias 0x86b8
#define PM3ZStart 0xadd8
#define PM3ZStartL 0x89b8
#define PM3ZStartU 0x89b0
/**********************************************
* GLINT Permedia3 2D setup Unit *
***********************************************/
#define PM3Config2D 0xb618
#define PM3Config2D_OpaqueSpan 1<<0
#define PM3Config2D_MultiRXBlit 1<<1
#define PM3Config2D_UserScissorEnable 1<<2
#define PM3Config2D_FBDestReadEnable 1<<3
#define PM3Config2D_AlphaBlendEnable 1<<4
#define PM3Config2D_DitherEnable 1<<5
#define PM3Config2D_ForegroundROPEnable 1<<6
#define PM3Config2D_ForegroundROP(rop) (((rop)&0xf)<<7)
#define PM3Config2D_BackgroundROPEnable 1<<11
#define PM3Config2D_BackgroundROP(rop) (((rop)&0xf)<<12)
#define PM3Config2D_UseConstantSource 1<<16
#define PM3Config2D_FBWriteEnable 1<<17
#define PM3Config2D_Blocking 1<<18
#define PM3Config2D_ExternalSourceData 1<<19
#define PM3Config2D_LUTModeEnable 1<<20
#define PM3DownloadGlyphwidth 0xb658
#define PM3DownloadGlyphwidth_GlyphWidth(gw) ((gw)&0xffff)
#define PM3DownloadTarget 0xb650
#define PM3DownloadTarget_TagName(tag) ((tag)&0x1fff)
#define PM3GlyphData 0xb660
#define PM3GlyphPosition 0xb608
#define PM3GlyphPosition_XOffset(x) ((x)&0xffff)
#define PM3GlyphPosition_YOffset(y) (((y)&0xffff)<<16)
#define PM3Packed4Pixels 0xb668
#define PM3Packed8Pixels 0xb630
#define PM3Packed16Pixels 0xb638
#define PM3RectanglePosition 0xb600
#define PM3RectanglePosition_XOffset(x) ((x)&0xffff)
#define PM3RectanglePosition_YOffset(y) (((y)&0xffff)<<16)
#define PM3Render2D 0xb640
#define PM3Render2D_Width(w) ((w)&0x0fff)
#define PM3Render2D_Operation_Normal 0<<12
#define PM3Render2D_Operation_SyncOnHostData 1<<12
#define PM3Render2D_Operation_SyncOnBitMask 2<<12
#define PM3Render2D_Operation_PatchOrderRendering 3<<12
#define PM3Render2D_FBSourceReadEnable 1<<14
#define PM3Render2D_SpanOperation 1<<15
#define PM3Render2D_Height(h) (((h)&0x0fff)<<16)
#define PM3Render2D_XPositive 1<<28
#define PM3Render2D_YPositive 1<<29
#define PM3Render2D_AreaStippleEnable 1<<30
#define PM3Render2D_TextureEnable 1<<31
#define PM3Render2DGlyph 0xb648
#define PM3Render2DGlyph_Width(w) ((w)&0x7f)
#define PM3Render2DGlyph_Height(h) (((h)&0x7f)<<7)
#define PM3Render2DGlyph_XOffset(x) (((x)&0x1ff)<<14)
#define PM3Render2DGlyph_YOffset(y) (((y)&0x1ff)<<23)
#define PM3RenderPatchOffset 0xb610
#define PM3RenderPatchOffset_XOffset(x) ((x)&0xffff)
#define PM3RenderPatchOffset_YOffset(y) (((y)&0xffff)<<16)
#define PM3RLCount 0xb678
#define PM3RLCount_Count(c) ((c)&0x0fff)
#define PM3RLData 0xb670
/**********************************************
* GLINT Permedia3 Alias Register *
***********************************************/
#define PM3FillBackgroundColor 0x8330
#define PM3FillConfig2D0 0x8338
#define PM3FillConfig2D1 0x8360
#define PM3FillConfig2D_OpaqueSpan 1<<0
#define PM3FillConfig2D_MultiRXBlit 1<<1
#define PM3FillConfig2D_UserScissorEnable 1<<2
#define PM3FillConfig2D_FBDestReadEnable 1<<3
#define PM3FillConfig2D_AlphaBlendEnable 1<<4
#define PM3FillConfig2D_DitherEnable 1<<5
#define PM3FillConfig2D_ForegroundROPEnable 1<<6
#define PM3FillConfig2D_ForegroundROP(rop) (((rop)&0xf)<<7)
#define PM3FillConfig2D_BackgroundROPEnable 1<<11
#define PM3FillConfig2D_BackgroundROP(rop) (((rop)&0xf)<<12)
#define PM3FillConfig2D_UseConstantSource 1<<16
#define PM3FillConfig2D_FBWriteEnable 1<<17
#define PM3FillConfig2D_Blocking 1<<18
#define PM3FillConfig2D_ExternalSourceData 1<<19
#define PM3FillConfig2D_LUTModeEnable 1<<20
#define PM3FillFBDestReadBufferAddr 0x8310
#define PM3FillFBSourceReadBufferAddr 0x8308
#define PM3FillFBSourceReadBufferOffset 0x8340
#define PM3FillFBSourceReadBufferOffset_XOffset(x) ((x)&0xffff)
#define PM3FillFBSourceReadBufferOffset_YOffset(y) (((y)&0xffff)<<16)
#define PM3FillFBWriteBufferAddr 0x8300
#define PM3FillForegroundColor0 0x8328
#define PM3FillForegroundColor1 0x8358
#define PM3FillGlyphPosition 0x8368
#define PM3FillGlyphPosition_XOffset(x) ((x)&0xffff)
#define PM3FillGlyphPosition_YOffset(y) (((y)&0xffff)<<16)
#define PM3FillRectanglePosition 0x8348
#define PM3FillRectanglePosition_XOffset(x) ((x)&0xffff)
#define PM3FillRectanglePosition_YOffset(y) (((y)&0xffff)<<16)
#define PM3_REGS_SIZE 0x10000
#define PM3_MAX_PIXCLOCK 300000
/* a few more useful registers & regs value... */
#define PM3Sync 0x8c40
#define PM3Sync_Tag 0x188
#define PM3FilterMode 0x8c00
#define PM3FilterModeSync 0x400
#define PM3OutputFifo 0x2000
#define PM3StatisticMode 0x8c08
#define PM3AreaStippleMode 0x81a0
#define AreaStipplePattern0 (0x8200)
#define AreaStipplePattern1 (0x8208)
#define AreaStipplePattern2 (0x8210)
#define AreaStipplePattern3 (0x8218)
#define AreaStipplePattern4 (0x8220)
#define AreaStipplePattern5 (0x8228)
#define AreaStipplePattern6 (0x8230)
#define AreaStipplePattern7 (0x8238)
#define AreaStipplePattern8 (0x8240)
#define AreaStipplePattern9 (0x8248)
#define AreaStipplePattern10 (0x8250)
#define AreaStipplePattern11 (0x8258)
#define AreaStipplePattern12 (0x8260)
#define AreaStipplePattern13 (0x8268)
#define AreaStipplePattern14 (0x8270)
#define AreaStipplePattern15 (0x8278)
#define AreaStipplePattern16 (0x8280)
#define AreaStipplePattern17 (0x8288)
#define AreaStipplePattern18 (0x8290)
#define AreaStipplePattern19 (0x8298)
#define AreaStipplePattern20 (0x82a0)
#define AreaStipplePattern21 (0x82a8)
#define AreaStipplePattern22 (0x82b0)
#define AreaStipplePattern23 (0x82b8)
#define AreaStipplePattern24 (0x82c0)
#define AreaStipplePattern25 (0x82c8)
#define AreaStipplePattern26 (0x82d0)
#define AreaStipplePattern27 (0x82d8)
#define AreaStipplePattern28 (0x82eo)
#define AreaStipplePattern29 (0x82e8)
#define AreaStipplePattern30 (0x82f0)
#define AreaStipplePattern31 (0x82f8)
#define AreaStipplePattern_indexed(i) (0x8200 + ((i) * 0x8))
#define PM3DepthMode 0x89a0
#define PM3StencilMode 0x8988
#define PM3StencilData 0x8990
#define PM3TextureReadMode 0x8670
#define PM3FogMode 0x8690
#define PM3ChromaTestMode 0x8f18
#define PM3YUVMode 0x8f00
#define PM3BitMaskPattern 0x8068
/* ***************************** */
/* ***** pm3fb IOCTL const ***** */
/* ***************************** */
/* debug-only IOCTL */
#define PM3FBIO_CLEARMEMORY 0x504D3300 /* 'PM3\000' */
#define PM3FBIO_CLEARCMAP 0x504D3301 /* 'PM3\001' */
/* common use IOCTL */
#define PM3FBIO_RESETCHIP 0x504D33FF /* 'PM3\377' */
/* ***************************************** */
/* ***** pm3fb useful define and macro ***** */
/* ***************************************** */
/* kernel -specific definitions */
/* what kernel is this ? */
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)))
#define KERNEL_2_5
#endif
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)))
#define KERNEL_2_4
#endif
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)))
#define KERNEL_2_2
/* pci_resource_start, available in 2.2.18 */
#include <linux/kcomp.h>
#ifdef CONFIG_FB_OF
#define SUPPORT_FB_OF
#endif
#endif
#if (!defined(KERNEL_2_2)) && (!defined(KERNEL_2_4)) && (!defined(KERNEL_2_5))
#error "Only kernel 2.2.x, kernel 2.4.y and kernel 2.5.z might work"
#endif
/* not sure if/why it's needed. doesn't work without on my PowerMac... */
#ifdef __BIG_ENDIAN
#define MUST_BYTESWAP
#endif
/* for compatibility between 2.5, 2.4 and 2.2 */
#ifndef B_FREE
#define B_FREE -1
#endif
/* permedia3 -specific definitions */
#define PM3_SCALE_TO_CLOCK(pr, fe, po) ((2 * PM3_REF_CLOCK * fe) / (pr * (1 << (po))))
#define PICOS2KHZ(a) (1000000000UL/(a))
#define KHZ2PICOS(a) (1000000000UL/(a))
/* in case it's not in linux/pci.h */
#ifndef PCI_DEVICE_ID_3DLABS_PERMEDIA3
#define PCI_DEVICE_ID_3DLABS_PERMEDIA3 0x000a
#endif
/* max number of simultaneous board */
/* warning : make sure module array def's are coherent with PM3_MAX_BOARD */
#define PM3_MAX_BOARD 4
#define PM3_MAX_BOARD_MODULE_ARRAY_SHORT "1-4h"
#define PM3_MAX_BOARD_MODULE_ARRAY_STRING "1-4s"
/* max size of options */
#define PM3_OPTIONS_SIZE 256
/* max size of font name */
#define PM3_FONTNAME_SIZE 40
/* do we want accelerated console */
#define PM3FB_USE_ACCEL 1
/* useful ? */
#define CHAR_IS_NUM(a) ((((a) >= '0') && ((a) <= '9')) ? 1 : 0)
/* for driver debugging ONLY */
/* 0 = assert only, 1 = error, 2 = info, 3+ = verbose */
/* define PM3FB_MASTER_DEBUG 1 */
#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 3)
#define PM3FB_TRACE
#endif /* defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 3) */
#ifdef PM3FB_MASTER_DEBUG
#define DPRINTK(l,a,b...) do { if ((l) <= PM3FB_MASTER_DEBUG) printk("pm3fb: %s: " a, __FUNCTION__ , ## b); } while (0)
#define DASSERT(t,a,b...) do { if (!(t)) printk("pm3fb: _assert failed: %s: " a, __FUNCTION__ , ## b); } while (0)
#ifdef PM3FB_TRACE
#define DTRACE printk("pm3fb: _enter %s\n", __FUNCTION__)
#else /* PM3FB_TRACE */
#define DTRACE
#endif /* PM3FB_TRACE */
#else /* PM3FB_MASTER_DEBUG */
#define DPRINTK(l,a,b...)
#define DASSERT(t,a,b...)
#define DTRACE
#endif /* PM3FB_MASTER_DEBUG */
#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2)
#define PM3_SHOW_CUR_MODE pm3fb_show_cur_mode(l_fb_info)
#else
#define PM3_SHOW_CUR_MODE /* pm3fb_show_cur_mode() */
#endif
/* ******************************************** */
/* ***** A bunch of register-access macro ***** */
/* ******************************************** */
#ifdef KERNEL_2_2
#ifdef MUST_BYTESWAP /* we are writing big_endian to big_endian through a little_endian macro */
#define PM3_READ_REG(r) __swab32(readl((l_fb_info->vIOBase + r)))
#define PM3_WRITE_REG(r, v) writel(__swab32(v), (l_fb_info->vIOBase + r))
#else /* MUST_BYTESWAP */
#define PM3_WRITE_REG(r, v) writel(v, (l_fb_info->vIOBase + r))
#define PM3_READ_REG(r) readl((l_fb_info->vIOBase + r))
#endif /* MUST_BYTESWAP */
#endif /* KERNEL_2_2 */
#if (defined KERNEL_2_4) || (defined KERNEL_2_5) /* native-endian access */
#define PM3_WRITE_REG(r, v) fb_writel(v, (l_fb_info->vIOBase + r))
#define PM3_READ_REG(r) fb_readl((l_fb_info->vIOBase + r))
#endif /* KERNEL_2_4 or KERNEL_2_5 */
#define depth2bpp(d) ((d + 7L) & ~7L)
#define depth2ByPP(d) (depth2bpp(d) / 8)
#define depth_supported(d) ((d == 8) || (d == 12) || (d == 15) || (d == 16) || (d==32))
#define PM3_WAIT(n) \
do{ \
while(PM3_READ_REG(PM3InFIFOSpace)<(n)); \
} while(0)
#define PM3_DELAY(x) do { \
int delay = x; \
unsigned char tmp; \
while(delay--){tmp = PM3_READ_REG(PM3InFIFOSpace);}; \
} while(0)
#define PM3_SLOW_WRITE_REG(r,v) \
do{ \
DASSERT((l_fb_info->vIOBase != (unsigned char*)(-1)), "l_fb_info->vIOBase mapped in slow write\n"); \
mb(); \
PM3_WAIT(1); \
mb(); \
PM3_WRITE_REG(r,v); \
} while(0)
#define PM3_SET_INDEX(index) \
do{ \
PM3_SLOW_WRITE_REG(PM3RD_IndexHigh,(((index)>>8)&0xff)); \
PM3_SLOW_WRITE_REG(PM3RD_IndexLow,((index)&0xff)); \
} while(0)
#define PM3_WRITE_DAC_REG(r, v) \
do { \
DASSERT((l_fb_info->vIOBase != (unsigned char*)(-1)), "l_fb_info->vIOBase mapped in write dac reg\n"); \
PM3_SET_INDEX(r); \
mb(); \
PM3_WRITE_REG(PM3RD_IndexedData, v); \
} while (0)
/* next one is really a function, added as a macro to be consistent */
#define PM3_READ_DAC_REG(r) pm3fb_read_dac_reg(l_fb_info, r)
#define PM3_COLOR(c) \
do { \
if (l_fb_info->current_par->depth == 8) \
{ \
c = (c & 0xFF); \
c = c | (c << 8); \
} \
if ((l_fb_info->current_par->depth == 8) || (depth2bpp(l_fb_info->current_par->depth) == 16)) \
{ \
c = (c & 0xFFFF); \
c = c | (c << 16); \
} \
} while (0)
#endif PM3FB_H
/*
* linux/drivers/video/q40fb.c -- Q40 frame buffer device
*
* Copyright (C) 2001
*
* Richard Zidlicky <Richard.Zidlicky@stud.informatik.uni-erlangen.de>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
......@@ -9,181 +21,68 @@
#include <asm/uaccess.h>
#include <asm/setup.h>
#include <asm/segment.h>
#include <asm/system.h>
/*#include <asm/irq.h>*/
#include <asm/q40_master.h>
#include <linux/fb.h>
#include <linux/module.h>
#include <asm/pgtable.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb16.h>
#define FBIOSETSCROLLMODE 0x4611
#define Q40_PHYS_SCREEN_ADDR 0xFE800000
static u16 fbcon_cmap_cfb16[16];
static u32 pseudo_palette[17];
static struct fb_info fb_info;
static struct display display;
static struct fb_fix_screeninfo q40fb_fix __initdata = {
id: "Q40",
smem_len: 1024*1024,
type: FB_TYPE_PACKED_PIXELS,
visual: FB_VISUAL_TRUECOLOR,
line_length: 1024*2,
accel_flags: FB_ACCEL_NONE,
};
static struct fb_var_screeninfo q40fb_var __initdata = {
xres: 1024,
yres: 512,
xres_virtual: 1024,
yres_virtual: 512,
bits_per_pixel: 16,
red: {6, 5, 0},
green: {11, 5, 0},
blue: {0, 6, 0},
activate: FB_ACTIVATE_NOW,
height: 230,
width: 300,
vmode: FB_VMODE_NONINTERLACED,
};
/* frame buffer operations */
int q40fb_init(void);
static int q40fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
static int q40fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int q40fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int q40fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
struct fb_info *info);
static int q40fb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
struct fb_info *info);
static int q40fb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
const struct fb_info *info);
unsigned blue, unsigned transp,
struct fb_info *info);
static int q40con_switch(int con, struct fb_info *info);
static int q40con_updatevar(int con, struct fb_info *info);
static void q40fb_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 q40fb_ops = {
owner: THIS_MODULE,
fb_get_fix: q40fb_get_fix,
fb_get_var: q40fb_get_var,
fb_set_var: q40fb_set_var,
fb_get_cmap: q40fb_get_cmap,
fb_set_cmap: q40fb_set_cmap,
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_setcolreg: q40fb_setcolreg,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
};
static char q40fb_name[]="Q40";
static int q40fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id,"Q40");
fix->smem_start = info->screen_base;
fix->smem_len=1024*1024;
fix->type=FB_TYPE_PACKED_PIXELS;
fix->type_aux=0;
fix->visual=FB_VISUAL_TRUECOLOR; /* good approximation so far ..*/;
fix->xpanstep=0;
fix->ypanstep=0;
fix->ywrapstep=0;
fix->line_length=1024*2;
/* no mmio,accel ...*/
return 0;
}
static int q40fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
memset(var, 0, sizeof(struct fb_var_screeninfo));
var->xres=1024;
var->yres=512;
var->xres_virtual=1024;
var->yres_virtual=512;
var->xoffset=0;
var->yoffset=0;
var->bits_per_pixel=16;
var->grayscale=0;
var->nonstd=0;
var->activate=FB_ACTIVATE_NOW;
var->height=230; /* approx for my 17" monitor, more important */
var->width=300; /* than the absolute values is the unusual aspect ratio*/
var->red.offset=6; /*6*/
var->red.length=5;
var->green.offset=11; /*11*/
var->green.length=5;
var->blue.offset=0;
var->blue.length=6;
var->transp.length=0;
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 q40fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
if(var->xres!=1024)
return -EINVAL;
if(var->yres!=512)
return -EINVAL;
if(var->xres_virtual!=1024)
return -EINVAL;
if(var->yres_virtual!=512)
return -EINVAL;
if(var->xoffset!=0)
return -EINVAL;
if(var->yoffset!=0)
return -EINVAL;
if(var->bits_per_pixel!=16)
return -EINVAL;
if(var->grayscale!=0)
return -EINVAL;
if(var->nonstd!=0)
return -EINVAL;
if(var->activate!=FB_ACTIVATE_NOW)
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 q40_getcolreg(unsigned regno, unsigned *red, unsigned *green,
unsigned *blue, unsigned *transp,
struct fb_info *info)
{
/*
* Read a single color register and split it into colors/transparent.
* The return values must have a 16 bit magnitude.
* Return != 0 for invalid regno.
*/
if (regno>=16) return 1;
*transp=0;
*green = ((fbcon_cmap_cfb16[regno]>>11) & 31)<<11;
*red = ((fbcon_cmap_cfb16[regno]>>6) & 31)<<11;
*blue = ((fbcon_cmap_cfb16[regno]) & 63)<<10;
return 0;
}
static int q40fb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
const struct fb_info *info)
unsigned blue, unsigned transp,
struct fb_info *info)
{
/*
* Set a single color register. The values supplied have a 16 bit
......@@ -191,142 +90,54 @@ static int q40fb_setcolreg(unsigned regno, unsigned red, unsigned green,
* Return != 0 for invalid regno.
*/
red>>=11;
green>>=11;
blue>>=10;
red>>=11;
green>>=11;
blue>>=10;
if (regno < 16) {
fbcon_cmap_cfb16[regno] = ((red & 31) <<6) |
((green & 31) << 11) |
(blue & 63);
info->pseudo_palette[regno] = ((red & 31) <<6) |
((green & 31) << 11) |
(blue & 63);
}
return 0;
}
static int q40fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
#if 1
if (con == info->currcon) /* current console? */
return fb_get_cmap(cmap, kspc, q40_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
cmap, kspc ? 0 : 2);
return 0;
#else
printk(KERN_ERR "get cmap not supported\n");
return -EINVAL;
#endif
}
static int q40fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
#if 1
int err;
if (!fb_display[con].cmap.len) { /* no colormap allocated? */
if ((err = fb_alloc_cmap(&fb_display[con].cmap,
1<<fb_display[con].var.bits_per_pixel,
0)))
return err;
}
if (con == info->currcon) /* current console? */
return fb_set_cmap(cmap, kspc, info);
else
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
#else
printk(KERN_ERR "set cmap not supported\n");
return -EINVAL;
#endif
}
static void q40fb_set_disp(int con, struct fb_info *info)
{
struct fb_fix_screeninfo fix;
struct display *display;
q40fb_get_fix(&fix, con, info);
if (con>=0)
display = &fb_display[con];
else
display = &disp[0];
if (con<0) 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 = 0;
display->inverse = 0;
display->line_length = fix.line_length;
display->scrollmode = SCROLL_YREDRAW;
#ifdef FBCON_HAS_CFB16
display->dispsw = &fbcon_cfb16;
disp->dispsw_data = fbcon_cmap_cfb16;
#else
display->dispsw = &fbcon_dummy;
#endif
}
int __init q40fb_init(void)
int q40fb_init(void)
{
if ( !MACH_IS_Q40)
return -ENXIO;
#if 0
fb_info.screen_base = kernel_map(Q40_PHYS_SCREEN_ADDR, 1024*1024,
KERNELMAP_NO_COPYBACK, NULL);
#else
fb_info.screen_base = Q40_PHYS_SCREEN_ADDR; /* mapped in q40/config.c */
#endif
fb_info.changevar=NULL;
strcpy(&fb_info.modename[0],q40fb_name);
fb_info.fontname[0]=0;
fb_info.disp=disp;
fb_info.currcon = -1;
fb_info.switch_con=&q40con_switch;
fb_info.updatevar=&q40con_updatevar;
/* mapped in q40/config.c */
q40fb_fix.smem_start = Q40_PHYS_SCREEN_ADDR;
fb_info.var = q40fb_var;
fb_info.fix = q40fb_fix;
fb_info.node = NODEV;
fb_info.fbops = &q40fb_ops;
fb_info.flags = FBINFO_FLAG_DEFAULT; /* not as module for now */
fb_info.pseudo_palette = pseudo_palette;
fb_info.screen_base = (char *) q40fb_fix.smem_start;
/* The below feilds will go away !!!! */
fb_info.currcon = -1;
strcpy(fb_info.modename, fb_info.fix.id);
fb_info.disp = &display;
fb_info.switch_con = gen_switch;
fb_info.updatevar = gen_update_var;
fb_alloc_cmap(&fb_info.cmap, 16, 0);
gen_set_disp(-1, &fb_info);
master_outb(3,DISPLAY_CONTROL_REG);
q40fb_get_var(&disp[0].var, 0, &fb_info);
q40fb_set_disp(-1, &fb_info);
master_outb(3, DISPLAY_CONTROL_REG);
if (register_framebuffer(&fb_info) < 0) {
printk(KERN_ERR "unable to register Q40 frame buffer\n");
printk(KERN_ERR "Unable to register Q40 frame buffer\n");
return -EINVAL;
}
printk(KERN_INFO "fb%d: Q40 frame buffer alive and kicking !\n",
GET_FB_IDX(fb_info.node));
return 0;
}
static int q40con_switch(int con, struct fb_info *info)
{
info->currcon=con;
return 0;
}
static int q40con_updatevar(int con, struct fb_info *info)
{
return 0;
}
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL");
/*
* linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device
*
* Modified to new api Jan 2001 by James Simmons (jsimmons@transvirtual.com)
*
* Created 28 Dec 1997 by Geert Uytterhoeven
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*
* I have started rewriting this driver as a example of the upcoming new API
* The primary goal is to remove the console code from fbdev and place it
* into fbcon.c. This reduces the code and makes writing a new fbdev driver
* easy since the author doesn't need to worry about console internals. It
* also allows the ability to run fbdev without a console/tty system on top
* of it.
*
* First the roles of struct fb_info and struct display have changed. Struct
* display will go away. The way the the new framebuffer console code will
* work is that it will act to translate data about the tty/console in
* struct vc_data to data in a device independent way in struct fb_info. Then
* various functions in struct fb_ops will be called to store the device
* dependent state in the par field in struct fb_info and to change the
* hardware to that state. This allows a very clean seperation of the fbdev
* layer from the console layer. It also allows one to use fbdev on its own
* which is a bounus for embedded devices. The reason this approach works is
* for each framebuffer device when used as a tty/console device is allocated
* a set of virtual terminals to it. Only one virtual terminal can be active
* per framebuffer device. We already have all the data we need in struct
* vc_data so why store a bunch of colormaps and other fbdev specific data
* per virtual terminal.
*
* As you can see doing this makes the con parameter pretty much useless
* for struct fb_ops functions, as it should be. Also having struct
* fb_var_screeninfo and other data in fb_info pretty much eliminates the
* need for get_fix and get_var. Once all drivers use the fix, var, and cmap
* fbcon can be written around these fields. This will also eliminate the
* need to regenerate struct fb_var_screeninfo, struct fb_fix_screeninfo
* struct fb_cmap every time get_var, get_fix, get_cmap functions are called
* as many drivers do now.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*/
#include <linux/module.h>
......@@ -19,9 +53,6 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <video/fbcon.h>
/*
* This is just simple sample code.
*
......@@ -29,310 +60,410 @@
* Even less warranty that it actually works :-)
*/
/*
* If your driver supports multiple boards, you should make the
* below data types arrays, or allocate them dynamically (using kmalloc()).
*/
/*
* This structure defines the hardware state of the graphics card. Normally
* you place this in a header file in linux/include/video. This file usually
* also includes register information. That allows other driver subsystems
* and userland applications the ability to use the same header file to
* avoid duplicate work and easy porting of software.
*/
struct xxx_par;
struct xxxfb_info {
/*
* Choose _one_ of the two alternatives:
*
* 1. Use the generic frame buffer operations (fbgen_*).
*/
struct fb_info_gen gen;
/*
* 2. Provide your own frame buffer operations.
*/
struct fb_info info;
/* Here starts the frame buffer device dependent part */
/* You can use this to store e.g. the board number if you support */
/* multiple boards */
/*
* Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
* if we don't use modedb. If we do use modedb see xxxfb_init how to use it
* to get a fb_var_screeninfo. Otherwise define a default var as well.
*/
static struct fb_fix_screeninfo xxxfb_fix __initdata = {
id: "FB's name",
type: FB_TYPE_PACKED_PIXELS,
visual: FB_VISUAL_PSEUDOCOLOR,
xpanstep: 1,
ypanstep: 1,
ywrapstep: 1,
accel: FB_ACCEL_NONE,
};
struct xxxfb_par {
/*
* The hardware specific data in this structure uniquely defines a video
* mode.
*
* If your hardware supports only one video mode, you can leave it empty.
* Modern graphical hardware not only supports pipelines but some
* also support multiple monitors where each display can have its
* its own unique data. In this case each display could be
* represented by a seperate framebuffer device thus a seperate
* struct fb_info. Now the struct xxx_par represents the graphics
* hardware state thus only one exist per card. In this case the
* struct xxx_par for each graphics card would be shared between
* every struct fb_info that represents a framebuffer on that card.
* This allows when one display changes it video resolution (info->var)
* the other displays know instantly. Each display can always be
* aware of the entire hardware state that affects it because they share
* the same xxx_par struct. The other side of the coin is multiple
* graphics cards that pass data around until it is finally displayed
* on one monitor. Such examples are the voodoo 1 cards and high end
* NUMA graphics servers. For this case we have a bunch of pars, each
* one that represents a graphics state, that belong to one struct
* fb_info. Their you would want to have *par point to a array of device
* states and have each struct fb_ops function deal with all those
* states. I hope this covers every possible hardware design. If not
* feel free to send your ideas at jsimmons@users.sf.net
*/
};
/*
* If your driver supports multiple boards, you should make these arrays,
* or allocate them dynamically (using kmalloc()).
* If your driver supports multiple boards or it supports multiple
* framebuffers, you should make these arrays, or allocate them
* dynamically (using kmalloc()).
*/
static struct fb_info info;
/*
* Each one represents the a state of the hardware. Most hardware have
* just one hardware state. These here represent the default state(s).
*/
static struct xxx_par __initdata current_par;
static struct xxxfb_info fb_info;
static struct xxxfb_par current_par;
static int current_par_valid = 0;
/* To go away in the near future */
static struct display disp;
static struct fb_var_screeninfo default_var;
static int inverse = 0;
int xxxfb_init(void);
int xxxfb_setup(char*);
/* ------------------- chipset specific functions -------------------------- */
static void xxx_detect(void)
/**
* xxxfb_check_var - Optional function. Validates a var passed in.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
*
* Checks to see if the hardware supports the state requested by
* var passed in. This function does not alter the hardware state!!!
* This means the data stored in struct fb_info and struct xxx_par do
* not change. This includes the var inside of struct fb_info.
* Do NOT change these. This function can be called on its own if we
* intent to only test a mode and not actually set it. The stuff in
* modedb.c is a example of this. If the var passed in is slightly
* off by what the hardware can support then we alter the var PASSED in
* to what we can do. If the hardware doesn't support mode change
* a -EINVAL will be returned by the upper layers. You don't need to
* implement this function then.
*
* Returns negative errno on error, or zero on success.
*/
static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
/*
* This function should detect the current video mode settings and store
* it as the default video mode
*/
struct xxxfb_par par;
const struct xxx_par *par = (const struct xxx_par *) info->par;
/* ... */
xxx_get_par(&par);
xxx_encode_var(&default_var, &par);
return 0;
}
static int xxx_encode_fix(struct fb_fix_screeninfo *fix, struct xxxfb_par *par,
const struct fb_info *info)
/**
* xxxfb_set_par - Optional function. Alters the hardware state.
* @info: frame buffer structure that represents a single frame buffer
*
* Using the fb_var_screeninfo in fb_info we set the resolution of the
* this particular framebuffer. This function alters the par AND the
* fb_fix_screeninfo stored in fb_info. It doesn't not alter var in
* fb_info since we are using that data. This means we depend on the
* data in var inside fb_info to be supported by the hardware.
* xxxfb_check_var is always called before xxxfb_set_par to ensure this.
*
*/
static int xxxfb_set_par(struct fb_info *info)
{
/*
* This function should fill in the 'fix' structure based on the values
* in the `par' structure.
*/
struct xxx_par *par = (struct xxx_par *) info->par;
/* ... */
return 0;
return 0;
}
static int xxx_decode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par,
const struct fb_info *info)
/**
* xxxfb_setcolreg - Optional function. Sets a color register.
* @regno: boolean, 0 copy local, 1 get_user() function
* @red: frame buffer colormap structure
* @green: The green value which can be up to 16 bits wide
* @blue: The blue value which can be up to 16 bits wide.
* @transp: If supported the alpha value which can be up to 16 bits wide.
* @info: frame buffer info structure
*
* Set a single color register. The values supplied have a 16 bit
* magnitude which needs to be scaled in this function for the hardware.
* Things to take into consideration are how many color registers, if
* any, are supported with the current color visual. With truecolor mode
* no color palettes are supported. Here a psuedo palette is created
* which we store the value in pseudo_palette in struct fb_info. For
* pseudocolor mode we have a limited color palette. To deal with this
* we can program what color is displayed for a particular pixel value.
* DirectColor is similar in that we can program each color field. If
* we have a static colormap we don't need to implement this function.
*
* Returns negative errno on error, or zero on success.
*/
static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
const struct fb_info *info)
{
if (regno >= 256) /* no. of hw registers */
return 1;
/*
* Get the video params out of 'var'. If a value doesn't fit, round it up,
* if it's too big, return -EINVAL.
*
* Suggestion: Round up in the following order: bits_per_pixel, xres,
* yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
* bitfields, horizontal timing, vertical timing.
* Program hardware... do anything you want with transp
*/
/* ... */
/* pixclock in picos, htotal in pixels, vtotal in scanlines */
if (!fbmon_valid_timings(pixclock, htotal, vtotal, info))
return -EINVAL;
return 0;
}
/* grayscale works only partially under directcolor */
if (info->var.grayscale) {
/* grayscale = 0.30*R + 0.59*G + 0.11*B */
red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
}
static int xxx_encode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par,
const struct fb_info *info)
{
/*
* Fill the 'var' structure based on the values in 'par' and maybe other
* values read out of the hardware.
/* Directcolor:
* var->{color}.offset contains start of bitfield
* var->{color}.length contains length of bitfield
* {hardwarespecific} contains width of DAC
* cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
* RAMDAC[X] is programmed to (red, green, blue)
*
* Pseudocolor:
* uses offset = 0 && length = DAC register width.
* var->{color}.offset is 0
* var->{color}.length contains widht of DAC
* cmap is not used
* DAC[X] is programmed to (red, green, blue)
* Truecolor:
* does not use RAMDAC (usually has 3 of them).
* var->{color}.offset contains start of bitfield
* var->{color}.length contains length of bitfield
* cmap is programmed to (red << red.offset) | (green << green.offset) |
* (blue << blue.offset) | (transp << transp.offset)
* RAMDAC does not exist
*/
#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
switch (info->fix.visual) {
case FB_VISUAL_TRUECOLOR:
case FB_VISUAL_PSEUDOCOLOR:
red = CNVT_TOHW(red, info->var.red.length);
green = CNVT_TOHW(green, info->var.green.length);
blue = CNVT_TOHW(blue, info->var.blue.length);
transp = CNVT_TOHW(transp, info->var.transp.length);
break;
case FB_VISUAL_DIRECTCOLOR:
/* example here assumes 8 bit DAC. Might be different
* for your hardware */
red = CNVT_TOHW(red, 8);
green = CNVT_TOHW(green, 8);
blue = CNVT_TOHW(blue, 8);
/* hey, there is bug in transp handling... */
transp = CNVT_TOHW(transp, 8);
break;
}
#undef CNVT_TOHW
/* Truecolor has hardware independent palette */
if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
u32 v;
if (regno >= 16)
return 1;
v = (red << info->var.red.offset) |
(green << info->var.green.offset) |
(blue << info->var.blue.offset) |
(transp << info->var.transp.offset);
switch (info->var.bits_per_pixel) {
case 8:
/* Yes some hand held devices have this. */
((u8*)(info->pseudo_palette))[regno] = v;
break;
case 16:
((u16*)(info->pseudo_palette))[regno] = v;
break;
case 24:
case 32:
((u32*)(info->pseudo_palette))[regno] = v;
break;
}
return 0;
}
/* ... */
return 0;
}
static void xxx_get_par(struct xxxfb_par *par, const struct fb_info *info)
{
/*
* Fill the hardware's 'par' structure.
*/
if (current_par_valid)
*par = current_par;
else {
/* ... */
}
}
static void xxx_set_par(struct xxxfb_par *par, const struct fb_info *info)
/**
* xxxfb_pan_display - NOT a required function. Pans the display.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
*
* Pan (or wrap, depending on the `vmode' field) the display using the
* `xoffset' and `yoffset' fields of the `var' structure.
* If the values don't fit, return -EINVAL.
*
* Returns negative errno on error, or zero on success.
*
*/
static int xxxfb_pan_display(struct fb_var_screeninfo *var,
const struct fb_info *info)
{
/*
* Set the hardware according to 'par'.
*/
current_par = *par;
current_par_valid = 1;
/* ... */
return 0;
}
static int xxx_getcolreg(unsigned regno, unsigned *red, unsigned *green,
unsigned *blue, unsigned *transp,
const struct fb_info *info)
/**
* xxxfb_blank - NOT a required function. Blanks the display.
* @blank_mode: the blank mode we want.
* @info: frame buffer structure that represents a single frame buffer
*
* Blank the screen if blank_mode != 0, else unblank. Return 0 if
* blanking succeeded, != 0 if un-/blanking failed due to e.g. a
* video mode which doesn't support it. Implements VESA suspend
* and powerdown modes on hardware that supports disabling hsync/vsync:
* blank_mode == 2: suspend vsync
* blank_mode == 3: suspend hsync
* blank_mode == 4: powerdown
*
* Returns negative errno on error, or zero on success.
*
*/
static int xxxfb_blank(int blank_mode, const struct fb_info *info)
{
/*
* Read a single color register and split it into colors/transparent.
* The return values must have a 16 bit magnitude.
* Return != 0 for invalid regno.
*/
/* ... */
return 0;
}
static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
const struct fb_info *info)
{
/*
* Set a single color register. The values supplied have a 16 bit
* magnitude.
* Return != 0 for invalid regno.
*/
/* ------------ Accelerated Functions --------------------- */
if (regno < 16) {
/*
* Make the first 16 colors of the palette available to fbcon
*/
if (is_cfb15) /* RGB 555 */
...fbcon_cmap.cfb16[regno] = ((red & 0xf800) >> 1) |
((green & 0xf800) >> 6) |
((blue & 0xf800) >> 11);
if (is_cfb16) /* RGB 565 */
...fbcon_cmap.cfb16[regno] = (red & 0xf800) |
((green & 0xfc00) >> 5) |
((blue & 0xf800) >> 11);
if (is_cfb24) /* RGB 888 */
...fbcon_cmap.cfb24[regno] = ((red & 0xff00) << 8) |
(green & 0xff00) |
((blue & 0xff00) >> 8);
if (is_cfb32) /* RGBA 8888 */
...fbcon_cmap.cfb32[regno] = ((red & 0xff00) << 16) |
((green & 0xff00) << 8) |
(blue & 0xff00) |
((transp & 0xff00) >> 8);
}
/* ... */
return 0;
}
/*
* We provide our own functions if we have hardware acceleration
* or non packed pixel format layouts. If we have no hardware
* acceleration, we use a generic unaccelerated function. If using
* a pack pixel format just use the functions in cfb*.c. Each file
* has one of the three different accel functions we support. You
* can use these functions as fallbacks if hardware unsupported
* action is requested. Also if you have non pack pixel modes and
* non accelerated cards you have to provide your own functions.
*/
static int xxx_pan_display(struct fb_var_screeninfo *var,
struct xxxfb_par *par, const struct fb_info *info)
/**
* xxxfb_fillrect - REQUIRED function. Can use generic routines if
* non acclerated hardware and packed pixel based.
* Draws a rectangle on the screen.
*
* @info: frame buffer structure that represents a single frame buffer
* @x1: The x and y corrdinates of the upper left hand corner of the
* @y1: area we want to draw to.
* @width: How wide the rectangle is we want to draw.
* @height: How tall the rectangle is we want to draw.
* @color: The color to fill in the rectangle with.
* @rop: The rater operation. We can draw the rectangle with a COPY
* of XOR which provides erasing effect.
*
* This drawing operation places/removes a retangle on the screen
* depending on the rastering operation with the value of color which
* is in the current color depth format.
*/
void xxxfb_fillrect(struct fb_info *p, struct fb_fillrect *region)
{
/*
* Pan (or wrap, depending on the `vmode' field) the display using the
* `xoffset' and `yoffset' fields of the `var' structure.
* If the values don't fit, return -EINVAL.
*/
/* ... */
return 0;
}
static int xxx_blank(int blank_mode, const struct fb_info *info)
/**
* xxxfb_copyarea - REQUIRED function. Can use generic routines if
* non acclerated hardware and packed pixel based.
* Copies on area of the screen to another area.
*
* @info: frame buffer structure that represents a single frame buffer
* @sx: The x and y corrdinates of the upper left hand corner of the
* @sy: source area on the screen.
* @width: How wide the rectangle is we want to copy.
* @height: How tall the rectangle is we want to copy.
* @dx: The x and y coordinates of the destination area on the screen.
*
* This drawing operation copies a rectangular area from one area of the
* screen to another area.
*/
void xxxfb_copyarea(struct fb_info *p, struct fb_copyarea *area)
{
/*
* Blank the screen if blank_mode != 0, else unblank. If blank == NULL
* then the caller blanks by setting the CLUT (Color Look Up Table) to all
* black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
* to e.g. a video mode which doesn't support it. Implements VESA suspend
* and powerdown modes on hardware that supports disabling hsync/vsync:
* blank_mode == 2: suspend vsync
* blank_mode == 3: suspend hsync
* blank_mode == 4: powerdown
*/
/* ... */
return 0;
}
static void xxx_set_disp(const void *par, struct display *disp,
struct fb_info_gen *info)
/**
* xxxfb_imageblit - REQUIRED function. Can use generic routines if
* non acclerated hardware and packed pixel based.
* Copies a image from system memory to the screen.
*
* @info: frame buffer structure that represents a single frame buffer
* @image: structure defining the image.
*
* This drawing operation draws a image on the screen. It can be a
* mono image (needed for font handling) or a color image (needed for
* tux).
*/
void xxxfb_imageblit(struct fb_info *p, struct fb_image *image)
{
/*
* Fill in a pointer with the virtual address of the mapped frame buffer.
* Fill in a pointer to appropriate low level text console operations (and
* optionally a pointer to help data) for the video mode `par' of your
* video hardware. These can be generic software routines, or hardware
* accelerated routines specifically tailored for your hardware.
* If you don't have any appropriate operations, you must fill in a
* pointer to dummy operations, and there will be no text output.
*/
#ifdef FBCON_HAS_CFB8
if (is_cfb8) {
disp->dispsw = fbcon_cfb8;
} else
#endif
#ifdef FBCON_HAS_CFB16
if (is_cfb16) {
disp->dispsw = fbcon_cfb16;
disp->dispsw_data = ...fbcon_cmap.cfb16; /* console palette */
} else
#endif
#ifdef FBCON_HAS_CFB24
if (is_cfb24) {
disp->dispsw = fbcon_cfb24;
disp->dispsw_data = ...fbcon_cmap.cfb24; /* console palette */
} else
#endif
#ifdef FBCON_HAS_CFB32
if (is_cfb32) {
disp->dispsw = fbcon_cfb32;
disp->dispsw_data = ...fbcon_cmap.cfb32; /* console palette */
} else
#endif
disp->dispsw = &fbcon_dummy;
}
/* ------------ Interfaces to hardware functions ------------ */
struct fbgen_hwswitch xxx_switch = {
xxx_detect, xxx_encode_fix, xxx_decode_var, xxx_encode_var, xxx_get_par,
xxx_set_par, xxx_getcolreg, xxx_pan_display, xxx_blank,
xxx_set_disp
};
/* ------------ Hardware Independent Functions ------------ */
/*
* Initialization
*/
int __init xxxfb_init(void)
{
fb_info.gen.fbhw = &xxx_switch;
fb_info.gen.fbhw->detect();
strcpy(fb_info.gen.info.modename, "XXX");
fb_info.gen.info.changevar = NULL;
fb_info.gen.info.node = NODEV;
fb_info.gen.info.fbops = &xxxfb_ops;
fb_info.gen.info.screen_base = virtual_frame_buffer_address;
fb_info.gen.info.disp = &disp;
fb_info.gen.info.currcon = -1;
fb_info.gen.info.switch_con = &xxxfb_switch;
fb_info.gen.info.updatevar = &xxxfb_update_var;
fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
/* This should give a reasonable default video mode */
fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
fbgen_set_disp(-1, &fb_info.gen);
do_install_cmap(0, &fb_info.gen);
if (register_framebuffer(&fb_info.gen.info) < 0)
return -EINVAL;
printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node),
fb_info.gen.info.modename);
int cmap_len, retval;
/*
* Here we set the screen_base to the vitrual memory address
* for the framebuffer. Usually we obtain the resource address
* from the bus layer and then translate it to virtual memory
* space via ioremap. Consult ioport.h.
*/
info.screen_base = framebuffer_virtual_memory;
info.node = NODEV;
info.fbops = &xxxfb_ops;
info.fix = xxxfb_fix;
info.pseudo_palette = pseudo_palette;
info.flags = FBINFO_FLAG_DEFAULT;
info.par = current_par;
/* The following has to be set but in th efuture will go away */
strcpy(info.modename, xxxfb_fix.id);
info.changevar = NULL;
info.currcon = -1;
info.disp = &disp;
info.switch_con = gen_switch;
info.updatevar = gen_update_var;
/* uncomment this if your driver cannot be unloaded */
/* MOD_INC_USE_COUNT; */
/*
* This should give a reasonable default video mode. The following is
* done when we can set a video mode.
*/
if (!mode_option)
mode_option = "640x480@60";
retval = fb_find_mode(&info.var, &info, mode_option, NULL, 0, NULL, 8);
if (!retval || retval == 4)
return -EINVAL;
/* This has to been done !!! */
fb_alloc_cmap(&info.cmap, cmap_len, 0);
/*
* The following is done in the case of having hardware with a static
* mode. If we are setting the mode ourselves we don't call this.
*/
info.var = xxxfb_var;
gen_set_disp(-1, &fb_info);
if (register_framebuffer(&info) < 0)
return -EINVAL;
printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(info.node),
info.fix.id);
return 0;
}
/*
* Cleanup
*/
void xxxfb_cleanup(struct fb_info *info)
static void __exit xxxfb_cleanup(void)
{
/*
* If your driver supports multiple boards, you should unregister and
......@@ -343,11 +474,14 @@ void xxxfb_cleanup(struct fb_info *info)
/* ... */
}
/*
* Setup
*/
/*
* Only necessary if your driver takes special options,
* otherwise we fall back on the generic fb_setup().
*/
int __init xxxfb_setup(char *options)
{
/* Parse user speficied options (`video=xxxfb:') */
......@@ -356,7 +490,6 @@ int __init xxxfb_setup(char *options)
/* ------------------------------------------------------------------------- */
/*
* Frame buffer operations
*/
......@@ -373,28 +506,29 @@ static int xxxfb_release(const struct fb_info *info, int user)
return 0;
}
/*
* In most cases the `generic' routines (fbgen_*) should be satisfactory.
* However, you're free to fill in your own replacements.
*/
static struct fb_ops xxxfb_ops = {
owner: THIS_MODULE,
fb_open: xxxfb_open, /* only if you need it to do something */
fb_release: xxxfb_release, /* only if you need it to do something */
fb_get_fix: fbgen_get_fix,
fb_get_var: fbgen_get_var,
fb_set_var: fbgen_set_var,
fb_get_cmap: fbgen_get_cmap,
/* Stuff to go away. Use generic functions for now */
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: xxxfb_check_var,
fb_set_par: xxxfb_set_par, /* optional */
fb_setcolreg: xxxfb_setcolreg,
fb_pan_display: fbgen_pan_display,
fb_blank: fbgen_blank,
fb_ioctl: xxxfb_ioctl, /* optional */
fb_blank: xxxfb_blank, /* optional */
fb_pan_display: xxxfb_pan_display, /* optional */
fb_fillrect: xxxfb_fillrect,
fb_copyarea: xxxfb_copyarea,
fb_imageblit: xxxfb_imageblit,
fb_ioctl: xxxfb_ioctl, /* optional */
fb_mmap: xxxfb_mmap, /* optional */
};
/* ------------------------------------------------------------------------- */
......@@ -403,14 +537,8 @@ static struct fb_ops xxxfb_ops = {
*/
#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
{
return xxxfb_init();
}
module_init(xxxfb_init);
#endif
module_exit(xxxfb_cleanup);
void cleanup_module(void)
{
xxxfb_cleanup(void);
}
#endif /* MODULE */
MODULE_LICENSE("GPL");
/*
* Frame buffer driver for Trident Blade and Image series
*
* Copyright 2001,2002 - Jani Monoses <jani@astechnix.ro>
*
* $Id: tridentfb.c,v 1.3 2002/02/25 20:09:41 marcelo Exp $
*
* CREDITS:(in order of appearance)
* skeletonfb.c by Geert Uytterhoeven and other fb code in drivers/video
* Special thanks ;) to Mattia Crivellini <tia@mclink.it>
* much inspired by the XFree86 4.1.0 Trident driver sources by Alan Hourihane
* the FreeVGA project
* Francesco Salvestrini <salvestrini@users.sf.net> XP support,code,suggestions
* NOTES:
* Tested on Compaq Presario 12XL300 with CyberBladei1
* Tested on Toshiba 1800-514 with CyberBladeXPAi1
* No monitors were harmed during the writing of this driver
* TODO:
* timing value tweaking so it looks good on every monitor in every mode
* test text acceleration for the Image series
* test DPMS stuff
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
#include <video/fbcon-cfb24.h>
#include <video/fbcon-cfb32.h>
#include "tridentfb.h"
#define VERSION "0.6.9"
struct tridentfb_par {
struct fb_var_screeninfo var;
int bpp;
int hres;
int vres;
int linelength;
int vclk; //in MHz
int vtotal;
int vdispend;
int vsyncstart;
int vsyncend;
int vblankstart;
int vblankend;
int htotal;
int hdispend;
int hsyncstart;
int hsyncend;
int hblankstart;
int hblankend;
};
struct tridentfb_info {
struct fb_info_gen gen;
unsigned int fbmem_virt; //framebuffer virtual memory address
unsigned int fbmem; //framebuffer physical memory address
unsigned int memsize; //size of fbmem
unsigned int io; //io space address
unsigned int io_virt; //iospace virtual memory address
unsigned int nativex; //flat panel xres
struct tridentfb_par currentmode;
};
static struct fb_ops tridentfb_ops;
static struct tridentfb_info fb_info;
static struct display disp;
static struct { unsigned char red,green,blue,transp; } palette[256];
static struct fb_var_screeninfo default_var;
static char * tridentfb_name = "Trident";
static int family;
static int pci_id;
static int defaultaccel;
static int displaytype;
static int pseudo_pal[16];
/* defaults which are normally overriden by user values */
/* video mode */
static char * mode = "640x480";
static int bpp = 8;
static int noaccel;
static int accel;
static int center;
static int stretch;
static int fp;
static int crt;
static int memsize;
static int memdiff;
static int nativex;
MODULE_PARM(mode,"s");
MODULE_PARM(bpp,"i");
MODULE_PARM(center,"i");
MODULE_PARM(stretch,"i");
MODULE_PARM(noaccel,"i");
MODULE_PARM(accel,"i");
MODULE_PARM(memsize,"i");
MODULE_PARM(memdiff,"i");
MODULE_PARM(nativex,"i");
MODULE_PARM(fp,"i");
MODULE_PARM(crt,"i");
#define CRT 0x3D0 //CRTC registers offset for color display
#ifndef TRIDENT_MMIO
#define TRIDENT_MMIO 1
#endif
#if TRIDENT_MMIO
#define t_outb(val,reg) writeb(val,fb_info.io_virt + reg)
#define t_inb(reg) readb(fb_info.io_virt + reg)
#else
#define t_outb(val,reg) outb(val,reg)
#define t_inb(reg) inb(reg)
#endif
static struct accel_switch {
void (*init_accel)(int,int);
void (*wait_engine)(void);
void (*fill_rect)(int,int,int,int,int);
void (*copy_rect)(int,int,int,int,int,int);
} *acc;
#define writemmr(r,v) writel(v, fb_info.io_virt + r)
#define readmmr(r) readl(fb_info.io_virt + r)
/*
* Blade specific acceleration.Not XP's though those are
* unaccelerated.
*/
#define point(x,y) ((y)<<16|(x))
#define STA 0x2120
#define CMD 0x2144
#define ROP 0x2148
#define CLR 0x2160
#define SR1 0x2100
#define SR2 0x2104
#define DR1 0x2108
#define DR2 0x210C
#define REPL(x) x = x | x<<16
#define ROP_S 0xCC
static void blade_init_accel(int pitch,int bpp)
{
int v1 = (pitch>>3)<<20;
int tmp = 0,v2;
switch (bpp) {
case 8:tmp = 0;break;
case 15:tmp = 5;break;
case 16:tmp = 1;break;
case 24:
case 32:tmp = 2;break;
}
v2 = v1 | (tmp<<29);
writemmr(0x21C0,v2);
writemmr(0x21C4,v2);
writemmr(0x21B8,v2);
writemmr(0x21BC,v2);
writemmr(0x21D0,v1);
writemmr(0x21D4,v1);
writemmr(0x21C8,v1);
writemmr(0x21CC,v1);
writemmr(0x216C,0);
}
static void blade_wait_engine(void)
{
while(readmmr(STA) & 0xFA800000);
}
static void blade_fill_rect(int x,int y,int w,int h,int c)
{
writemmr(CLR,c);
writemmr(ROP,ROP_S);
writemmr(CMD,0x20000000|1<<19|1<<4|2<<2);
writemmr(DR1,point(x,y));
writemmr(DR2,point(x+w-1,y+h-1));
}
static void blade_copy_rect(int x1,int y1,int x2,int y2,int w,int h)
{
int s1,s2,d1,d2;
int direction = 2;
s1 = point(x1,y1);
s2 = point(x1+w-1,y1+h-1);
d1 = point(x2,y2);
d2 = point(x2+w-1,y2+h-1);
if ((y1 > y2) || ((y1 == y2) && (x1 >x2)))
direction = 0;
writemmr(ROP,ROP_S);
writemmr(CMD,0xE0000000|1<<19|1<<4|1<<2|direction);
writemmr(SR1,direction?s2:s1);
writemmr(SR2,direction?s1:s2);
writemmr(DR1,direction?d2:d1);
writemmr(DR2,direction?d1:d2);
}
static struct accel_switch accel_blade = {
blade_init_accel,
blade_wait_engine,
blade_fill_rect,
blade_copy_rect,
};
/*
* Image specific acceleration functions
*/
static void image_init_accel(int pitch,int bpp)
{
int tmp = 0;
switch (bpp) {
case 8:tmp = 0;break;
case 15:tmp = 5;break;
case 16:tmp = 1;break;
case 24:
case 32:tmp = 2;break;
}
writemmr(0x2120, 0xF0000000);
writemmr(0x2120, 0x40000000|tmp);
writemmr(0x2120, 0x80000000);
writemmr(0x2144, 0x00000000);
writemmr(0x2148, 0x00000000);
writemmr(0x2150, 0x00000000);
writemmr(0x2154, 0x00000000);
writemmr(0x2120, 0x60000000 |(pitch<<16) |pitch);
writemmr(0x216C, 0x00000000);
writemmr(0x2170, 0x00000000);
writemmr(0x217C, 0x00000000);
writemmr(0x2120, 0x10000000);
writemmr(0x2130, (2047 << 16) | 2047);
}
static void image_wait_engine(void)
{
while(readmmr(0x2164) & 0xF0000000);
}
static void image_fill_rect(int x,int y,int w,int h,int c)
{
writemmr(0x2120,0x80000000);
writemmr(0x2120,0x90000000|ROP_S);
writemmr(0x2144,c);
writemmr(DR1,point(x,y));
writemmr(DR2,point(x+w-1,y+h-1));
writemmr(0x2124,0x80000000|3<<22|1<<10|1<<9);
}
static void image_copy_rect(int x1,int y1,int x2,int y2,int w,int h)
{
int s1,s2,d1,d2;
int direction = 2;
s1 = point(x1,y1);
s2 = point(x1+w-1,y1+h-1);
d1 = point(x2,y2);
d2 = point(x2+w-1,y2+h-1);
if ((y1 > y2) || ((y1 == y2) && (x1 >x2)))
direction = 0;
writemmr(0x2120,0x80000000);
writemmr(0x2120,0x90000000|ROP_S);
writemmr(SR1,direction?s2:s1);
writemmr(SR2,direction?s1:s2);
writemmr(DR1,direction?d2:d1);
writemmr(DR2,direction?d1:d2);
writemmr(0x2124,0x80000000|1<<22|1<<10|1<<7|direction);
}
static struct accel_switch accel_image = {
image_init_accel,
image_wait_engine,
image_fill_rect,
image_copy_rect,
};
/*
* Accel functions called by the upper layers
*/
static void trident_bmove (struct display *p, int sy, int sx,
int dy, int dx, int height, int width)
{
sx *= fontwidth(p);
dx *= fontwidth(p);
width *= fontwidth(p);
sy *= fontheight(p);
dy *= fontheight(p);
height *= fontheight(p);
acc->copy_rect(sx,sy,dx,dy,width,height);
acc->wait_engine();
}
static void trident_clear_helper (int c, struct display *p,
int sy, int sx, int height, int width)
{
sx *= fontwidth(p);
sy *= fontheight(p);
width *= fontwidth(p);
height *= fontheight(p);
acc->fill_rect(sx,sy,width,height,c);
acc->wait_engine();
}
#ifdef FBCON_HAS_CFB8
static void trident_8bpp_clear (struct vc_data *conp, struct display *p,
int sy, int sx, int height, int width)
{
int c;
c = attr_bgcol_ec(p,conp) & 0xFF;
c |= c<<8;
c |= c<<16;
trident_clear_helper(c,p,sy,sx,height,width);
}
static struct display_switch trident_8bpp = {
setup: fbcon_cfb8_setup,
bmove: trident_bmove,
clear: trident_8bpp_clear,
putc: fbcon_cfb8_putc,
putcs: fbcon_cfb8_putcs,
revc: fbcon_cfb8_revc,
clear_margins: fbcon_cfb8_clear_margins,
fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
};
#endif
#ifdef FBCON_HAS_CFB16
static void trident_16bpp_clear (struct vc_data *conp, struct display *p,
int sy, int sx, int height, int width)
{
int c;
c = ((u16*)p->dispsw_data)[attr_bgcol_ec(p,conp)];
c = c | c<<16;
trident_clear_helper(c,p,sy,sx,height,width);
}
static struct display_switch trident_16bpp = {
setup: fbcon_cfb16_setup,
bmove: trident_bmove,
clear: trident_16bpp_clear,
putc: fbcon_cfb16_putc,
putcs: fbcon_cfb16_putcs,
revc: fbcon_cfb16_revc,
clear_margins: fbcon_cfb16_clear_margins,
fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
};
#endif
#ifdef FBCON_HAS_CFB32
static void trident_32bpp_clear (struct vc_data *conp, struct display *p,
int sy, int sx, int height, int width)
{
int c;
c = ((u32*)p->dispsw_data)[attr_bgcol_ec(p,conp)];
trident_clear_helper(c,p,sy,sx,height,width);
}
static struct display_switch trident_32bpp = {
setup: fbcon_cfb32_setup,
bmove: trident_bmove,
clear: trident_32bpp_clear,
putc: fbcon_cfb32_putc,
putcs: fbcon_cfb32_putcs,
revc: fbcon_cfb32_revc,
clear_margins: fbcon_cfb32_clear_margins,
fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
};
#endif
/*
* Hardware access functions
*/
static inline unsigned char read3X4(int reg)
{
writeb(reg, fb_info.io_virt + CRT + 4);
return readb(fb_info.io_virt + CRT + 5);
}
static inline void write3X4(int reg, unsigned char val)
{
writeb(reg, fb_info.io_virt + CRT + 4);
writeb(val, fb_info.io_virt + CRT + 5);
}
static inline unsigned char read3C4(int reg)
{
t_outb(reg, 0x3C4);
return t_inb(0x3C5);
}
static inline void write3C4(int reg, unsigned char val)
{
t_outb(reg, 0x3C4);
t_outb(val, 0x3C5);
}
static inline unsigned char read3CE(int reg)
{
t_outb(reg, 0x3CE);
return t_inb(0x3CF);
}
static inline void writeAttr(int reg, unsigned char val)
{
readb(fb_info.io_virt + CRT + 0x0A); //flip-flop to index
t_outb(reg, 0x3C0);
t_outb(val, 0x3C0);
}
static inline unsigned char readAttr(int reg)
{
readb(fb_info.io_virt + CRT + 0x0A); //flip-flop to index
t_outb(reg, 0x3C0);
return t_inb(0x3C1);
}
static inline void write3CE(int reg, unsigned char val)
{
t_outb(reg, 0x3CE);
t_outb(val, 0x3CF);
}
#define unprotect_all() write3C4(Protection, 0x92);unprotect()
#define unprotect() write3C4(NewMode1,0xC2)
#define bios_reg(reg) write3CE(BiosReg, reg)
#define enable_mmio() outb(PCIReg, 0x3D4); \
outb(inb(0x3D5) | 0x01, 0x3D5)
#define crtc_unlock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F)
/* Return flat panel's maximum x resolution */
static int __init get_nativex(void)
{
int x,y,tmp;
if (nativex)
return nativex;
tmp = (read3CE(VertStretch) >> 4) & 3;
/* detection broken on XPAi ??? misdetects 1024 for 800 */
if (pci_id == CYBERBLADEXPAi1 && tmp == 3)
tmp = 2;
switch (tmp) {
case 0:x = 1280;y = 1024;break;
case 1:x = 640;y = 480;break;
case 2:x = 1024;y = 768;break;
default:x = 800;y = 600;break;
}
output("%dx%d flat panel found\n", x, y);
return x;
}
/* Set pitch */
static void set_lwidth(int width)
{
write3X4(Offset, width & 0xFF);
write3X4(AddColReg, (read3X4(AddColReg) & 0xCF) | ((width & 0x300) >>4));
}
/* For resolutions smaller than FP resolution stretch */
static void screen_stretch(void)
{
write3CE(VertStretch,(read3CE(VertStretch) & 0x7C) | 1);
write3CE(HorStretch,(read3CE(HorStretch) & 0x7C) | 1);
}
/* For resolutions smaller than FP resolution center */
static void screen_center(void)
{
bios_reg(0); // no stretch
write3CE(VertStretch,(read3CE(VertStretch) & 0x7C) | 0x80);
write3CE(HorStretch,(read3CE(HorStretch) & 0x7C) | 0x80);
}
/* Address of first shown pixel in display memory */
static void set_screen_start(int base)
{
write3X4(StartAddrLow, base & 0xFF);
write3X4(StartAddrHigh, (base & 0xFF00) >>8);
write3X4(CRTCModuleTest, (read3X4(CRTCModuleTest) & 0xDF) | ((base & 0x10000) >>11));
write3X4(CRTHiOrd, (read3X4(CRTHiOrd) & 0xF8) | (base & 0xE0000) >> 17);
}
/* Use 20.12 fixed-point for NTSC value and frequency calculation */
#define calc_freq(n,m,k) ( (unsigned long)0xE517 * (n+8) / (m+2)*(1<<k) )
/* Set dotclock frequency */
static void set_vclk(int freq)
{
int m,n,k;
int f,fi,d,di;
unsigned char lo=0,hi=0;
d = 20;
for(k = 2;k>=0;k--)
for(m = 0;m<63;m++)
for(n = 0;n<128;n++) {
fi = calc_freq(n,m,k);
if ((di = abs(fi - freq)) < d) {
d = di;
f = fi;
lo = n;
hi = (k<<6) | m;
}
}
write3C4(ClockHigh,hi);
write3C4(ClockLow,lo);
debug("VCLK = %X %X\n",hi,lo);
}
/* Set number of lines for flat panels*/
static void set_number_of_lines(int lines)
{
int tmp = read3CE(CyberEnhance) & 0x8F;
if (lines > 768)
tmp |= 0x30;
else if (lines > 600)
tmp |= 0x20;
else if (lines > 480)
tmp |= 0x10;
write3CE(CyberEnhance, tmp);
}
/*
* If we see that FP is active we assume we have one.
* Otherwise we have a CRT display.User can override.
*/
static unsigned int __init get_displaytype(void)
{
if (fp)
return DISPLAY_FP;
if (crt)
return DISPLAY_CRT;
return (read3CE(FPConfig) & 0x10)?DISPLAY_FP:DISPLAY_CRT;
}
/* Try detecting the video memory size */
static unsigned int __init get_memsize(void)
{
unsigned char tmp;
unsigned int k;
/* If memory size provided by user */
if (memsize)
k = memsize * Kb;
else
switch (pci_id) {
case CYBER9525DVD:k = 2560 * Kb;break;
case CYBERBLADEXPAi1:k = 16 * Mb;break;
case CYBERBLADEXPm16:k = 16 * Mb;break;
case CYBERBLADEXPm8:k = 8 * Mb;break;
default:
tmp = read3X4(SPR) & 0x0F;
switch (tmp) {
case 3:k = 1 * Mb;break;
case 7:k = 2 * Mb;break;
case 15:k = 4 * Mb;break;
case 4:k = 8 * Mb;break;
default:k = 1 * Mb;
}
}
k -= memdiff * Kb;
output("framebuffer size = %d Kb\n", k/Kb);
return k;
}
/* Fill in fix */
static int trident_encode_fix(struct fb_fix_screeninfo *fix,
const void *par,
struct fb_info_gen *info)
{
struct tridentfb_info * i = (struct tridentfb_info *)info;
struct tridentfb_par * p = (struct tridentfb_par *)par;
debug("enter\n");
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id,tridentfb_name);
fix->smem_start = i->fbmem;
fix->smem_len = i->memsize;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
fix->visual = p->bpp==8 ? FB_VISUAL_PSEUDOCOLOR:FB_VISUAL_TRUECOLOR;
fix->xpanstep = fix->ywrapstep = 0;
fix->ypanstep = 1;
fix->line_length = p->linelength;
fix->mmio_start = 0;
fix->mmio_len = 0;
fix->accel = FB_ACCEL_NONE;
debug("exit\n");
return 0;
}
/* Fill in par from var */
static int trident_decode_var(const struct fb_var_screeninfo *var,
void *par,
struct fb_info_gen *info)
{
struct tridentfb_par * p = (struct tridentfb_par *)par;
struct tridentfb_info * i = (struct tridentfb_info *)info;
int vres,vfront,vback,vsync;
debug("enter\n");
p->var = *var;
p->bpp = var->bits_per_pixel;
if (p->bpp == 24 )
p->bpp = 32;
p->linelength = var->xres_virtual * p->bpp/8;
switch (p->bpp) {
case 8:
p->var.red.offset = 0;
p->var.green.offset = 0;
p->var.blue.offset = 0;
p->var.red.length = 6;
p->var.green.length = 6;
p->var.blue.length = 6;
break;
case 16:
p->var.red.offset = 11;
p->var.green.offset = 5;
p->var.blue.offset = 0;
p->var.red.length = 5;
p->var.green.length = 6;
p->var.blue.length = 5;
break;
case 32:
p->var.red.offset = 16;
p->var.green.offset = 8;
p->var.blue.offset = 0;
p->var.red.length = 8;
p->var.green.length = 8;
p->var.blue.length = 8;
break;
default:
return -EINVAL;
}
/* convert from picoseconds to MHz */
p->vclk = 1000000/var->pixclock;
if (p->bpp == 32)
p->vclk *=2;
p->hres = var->xres;
vres = p->vres = var->yres;
/* See if requested resolution is larger than flat panel */
if (p->hres > i->nativex && flatpanel) {
return -EINVAL;
}
/* See if requested resolution fits in available memory */
if (p->hres * p->vres * p->bpp/8 > i->memsize) {
return -EINVAL;
}
vfront = var->upper_margin;
vback = var->lower_margin;
vsync = var->vsync_len;
/* Compute horizontal and vertical VGA CRTC timing values */
if (var->vmode & FB_VMODE_INTERLACED) {
vres /= 2;
vfront /=2;
vback /=2;
vsync /=2;
}
if (var->vmode & FB_VMODE_DOUBLE) {
vres *= 2;
vfront *=2;
vback *=2;
vsync *=2;
}
p->htotal = (p->hres + var->left_margin + var->right_margin + var->hsync_len)/8 - 10;
p->hdispend = p->hres/8 - 1;
p->hsyncstart = (p->hres + var->right_margin)/8;
p->hsyncend = var->hsync_len/8;
p->hblankstart = p->hdispend + 1;
p->hblankend = p->htotal + 5;
p->vtotal = vres + vfront + vback + vsync - 2;
p->vdispend = vres - 1;
p->vsyncstart = vres + vback;
p->vsyncend = vsync;
p->vblankstart = vres;
p->vblankend = p->vtotal + 2;
debug("exit\n");
return 0;
}
/* Fill in var from info */
static int trident_encode_var(struct fb_var_screeninfo *var,
const void *par,
struct fb_info_gen *info)
{
struct tridentfb_par * p = (struct tridentfb_par *)par;
debug("enter\n");
*var = p->var;
var->bits_per_pixel = p->bpp;
debug("exit\n");
return 0;
}
/* Fill in par from hardware */
static void trident_get_par(void *par, struct fb_info_gen *info)
{
struct tridentfb_par * p = (struct tridentfb_par *)par;
struct tridentfb_info * i = (struct tridentfb_info *)info;
debug("enter\n");
*p = i->currentmode;
debug("exit\n");
}
/* Pan the display */
static int trident_pan_display(const struct fb_var_screeninfo *var,
struct fb_info_gen *info)
{
unsigned int offset;
struct tridentfb_info * i = (struct tridentfb_info *)info;
debug("enter\n");
offset = (var->xoffset + (var->yoffset * var->xres))
* var->bits_per_pixel/32;
i->currentmode.var.xoffset = var->xoffset;
i->currentmode.var.yoffset = var->yoffset;
set_screen_start(offset);
debug("exit\n");
return 0;
}
/* Set the hardware from par */
static void trident_set_par(const void *par, struct fb_info_gen *info)
{
struct tridentfb_par * p = (struct tridentfb_par *)par;
struct tridentfb_info * i = (struct tridentfb_info *)info;
unsigned char tmp;
debug("enter\n");
i->currentmode = *p;
unprotect_all();
crtc_unlock();
enable_mmio();
write3CE(CyberControl,8);
if (flatpanel && p->hres < i->nativex) {
/*
* on flat panels with native size larger
* than requested resolution decide whether
* we stretch or center
*/
t_outb(0xEB,0x3C2);
write3CE(CyberControl,0x81);
if (center) //|| (p->bpp==32 && pci_id == CYBERBLADEi1D))
screen_center();
else if (stretch)
screen_stretch();
} else {
t_outb(0x2B,0x3C2);
write3CE(CyberControl,8);
}
/* vertical timing values */
write3X4(CRTVTotal, p->vtotal & 0xFF);
write3X4(CRTVDispEnd, p->vdispend & 0xFF);
write3X4(CRTVSyncStart, p->vsyncstart & 0xFF);
write3X4(CRTVSyncEnd, (p->vsyncend & 0x0F));
write3X4(CRTVBlankStart, p->vblankstart & 0xFF);
write3X4(CRTVBlankEnd, 0/*p->vblankend & 0xFF*/);
/* horizontal timing values */
write3X4(CRTHTotal, p->htotal & 0xFF);
write3X4(CRTHDispEnd, p->hdispend & 0xFF);
write3X4(CRTHSyncStart, p->hsyncstart & 0xFF);
write3X4(CRTHSyncEnd, (p->hsyncend & 0x1F) | ((p->hblankend & 0x20)<<2));
write3X4(CRTHBlankStart, p->hblankstart & 0xFF);
write3X4(CRTHBlankEnd, 0/*(p->hblankend & 0x1F)*/);
/* higher bits of vertical timing values */
tmp = 0x10;
if (p->vtotal & 0x100) tmp |= 0x01;
if (p->vdispend & 0x100) tmp |= 0x02;
if (p->vsyncstart & 0x100) tmp |= 0x04;
if (p->vblankstart & 0x100) tmp |= 0x08;
if (p->vtotal & 0x200) tmp |= 0x20;
if (p->vdispend & 0x200) tmp |= 0x40;
if (p->vsyncstart & 0x200) tmp |= 0x80;
write3X4(CRTOverflow, tmp);
tmp = read3X4(CRTHiOrd) | 0x08; //line compare bit 10
if (p->vtotal & 0x400) tmp |= 0x80;
if (p->vblankstart & 0x400) tmp |= 0x40;
if (p->vsyncstart & 0x400) tmp |= 0x20;
if (p->vdispend & 0x400) tmp |= 0x10;
write3X4(CRTHiOrd, tmp);
write3X4(HorizOverflow, 0);
tmp = 0x40;
if (p->vblankstart & 0x200) tmp |= 0x20;
if (p->var.vmode & FB_VMODE_DOUBLE) tmp |= 0x80; //double scan for 200 line modes
write3X4(CRTMaxScanLine, tmp);
write3X4(CRTLineCompare,0xFF);
write3X4(CRTPRowScan,0);
write3X4(CRTModeControl,0xC3);
write3X4(LinearAddReg,0x20); //enable linear addressing
tmp = (p->var.vmode & FB_VMODE_INTERLACED) ? 0x84:0x80;
write3X4(CRTCModuleTest,tmp); //enable access extended memory
write3X4(GraphEngReg, 0x80); //enable GE for text acceleration
if (p->var.accel_flags & FB_ACCELF_TEXT)
acc->init_accel(p->hres,p->bpp);
switch (p->bpp) {
case 8:tmp=0;break;
case 16:tmp=5;break;
case 24:
/* tmp=0x29;break; */
/* seems like 24bpp is same as 32bpp when using vesafb */
case 32:tmp=9;break;
}
write3X4(PixelBusReg, tmp);
write3X4(InterfaceSel, 0x5B); //32bit internal data path
write3X4(DRAMControl, 0x30); //both IO,linear enable
write3X4(Performance, 0xBF);
write3X4(PCIReg,0x07); //MMIO & PCI read and write burst enable
set_vclk(p->vclk);
write3C4(0,3);
write3C4(1,1); //set char clock 8 dots wide
write3C4(2,0x0F); //enable 4 maps because needed in chain4 mode
write3C4(3,0);
write3C4(4,0x0E); //memory mode enable bitmaps ??
write3CE(MiscExtFunc,(p->bpp==32)?0x1A:0x12); //divide clock by 2 if 32bpp
//chain4 mode display and CPU path
write3CE(0x5,0x40); //no CGA compat,allow 256 col
write3CE(0x6,0x05); //graphics mode
write3CE(0x7,0x0F); //planes?
writeAttr(0x10,0x41); //graphics mode and support 256 color modes
writeAttr(0x12,0x0F); //planes
writeAttr(0x13,0); //horizontal pel panning
//colors
for(tmp = 0;tmp < 0x10;tmp++)
writeAttr(tmp,tmp);
readb(fb_info.io_virt + CRT + 0x0A); //flip-flop to index
t_outb(0x20, 0x3C0); //enable attr
switch (p->bpp) {
case 8: tmp = 0;break; //256 colors
case 15: tmp = 0x10;break;
case 16: tmp = 0x30;break; //hicolor
case 24: //truecolor
case 32: tmp = 0xD0;break;
}
t_inb(0x3C8);
t_inb(0x3C6);
t_inb(0x3C6);
t_inb(0x3C6);
t_inb(0x3C6);
t_outb(tmp,0x3C6);
t_inb(0x3C8);
if (flatpanel)
set_number_of_lines(p->vres);
set_lwidth(p->hres*p->bpp/(4*16));
trident_pan_display(&p->var,info);
debug("exit\n");
}
/* Get value of one color register */
static int trident_getcolreg(unsigned regno, unsigned *red,
unsigned *green, unsigned *blue,
unsigned *transp, struct fb_info *info)
{
struct tridentfb_info * i = (struct tridentfb_info *)info;
int m = i->currentmode.bpp==8?256:16;
debug("enter %d\n",regno);
if (regno >= m)
return 1;
*red = palette[regno].red;
*green = palette[regno].green;
*blue = palette[regno].blue;
*transp = palette[regno].transp;
debug("exit\n");
return 0;
}
/* Set one color register */
static int tridentfb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
struct tridentfb_info * i = (struct tridentfb_info *)info;
int bpp = i->currentmode.bpp;
int m = bpp==8?256:16;
debug("enter %d\n",regno);
if (regno >= m)
return 1;
palette[regno].red = red;
palette[regno].green = green;
palette[regno].blue = blue;
palette[regno].transp = transp;
if (bpp==8) {
t_outb(0xFF,0x3C6);
t_outb(regno,0x3C8);
t_outb(red>>10,0x3C9);
t_outb(green>>10,0x3C9);
t_outb(blue>>10,0x3C9);
} else
if (bpp == 16) /* RGB 565 */
((u16*)info->pseudo_palette)[regno] = (red & 0xF800) |
((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
else
if (bpp == 32) /* ARGB 8888 */
((u32*)info->pseudo_palette)[regno] =
((transp & 0xFF00) <<16) |
((red & 0xFF00) << 8) |
((green & 0xFF00)) |
((blue & 0xFF00)>>8);
debug("exit\n");
return 0;
}
/* Try blanking the screen.For flat panels it does nothing */
static int trident_blank(int blank_mode, struct fb_info_gen *info)
{
unsigned char PMCont,DPMSCont;
debug("enter\n");
if (flatpanel)
return 0;
t_outb(0x04,0x83C8); /* Read DPMS Control */
PMCont = t_inb(0x83C6) & 0xFC;
DPMSCont = read3CE(PowerStatus) & 0xFC;
switch (blank_mode)
{
case VESA_NO_BLANKING:
/* Screen: On, HSync: On, VSync: On */
PMCont |= 0x03;
DPMSCont |= 0x00;
break;
case VESA_HSYNC_SUSPEND:
/* Screen: Off, HSync: Off, VSync: On */
PMCont |= 0x02;
DPMSCont |= 0x01;
break;
case VESA_VSYNC_SUSPEND:
/* Screen: Off, HSync: On, VSync: Off */
PMCont |= 0x02;
DPMSCont |= 0x02;
break;
case VESA_POWERDOWN:
/* Screen: Off, HSync: Off, VSync: Off */
PMCont |= 0x00;
DPMSCont |= 0x03;
break;
}
write3CE(PowerStatus,DPMSCont);
t_outb(4,0x83C8);
t_outb(PMCont,0x83C6);
debug("exit\n");
return 0;
}
/* Set display switch used by console */
static void trident_set_disp(const void *par, struct display *disp,
struct fb_info_gen *info)
{
struct tridentfb_info * i = (struct tridentfb_info *)info;
struct fb_info * ii = (struct fb_info *)info;
struct tridentfb_par * p = (struct tridentfb_par *)par;
int isaccel = p->var.accel_flags & FB_ACCELF_TEXT;
info->info.screen_base = (char *)i->fbmem_virt;
debug("enter\n");
#ifdef FBCON_HAS_CFB8
if (p->bpp == 8 ) {
if (isaccel)
disp->dispsw = &trident_8bpp;
else
disp->dispsw = &fbcon_cfb8;
} else
#endif
#ifdef FBCON_HAS_CFB16
if (p->bpp == 16) {
if (isaccel)
disp->dispsw = &trident_16bpp;
else
disp->dispsw = &fbcon_cfb16;
disp->dispsw_data =ii->pseudo_palette; /* console palette */
} else
#endif
#ifdef FBCON_HAS_CFB32
if (p->bpp == 32) {
if (isaccel)
disp->dispsw = &trident_32bpp;
else
disp->dispsw = &fbcon_cfb32;
disp->dispsw_data =ii->pseudo_palette; /* console palette */
} else
#endif
disp->dispsw = &fbcon_dummy;
debug("exit\n");
}
static struct fbgen_hwswitch trident_hwswitch = {
NULL, /* detect not needed */
trident_encode_fix,
trident_decode_var,
trident_encode_var,
trident_get_par,
trident_set_par,
trident_getcolreg,
trident_pan_display,
trident_blank,
trident_set_disp
};
/* List of boards that we are trying to support */
static struct almost_supported_board {
int pci_id;
int family;
struct accel_switch * acc;
char* board_name;
int accel;
} asb[] __initdata = {
{ BLADE3D, BLADE, &accel_blade, "Blade3D", ACCEL },
{ CYBERBLADEi7, BLADE, &accel_blade, "CyberBladei7", ACCEL },
{ CYBERBLADEi7D, BLADE, &accel_blade, "CyberBladei7D", ACCEL },
{ CYBERBLADEi1, BLADE, &accel_blade, "CyberBladei1", ACCEL },
{ CYBERBLADEi1D, BLADE, &accel_blade, "CyberBladei1D", ACCEL },
{ CYBERBLADEAi1, BLADE, &accel_blade, "CyberBladeAi1", ACCEL },
{ CYBERBLADEAi1D, BLADE, &accel_blade, "CyberBladeAi1D", ACCEL },
{ CYBERBLADEE4, BLADE, &accel_blade, "CyberBladeE4", ACCEL },
{ IMAGE975, IMAGE, &accel_image, "IMAGE975", NOACCEL },
{ IMAGE985, IMAGE, &accel_image, "IMAGE985", NOACCEL },
{ CYBER9320, IMAGE, &accel_image, "Cyber9320", NOACCEL },
{ CYBER9388, IMAGE, &accel_image, "Cyber9388", NOACCEL },
{ CYBER9520, IMAGE, &accel_image, "Cyber9520", NOACCEL },
{ CYBER9525DVD, IMAGE, &accel_image, "Cyber9525DVD", NOACCEL },
{ CYBER9397, IMAGE, &accel_image, "Cyber9397", NOACCEL },
{ CYBER9397DVD, IMAGE, &accel_image, "Cyber9397DVD", NOACCEL },
{ CYBERBLADEXPAi1, XP, &accel_blade, "CyberBladeXPAi1", NOACCEL },
{ CYBERBLADEXPm8, XP, &accel_blade, "CyberBladeXPm8", NOACCEL },
{ CYBERBLADEXPm16, XP, &accel_blade, "CyberBladeXPm16", NOACCEL },
};
static __init int trident_find_board(void)
{
int i;
struct pci_dev * board;
for (i = 0;i < ARRAY_SIZE(asb);i++) {
if ((board = pci_find_device(PCI_VENDOR_ID_TRIDENT,
asb[i].pci_id,
NULL))) {
family = asb[i].family;
acc = asb[i].acc;
pci_id = asb[i].pci_id;
defaultaccel = asb[i].accel;
fb_info.io = pci_resource_start(board,1);
fb_info.fbmem = pci_resource_start(board,0);
output("%s board found\n", asb[i].board_name);
return 1;
}
}
output("No Trident board found\n");
return 0;
}
int __init tridentfb_init(void)
{
output("Trident framebuffer %s initializing\n", VERSION);
if (!trident_find_board())
return -1;
if (!request_mem_region(fb_info.io, TRIDENT_IOSIZE, "tridentfb")) {
debug("request_region failed!\n");
return -1;
};
fb_info.io_virt = (unsigned int)ioremap_nocache(fb_info.io, TRIDENT_IOSIZE);
if (!fb_info.io_virt) {
release_region(fb_info.io, TRIDENT_IOSIZE);
debug("ioremap failed\n");
return -1;
}
fb_info.memsize = get_memsize();
if (!request_mem_region(fb_info.fbmem, fb_info.memsize, "tridentfb")) {
debug("request_mem_region failed!\n");
return -1;
}
fb_info.fbmem_virt = (unsigned int)ioremap_nocache(fb_info.fbmem, fb_info.memsize);
if (!fb_info.fbmem_virt) {
release_mem_region(fb_info.fbmem, fb_info.memsize);
debug("ioremap failed\n");
return -1;
}
debug("Trident board found : mem = %X,io = %X, mem_v = %X, io_v = %X\n",
fb_info.fbmem, fb_info.io, fb_info.fbmem_virt, fb_info.io_virt);
fb_info.gen.parsize = sizeof (struct tridentfb_par);
fb_info.gen.fbhw = &trident_hwswitch;
strcpy(fb_info.gen.info.modename, tridentfb_name);
displaytype = get_displaytype();
if(flatpanel)
fb_info.nativex = get_nativex();
fb_info.gen.info.changevar = NULL;
fb_info.gen.info.node = NODEV;
fb_info.gen.info.fbops = &tridentfb_ops;
fb_info.gen.info.disp = &disp;
fb_info.gen.info.switch_con = &fbgen_switch;
fb_info.gen.info.updatevar = &fbgen_update_var;
fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
fb_info.gen.info.fontname[0] = '\0';
fb_info.gen.info.pseudo_palette = pseudo_pal;
/* This should give a reasonable default video mode */
fb_find_mode(&default_var,&fb_info.gen.info,mode,NULL,0,NULL,bpp);
/*
* Unless user explicitly requires accel/noaccel use
* per chip defaults.Accel has priority over noaccel.
*/
if (accel)
defaultaccel = ACCEL;
else if (noaccel)
defaultaccel = NOACCEL;
if (defaultaccel == ACCEL)
default_var.accel_flags |= FB_ACCELF_TEXT;
else
default_var.accel_flags &= ~FB_ACCELF_TEXT;
trident_decode_var(&default_var, &fb_info.currentmode, &fb_info.gen);
fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
default_var.activate |= FB_ACTIVATE_NOW;
fbgen_set_disp(-1, &fb_info.gen);
if (register_framebuffer(&fb_info.gen.info) < 0) {
printk("Could not register Trident framebuffer\n");
return -EINVAL;
}
output("fb%d: %s frame buffer device %dx%d-%dbpp\n",
GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename,default_var.xres,
default_var.yres,default_var.bits_per_pixel);
return 0;
}
void __exit tridentfb_exit(void)
{
unregister_framebuffer(&fb_info.gen.info);
iounmap((void *)fb_info.io_virt);
iounmap((void *)fb_info.fbmem_virt);
}
/*
* Parse user specified options (`video=trident:')
* example:
* video=trident:800x600,bpp=16,noaccel
*/
int tridentfb_setup(char *options)
{
char * opt;
if (!options || !*options)
return 0;
while((opt=strsep(&options,",")) != NULL) {
if (!*opt) continue;
if (!strncmp(opt,"noaccel",7))
noaccel = 1;
else if (!strncmp(opt,"accel",5))
accel = 1;
else if (!strncmp(opt,"fp",2))
displaytype = DISPLAY_FP;
else if (!strncmp(opt,"crt",3))
displaytype = DISPLAY_CRT;
else if (!strncmp(opt,"bpp=",4))
bpp = simple_strtoul(opt+4,NULL,0);
else if (!strncmp(opt,"center",6))
center = 1;
else if (!strncmp(opt,"stretch",7))
stretch = 1;
else if (!strncmp(opt,"memsize=",8))
memsize = simple_strtoul(opt+8,NULL,0);
else if (!strncmp(opt,"memdiff=",8))
memdiff = simple_strtoul(opt+8,NULL,0);
else if (!strncmp(opt,"nativex=",8))
nativex = simple_strtoul(opt+8,NULL,0);
else
mode = opt;
}
return 0;
}
static struct fb_ops tridentfb_ops = {
fb_get_fix: fbgen_get_fix,
fb_get_var: fbgen_get_var,
fb_set_var: fbgen_set_var,
fb_get_cmap: fbgen_get_cmap,
fb_set_cmap: fbgen_set_cmap,
fb_setcolreg: tridentfb_setcolreg,
fb_pan_display: fbgen_pan_display,
};
#ifdef MODULE
module_init(tridentfb_init);
#endif
module_exit(tridentfb_exit);
MODULE_AUTHOR("Jani Monoses <jani@astechnix.ro>");
MODULE_DESCRIPTION("Framebuffer driver for Trident cards");
MODULE_LICENSE("GPL");
#ifndef TRIDENTFB_DEBUG
#define TRIDENTFB_DEBUG 0
#endif
#if TRIDENTFB_DEBUG
#define debug(f,a...) printk("%s:" f, __FUNCTION__ , ## a)
#else
#define debug(f,a...)
#endif
#define output(f, a...) printk("tridentfb: " f, ## a)
#define Kb (1024)
#define Mb (Kb*Kb)
/* PCI IDS of supported cards temporarily here */
#define CYBER9320 0x9320
#define CYBER9388 0x9388
#define CYBER9397 0x9397
#define CYBER9397DVD 0x939A
#define CYBER9520 0x9520
#define CYBER9525DVD 0x9525
#define IMAGE975 0x9750
#define IMAGE985 0x9850
#define BLADE3D 0x9880
#define CYBERBLADEE4 0x9540
#define CYBERBLADEi7 0x8400
#define CYBERBLADEi7D 0x8420
#define CYBERBLADEi1 0x8500
#define CYBERBLADEi1D 0x8520
#define CYBERBLADEAi1 0x8600
#define CYBERBLADEAi1D 0x8620
#define CYBERBLADEXPAi1 0x8820
#define CYBERBLADEXPm8 0x9910
#define CYBERBLADEXPm16 0x9930
/* acceleration families */
#define IMAGE 0
#define BLADE 1
#define XP 2
#define is_image() (family == IMAGE)
#define is_blade() (family == BLADE)
#define is_xp() (family == XP)
/* these defines are for 'lcd' variable */
#define LCD_STRETCH 0
#define LCD_CENTER 1
#define LCD_BIOS 2
/* display types */
#define DISPLAY_CRT 0
#define DISPLAY_FP 1
#define flatpanel (displaytype == DISPLAY_FP)
/* these are for defaultaccel variable */
#define ACCEL 1
#define NOACCEL 0
#define TRIDENT_IOSIZE 0x20000
#define NTSC 14.31818
#define PAL 17.73448
/* General Registers */
#define SPR 0x1F /* Software Programming Register (videoram) */
/* 3C4 */
#define RevisionID 0x09
#define OldOrNew 0x0B
#define ConfPort1 0x0C
#define ConfPort2 0x0C
#define NewMode2 0x0D
#define NewMode1 0x0E
#define Protection 0x11
#define MCLKLow 0x16
#define MCLKHigh 0x17
#define ClockLow 0x18
#define ClockHigh 0x19
#define SSetup 0x20
#define SKey 0x37
#define SPKey 0x57
/* 0x3x4 */
#define CRTHTotal 0x00
#define CRTHDispEnd 0x01
#define CRTHBlankStart 0x02
#define CRTHBlankEnd 0x03
#define CRTHSyncStart 0x04
#define CRTHSyncEnd 0x05
#define CRTVTotal 0x06
#define CRTVDispEnd 0x12
#define CRTVBlankStart 0x15
#define CRTVBlankEnd 0x16
#define CRTVSyncStart 0x10
#define CRTVSyncEnd 0x11
#define CRTOverflow 0x07
#define CRTPRowScan 0x08
#define CRTMaxScanLine 0x09
#define CRTModeControl 0x17
#define CRTLineCompare 0x18
/* 3x4 */
#define StartAddrHigh 0x0C
#define StartAddrLow 0x0D
#define Offset 0x13
#define Underline 0x14
#define CRTCMode 0x17
#define CRTCModuleTest 0x1E
#define FIFOControl 0x20
#define LinearAddReg 0x21
#define DRAMTiming 0x23
#define New32 0x23
#define RAMDACTiming 0x25
#define CRTHiOrd 0x27
#define AddColReg 0x29
#define InterfaceSel 0x2A
#define HorizOverflow 0x2B
#define GETest 0x2D
#define Performance 0x2F
#define GraphEngReg 0x36
#define I2C 0x37
#define PixelBusReg 0x38
#define PCIReg 0x39
#define DRAMControl 0x3A
#define MiscContReg 0x3C
#define CursorXLow 0x40
#define CursorXHigh 0x41
#define CursorYLow 0x42
#define CursorYHigh 0x43
#define CursorLocLow 0x44
#define CursorLocHigh 0x45
#define CursorXOffset 0x46
#define CursorYOffset 0x47
#define CursorFG1 0x48
#define CursorFG2 0x49
#define CursorFG3 0x4A
#define CursorFG4 0x4B
#define CursorBG1 0x4C
#define CursorBG2 0x4D
#define CursorBG3 0x4E
#define CursorBG4 0x4F
#define CursorControl 0x50
#define PCIRetry 0x55
#define PreEndControl 0x56
#define PreEndFetch 0x57
#define PCIMaster 0x60
#define Enhancement0 0x62
#define NewEDO 0x64
#define TVinterface 0xC0
#define TVMode 0xC1
#define ClockControl 0xCF
/* 3CE */
#define MiscExtFunc 0x0F
#define PowerStatus 0x23
#define MiscIntContReg 0x2F
#define CyberControl 0x30
#define CyberEnhance 0x31
#define FPConfig 0x33
#define VertStretch 0x52
#define HorStretch 0x53
#define BiosMode 0x5c
#define BiosReg 0x5d
......@@ -26,71 +26,28 @@
#include <asm/mtrr.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
#include <video/fbcon-cfb24.h>
#include <video/fbcon-cfb32.h>
#include <video/fbcon-mac.h>
#define dac_reg (0x3c8)
#define dac_val (0x3c9)
/* --------------------------------------------------------------------- */
/*
* card parameters
*/
/* card */
unsigned long video_base; /* physical addr */
int video_size;
char *video_vbase; /* mapped */
/* mode */
static int video_bpp;
static int video_width;
static int video_height;
static int video_height_virtual;
static int video_type = FB_TYPE_PACKED_PIXELS;
static int video_visual;
static int video_linelength;
static int video_cmap_len;
/* --------------------------------------------------------------------- */
static struct fb_var_screeninfo vesafb_defined = {
0,0,0,0, /* W,H, W, H (virtual) load xres,xres_virtual*/
0,0, /* virtual -> visible no offset */
8, /* depth -> load bits_per_pixel */
0, /* greyscale ? */
{0,0,0}, /* R */
{0,0,0}, /* G */
{0,0,0}, /* B */
{0,0,0}, /* transparency */
0, /* standard pixel format */
FB_ACTIVATE_NOW,
-1,-1,
0,
0L,0L,0L,0L,0L,
0L,0L,0, /* No sync info */
FB_VMODE_NONINTERLACED,
{0,0,0,0,0,0}
activate: FB_ACTIVATE_NOW,
height: -1,
width: -1,
vmode: FB_VMODE_NONINTERLACED,
};
static struct fb_fix_screeninfo vesafb_fix = {
id: "VESA VGA",
type: FB_TYPE_PACKED_PIXELS,
accel: FB_ACCEL_NONE,
};
static struct display disp;
static struct fb_info fb_info;
static struct { u_short blue, green, red, pad; } palette[256];
static union {
#ifdef FBCON_HAS_CFB16
u16 cfb16[16];
#endif
#ifdef FBCON_HAS_CFB24
u32 cfb24[16];
#endif
#ifdef FBCON_HAS_CFB32
u32 cfb32[16];
#endif
} fbcon_cmap;
static u32 pseudo_palette[17];
static int inverse = 0;
static int mtrr = 0;
......@@ -101,8 +58,6 @@ static unsigned short *pmi_base = 0;
static void (*pmi_start)(void);
static void (*pmi_pal)(void);
static struct display_switch vesafb_sw;
/* --------------------------------------------------------------------- */
static int vesafb_pan_display(struct fb_var_screeninfo *var, int con,
......@@ -119,7 +74,7 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var, int con,
if ((ypan==1) && var->yoffset+var->yres > var->yres_virtual)
return -EINVAL;
offset = (var->yoffset * video_linelength + var->xoffset) / 4;
offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4;
__asm__ __volatile__(
"call *(%%edi)"
......@@ -132,172 +87,6 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var, int con,
return 0;
}
static int vesafb_update_var(int con, struct fb_info *info)
{
if (con == info->currcon && ypan) {
struct fb_var_screeninfo *var = &fb_display[info->currcon].var;
return vesafb_pan_display(var,con,info);
}
return 0;
}
static int vesafb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id,"VESA VGA");
fix->smem_start=video_base;
fix->smem_len=video_size;
fix->type = video_type;
fix->visual = video_visual;
fix->xpanstep = 0;
fix->ypanstep = ypan ? 1 : 0;
fix->ywrapstep = (ypan>1) ? 1 : 0;
fix->line_length=video_linelength;
return 0;
}
static int vesafb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
if(con==-1)
memcpy(var, &vesafb_defined, sizeof(struct fb_var_screeninfo));
else
*var=fb_display[con].var;
return 0;
}
static void vesafb_set_disp(int con)
{
struct fb_fix_screeninfo fix;
struct display *display;
struct display_switch *sw;
if (con >= 0)
display = &fb_display[con];
else
display = &disp; /* used during initialization */
vesafb_get_fix(&fix, con, 0);
memset(display, 0, sizeof(struct display));
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
display->ypanstep = fix.ypanstep;
display->ywrapstep = fix.ywrapstep;
display->line_length = fix.line_length;
display->next_line = fix.line_length;
display->can_soft_blank = 0;
display->inverse = inverse;
vesafb_get_var(&display->var, -1, &fb_info);
switch (video_bpp) {
#ifdef FBCON_HAS_CFB8
case 8:
sw = &fbcon_cfb8;
break;
#endif
#ifdef FBCON_HAS_CFB16
case 15:
case 16:
sw = &fbcon_cfb16;
display->dispsw_data = fbcon_cmap.cfb16;
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
sw = &fbcon_cfb24;
display->dispsw_data = fbcon_cmap.cfb24;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
sw = &fbcon_cfb32;
display->dispsw_data = fbcon_cmap.cfb32;
break;
#endif
default:
#ifdef FBCON_HAS_MAC
sw = &fbcon_mac;
break;
#else
sw = &fbcon_dummy;
return;
#endif
}
memcpy(&vesafb_sw, sw, sizeof(*sw));
display->dispsw = &vesafb_sw;
if (!ypan) {
display->scrollmode = SCROLL_YREDRAW;
vesafb_sw.bmove = fbcon_redraw_bmove;
}
}
static int vesafb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
static int first = 1;
if (var->xres != vesafb_defined.xres ||
var->yres != vesafb_defined.yres ||
var->xres_virtual != vesafb_defined.xres_virtual ||
var->yres_virtual > video_height_virtual ||
var->yres_virtual < video_height ||
var->xoffset ||
var->bits_per_pixel != vesafb_defined.bits_per_pixel ||
var->nonstd) {
if (first) {
printk(KERN_ERR "Vesafb does not support changing the video mode\n");
first = 0;
}
return -EINVAL;
}
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
return 0;
if (ypan) {
if (vesafb_defined.yres_virtual != var->yres_virtual) {
vesafb_defined.yres_virtual = var->yres_virtual;
if (con != -1) {
fb_display[con].var = vesafb_defined;
info->changevar(con);
}
}
if (var->yoffset != vesafb_defined.yoffset)
return vesafb_pan_display(var,con,info);
return 0;
}
if (var->yoffset)
return -EINVAL;
return 0;
}
static int vesa_getcolreg(unsigned regno, unsigned *red, unsigned *green,
unsigned *blue, unsigned *transp,
struct fb_info *fb_info)
{
/*
* Read a single color register and split it into colors/transparent.
* Return != 0 for invalid regno.
*/
if (regno >= video_cmap_len)
return 1;
*red = palette[regno].red;
*green = palette[regno].green;
*blue = palette[regno].blue;
*transp = 0;
return 0;
}
#ifdef FBCON_HAS_CFB8
static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
{
struct { u_char blue, green, red, pad; } entry;
......@@ -325,11 +114,9 @@ static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned bl
}
}
#endif
static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *fb_info)
struct fb_info *info)
{
/*
* Set a single color register. The values supplied are
......@@ -338,85 +125,62 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
* != 0 for invalid regno.
*/
if (regno >= video_cmap_len)
if (regno >= info->cmap.len)
return 1;
palette[regno].red = red;
palette[regno].green = green;
palette[regno].blue = blue;
switch (video_bpp) {
#ifdef FBCON_HAS_CFB8
switch (info->var.bits_per_pixel) {
case 8:
vesa_setpalette(regno,red,green,blue);
break;
#endif
#ifdef FBCON_HAS_CFB16
case 15:
case 16:
if (vesafb_defined.red.offset == 10) {
if (info->var.red.offset == 10) {
/* 1:5:5:5 */
fbcon_cmap.cfb16[regno] =
((red & 0xf800) >> 1) |
((green & 0xf800) >> 6) |
((blue & 0xf800) >> 11);
((u32*) (info->pseudo_palette))[regno] =
((red & 0xf800) >> 1) |
((green & 0xf800) >> 6) |
((blue & 0xf800) >> 11);
} else {
/* 0:5:6:5 */
fbcon_cmap.cfb16[regno] =
((red & 0xf800) ) |
((green & 0xfc00) >> 5) |
((blue & 0xf800) >> 11);
((u32*) (info->pseudo_palette))[regno] =
((red & 0xf800) ) |
((green & 0xfc00) >> 5) |
((blue & 0xf800) >> 11);
}
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
red >>= 8;
green >>= 8;
blue >>= 8;
fbcon_cmap.cfb24[regno] =
(red << vesafb_defined.red.offset) |
(green << vesafb_defined.green.offset) |
(blue << vesafb_defined.blue.offset);
((u32 *)(info->pseudo_palette))[regno] =
(red << info->var.red.offset) |
(green << info->var.green.offset) |
(blue << info->var.blue.offset);
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
red >>= 8;
green >>= 8;
blue >>= 8;
fbcon_cmap.cfb32[regno] =
(red << vesafb_defined.red.offset) |
(green << vesafb_defined.green.offset) |
(blue << vesafb_defined.blue.offset);
((u32 *)(info->pseudo_palette))[regno] =
(red << info->var.red.offset) |
(green << info->var.green.offset) |
(blue << info->var.blue.offset);
break;
#endif
}
return 0;
}
static int vesafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
if (con == info->currcon) /* current console? */
return fb_get_cmap(cmap, kspc, vesa_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
fb_copy_cmap(fb_default_cmap(video_cmap_len),
cmap, kspc ? 0 : 2);
return 0;
}
static struct fb_ops vesafb_ops = {
owner: THIS_MODULE,
fb_get_fix: vesafb_get_fix,
fb_get_var: vesafb_get_var,
fb_set_var: vesafb_set_var,
fb_get_cmap: vesafb_get_cmap,
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_setcolreg: vesafb_setcolreg,
fb_pan_display: vesafb_pan_display,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
};
int __init vesafb_setup(char *options)
......@@ -451,59 +215,46 @@ int __init vesafb_setup(char *options)
return 0;
}
static int vesafb_switch(int con, struct fb_info *info)
{
/* Do we have to save the colormap? */
if (fb_display[info->currcon].cmap.len)
fb_get_cmap(&fb_display[info->currcon].cmap, 1, vesa_getcolreg,
info);
info->currcon = con;
/* Install new colormap */
do_install_cmap(con, info);
vesafb_update_var(con,info);
return 1;
}
int __init vesafb_init(void)
{
int i,j;
int video_cmap_len;
int i;
if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
return -ENXIO;
video_base = screen_info.lfb_base;
video_bpp = screen_info.lfb_depth;
if (15 == video_bpp)
video_bpp = 16;
video_width = screen_info.lfb_width;
video_height = screen_info.lfb_height;
video_linelength = screen_info.lfb_linelength;
video_size = screen_info.lfb_size * 65536;
video_visual = (video_bpp == 8) ?
vesafb_fix.smem_start = screen_info.lfb_base;
vesafb_defined.bits_per_pixel = screen_info.lfb_depth;
if (15 == vesafb_defined.bits_per_pixel)
vesafb_defined.bits_per_pixel = 16;
vesafb_defined.xres = screen_info.lfb_width;
vesafb_defined.yres = screen_info.lfb_height;
vesafb_fix.line_length = screen_info.lfb_linelength;
vesafb_fix.smem_len = screen_info.lfb_size * 65536;
vesafb_fix.visual = (vesafb_defined.bits_per_pixel == 8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
if (!request_mem_region(video_base, video_size, "vesafb")) {
if (!request_mem_region(vesafb_fix.smem_start, vesafb_fix.smem_len, "vesafb")) {
printk(KERN_WARNING
"vesafb: abort, cannot reserve video memory at 0x%lx\n",
video_base);
vesafb_fix.smem_start);
/* We cannot make this fatal. Sometimes this comes from magic
spaces our resource handlers simply don't know about */
}
video_vbase = ioremap(video_base, video_size);
if (!video_vbase) {
release_mem_region(video_base, video_size);
fb_info.screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len);
if (!fb_info.screen_base) {
release_mem_region(vesafb_fix.smem_start, vesafb_fix.smem_len);
printk(KERN_ERR
"vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
video_size, video_base);
vesafb_fix.smem_len, vesafb_fix.smem_start);
return -EIO;
}
printk(KERN_INFO "vesafb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
video_base, video_vbase, video_size/1024);
vesafb_fix.smem_start, fb_info.screen_base, vesafb_fix.smem_len/1024);
printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
video_width, video_height, video_bpp, video_linelength, screen_info.pages);
vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, vesafb_fix.line_length, screen_info.pages);
if (screen_info.vesapm_seg) {
printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x\n",
......@@ -536,32 +287,27 @@ int __init vesafb_init(void)
}
}
vesafb_defined.xres=video_width;
vesafb_defined.yres=video_height;
vesafb_defined.xres_virtual=video_width;
vesafb_defined.yres_virtual=video_size / video_linelength;
vesafb_defined.bits_per_pixel=video_bpp;
if (ypan && vesafb_defined.yres_virtual > video_height) {
vesafb_defined.xres_virtual = vesafb_defined.xres;
vesafb_defined.yres_virtual = vesafb_fix.smem_len / vesafb_fix.line_length;
if (ypan && vesafb_defined.yres_virtual > vesafb_defined.yres) {
printk(KERN_INFO "vesafb: scrolling: %s using protected mode interface, yres_virtual=%d\n",
(ypan > 1) ? "ywrap" : "ypan",vesafb_defined.yres_virtual);
} else {
printk(KERN_INFO "vesafb: scrolling: redraw\n");
vesafb_defined.yres_virtual = video_height;
vesafb_defined.yres_virtual = vesafb_defined.yres;
ypan = 0;
}
video_height_virtual = vesafb_defined.yres_virtual;
/* some dummy values for timing to make fbset happy */
vesafb_defined.pixclock = 10000000 / video_width * 1000 / video_height;
vesafb_defined.left_margin = (video_width / 8) & 0xf8;
vesafb_defined.pixclock = 10000000 / vesafb_defined.xres * 1000 / vesafb_defined.yres;
vesafb_defined.left_margin = (vesafb_defined.xres / 8) & 0xf8;
vesafb_defined.right_margin = 32;
vesafb_defined.upper_margin = 16;
vesafb_defined.lower_margin = 4;
vesafb_defined.hsync_len = (video_width / 8) & 0xf8;
vesafb_defined.hsync_len = (vesafb_defined.xres / 8) & 0xf8;
vesafb_defined.vsync_len = 4;
if (video_bpp > 8) {
if (vesafb_defined.bits_per_pixel > 8) {
vesafb_defined.red.offset = screen_info.red_pos;
vesafb_defined.red.length = screen_info.red_size;
vesafb_defined.green.offset = screen_info.green_pos;
......@@ -585,48 +331,49 @@ int __init vesafb_init(void)
vesafb_defined.red.length = 6;
vesafb_defined.green.length = 6;
vesafb_defined.blue.length = 6;
for(i = 0; i < 16; i++) {
j = color_table[i];
palette[i].red = default_red[j];
palette[i].green = default_grn[j];
palette[i].blue = default_blu[j];
}
video_cmap_len = 256;
}
vesafb_fix.ypanstep = ypan ? 1 : 0;
vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0;
/* request failure does not faze us, as vgacon probably has this
* region already (FIXME) */
request_region(0x3c0, 32, "vesafb");
if (mtrr) {
int temp_size = video_size;
int temp_size = vesafb_fix.smem_len;
/* Find the largest power-of-two */
while (temp_size & (temp_size - 1))
temp_size &= (temp_size - 1);
/* Try and find a power of two to add */
while (temp_size && mtrr_add(video_base, temp_size, MTRR_TYPE_WRCOMB, 1)==-EINVAL) {
while (temp_size && mtrr_add(vesafb_fix.smem_start, temp_size, MTRR_TYPE_WRCOMB, 1)==-EINVAL) {
temp_size >>= 1;
}
}
strcpy(fb_info.modename, "VESA VGA");
strcpy(fb_info.modename, vesafb_fix.id);
fb_info.changevar = NULL;
fb_info.node = NODEV;
fb_info.fbops = &vesafb_ops;
fb_info.screen_base = video_vbase;
fb_info.disp=&disp;
fb_info.var = vesafb_defined;
fb_info.fix = vesafb_fix;
fb_info.currcon = -1;
fb_info.switch_con=&vesafb_switch;
fb_info.updatevar=&vesafb_update_var;
fb_info.flags=FBINFO_FLAG_DEFAULT;
vesafb_set_disp(-1);
fb_info.disp = &disp;
fb_info.switch_con = gen_switch;
fb_info.updatevar = gen_update_var;
fb_info.pseudo_palette = pseudo_palette;
fb_info.flags = FBINFO_FLAG_DEFAULT;
fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0);
gen_set_disp(-1, &fb_info);
if (register_framebuffer(&fb_info)<0)
return -EINVAL;
printk(KERN_INFO "fb%d: %s frame buffer device\n",
GET_FB_IDX(fb_info.node), fb_info.modename);
GET_FB_IDX(fb_info.node), fb_info.fix.id);
return 0;
}
......
/*
* linux/drivers/video/vfb.c -- Virtual frame buffer device
*
* Copyright (C) 2002 James Simmons
*
* Copyright (C) 1997 Geert Uytterhoeven
*
* This file is subject to the terms and conditions of the GNU General Public
......@@ -22,15 +24,7 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <video/fbcon.h>
#include <video/fbcon-mfb.h>
#include <video/fbcon-cfb2.h>
#include <video/fbcon-cfb4.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
#include <video/fbcon-cfb24.h>
#include <video/fbcon-cfb32.h>
#include <linux/fbcon.h>
/*
* RAM we reserve for the frame buffer. This defines the maximum screen
......@@ -41,525 +35,447 @@
#define VIDEOMEMSIZE (1*1024*1024) /* 1 MB */
static u_long videomemory, videomemorysize = VIDEOMEMSIZE;
static void *videomemory;
static u_long videomemorysize = VIDEOMEMSIZE;
MODULE_PARM(videomemorysize, "l");
static struct display disp;
static const char *mode_option __initdata = NULL;
static struct fb_info fb_info;
static struct { u_char red, green, blue, pad; } palette[256];
static union {
#ifdef FBCON_HAS_CFB16
u16 cfb16[16];
#endif
#ifdef FBCON_HAS_CFB24
u32 cfb24[16];
#endif
#ifdef FBCON_HAS_CFB32
u32 cfb32[16];
#endif
} fbcon_cmap;
static char vfb_name[16] = "Virtual FB";
static struct fb_var_screeninfo vfb_default = {
/* 640x480, 8 bpp */
640, 480, 640, 480, 0, 0, 8, 0,
{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
0, 0, -1, -1, 0, 20000, 64, 64, 32, 32, 64, 2,
0, FB_VMODE_NONINTERLACED
static u32 vfb_pseudo_palette[17];
static struct display disp;
static struct fb_var_screeninfo vfb_default __initdata = {
xres: 640,
yres: 480,
xres_virtual: 640,
yres_virtual: 480,
bits_per_pixel: 8,
red: { 0, 8, 0 },
green: { 0, 8, 0 },
blue: { 0, 8, 0 },
activate: FB_ACTIVATE_TEST,
height: -1,
width: -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,
};
static int vfb_enable = 0; /* disabled by default */
static struct fb_fix_screeninfo vfb_fix __initdata = {
id: "Virtual FB",
type: FB_TYPE_PACKED_PIXELS,
visual: FB_VISUAL_PSEUDOCOLOR,
xpanstep: 1,
ypanstep: 1,
ywrapstep: 1,
accel: FB_ACCEL_NONE,
};
static int vfb_enable __initdata = 0; /* disabled by default */
MODULE_PARM(vfb_enable, "i");
/*
* Interface used by the world
*/
int vfb_init(void);
int vfb_setup(char *);
int vfb_setup(char*);
static int vfb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
static int vfb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int vfb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int vfb_check_var(struct fb_var_screeninfo *var,
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,
u_int transp, struct fb_info *info);
static int vfb_pan_display(struct fb_var_screeninfo *var, int con,
u_int transp, struct fb_info *info);
static int vfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info);
static int vfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info);
/*
* Interface to the low level console driver
*/
int vfb_init(void);
static int vfbcon_switch(int con, struct fb_info *info);
static int vfbcon_updatevar(int con, struct fb_info *info);
/*
* Internal routines
*/
static u_long get_line_length(int xres_virtual, int bpp);
static void vfb_encode_fix(struct fb_fix_screeninfo *fix,
struct fb_var_screeninfo *var);
static void set_color_bitfields(struct fb_var_screeninfo *var);
static int vfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info);
static int vfb_mmap(struct fb_info *info, struct file *file,
struct vm_area_struct *vma);
static struct fb_ops vfb_ops = {
owner: THIS_MODULE,
fb_get_fix: vfb_get_fix,
fb_get_var: vfb_get_var,
fb_set_var: vfb_set_var,
fb_get_cmap: vfb_get_cmap,
fb_get_fix: gen_get_fix,
fb_get_var: gen_get_var,
fb_set_var: gen_set_var,
fb_get_cmap: gen_set_cmap,
fb_set_cmap: gen_set_cmap,
fb_check_var: vfb_check_var,
fb_set_par: vfb_set_par,
fb_setcolreg: vfb_setcolreg,
fb_pan_display: vfb_pan_display,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
fb_mmap: vfb_mmap,
};
/*
* Get the Fixed Part of the Display
* Internal routines
*/
static int vfb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
static u_long get_line_length(int xres_virtual, int bpp)
{
struct fb_var_screeninfo *var;
if (con == -1)
var = &vfb_default;
else
var = &fb_display[con].var;
vfb_encode_fix(fix, var);
return 0;
}
u_long length;
length = xres_virtual * bpp;
length = (length + 31) & ~31;
length >>= 3;
return (length);
}
/*
* Get the User Defined Part of the Display
* Setting the video mode has been split into two parts.
* First part, xxxfb_check_var, must not write anything
* to hardware, it should only verify and adjust var.
* This means it doesn't alter par but it does use hardware
* data from it to check this var.
*/
static int vfb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
static int vfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
if (con == -1)
*var = vfb_default;
else
*var = fb_display[con].var;
set_color_bitfields(var);
return 0;
}
u_long line_length;
/*
* FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
* as FB_VMODE_SMOOTH_XPAN is only used internally
*/
/*
* Set the User Defined Part of the Display
*/
static int vfb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
int err, activate = var->activate;
int oldxres, oldyres, oldvxres, oldvyres, oldbpp;
u_long line_length;
if (var->vmode & FB_VMODE_CONUPDATE) {
var->vmode |= FB_VMODE_YWRAP;
var->xoffset = info->var.xoffset;
var->yoffset = info->var.yoffset;
}
struct display *display;
if (con >= 0)
display = &fb_display[con];
else
display = &disp; /* used during initialization */
/*
* Some very basic checks
*/
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 <= 8)
var->bits_per_pixel = 8;
else if (var->bits_per_pixel <= 16)
var->bits_per_pixel = 16;
else if (var->bits_per_pixel <= 24)
var->bits_per_pixel = 24;
else if (var->bits_per_pixel <= 32)
var->bits_per_pixel = 32;
else
return -EINVAL;
if (var->xres_virtual < var->xoffset + var->xres)
var->xres_virtual = var->xoffset + var->xres;
if (var->yres_virtual < var->yoffset + var->yres)
var->yres_virtual = var->yoffset + var->yres;
/*
* Memory limit
*/
line_length =
get_line_length(var->xres_virtual, var->bits_per_pixel);
if (line_length * var->yres_virtual > videomemorysize)
return -ENOMEM;
/*
* Now that we checked it we alter var. The reason being is that the video
* mode passed in might not work but slight changes to it might make it
* work. This way we let the user know what is acceptable.
*/
switch (var->bits_per_pixel) {
case 1:
case 8:
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 0;
var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break;
case 16: /* RGBA 5551 */
if (var->transp.length) {
var->red.offset = 0;
var->red.length = 5;
var->green.offset = 5;
var->green.length = 5;
var->blue.offset = 10;
var->blue.length = 5;
var->transp.offset = 15;
var->transp.length = 1;
} else { /* RGB 565 */
var->red.offset = 0;
var->red.length = 5;
var->green.offset = 5;
var->green.length = 6;
var->blue.offset = 11;
var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
}
break;
case 24: /* RGB 888 */
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 8;
var->green.length = 8;
var->blue.offset = 16;
var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break;
case 32: /* RGBA 8888 */
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 8;
var->green.length = 8;
var->blue.offset = 16;
var->blue.length = 8;
var->transp.offset = 24;
var->transp.length = 8;
break;
}
var->red.msb_right = 0;
var->green.msb_right = 0;
var->blue.msb_right = 0;
var->transp.msb_right = 0;
/*
* FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
* as FB_VMODE_SMOOTH_XPAN is only used internally
*/
return 0;
}
if (var->vmode & FB_VMODE_CONUPDATE) {
var->vmode |= FB_VMODE_YWRAP;
var->xoffset = display->var.xoffset;
var->yoffset = display->var.yoffset;
}
/* This routine actually sets the video mode. It's in here where we
* the hardware state info->par and fix which can be affected by the
* change in par. For this driver it doesn't do much.
*/
static int vfb_set_par(struct fb_info *info)
{
info->fix.line_length = get_line_length(info->var.xres_virtual,
info->var.bits_per_pixel);
return 0;
}
/*
* Some very basic checks
* Set a single color register. The values supplied are already
* rounded down to the hardware's capabilities (according to the
* entries in the var structure). Return != 0 for invalid regno.
*/
if (!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 <= 8)
var->bits_per_pixel = 8;
else if (var->bits_per_pixel <= 16)
var->bits_per_pixel = 16;
#if 0
/* fbcon doesn't support this (yet) */
else if (var->bits_per_pixel <= 24)
var->bits_per_pixel = 24;
else if (var->bits_per_pixel <= 32)
var->bits_per_pixel = 32;
#endif
else
return -EINVAL;
/*
* Memory limit
*/
line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
if (line_length*var->yres_virtual > videomemorysize)
return -ENOMEM;
set_color_bitfields(var);
if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
oldxres = display->var.xres;
oldyres = display->var.yres;
oldvxres = display->var.xres_virtual;
oldvyres = display->var.yres_virtual;
oldbpp = display->var.bits_per_pixel;
display->var = *var;
if (oldxres != var->xres || oldyres != var->yres ||
oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
oldbpp != var->bits_per_pixel) {
struct fb_fix_screeninfo fix;
vfb_encode_fix(&fix, var);
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
display->ypanstep = fix.ypanstep;
display->ywrapstep = fix.ywrapstep;
display->line_length = fix.line_length;
display->can_soft_blank = 1;
display->inverse = 0;
switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_MFB
case 1:
display->dispsw = &fbcon_mfb;
break;
#endif
#ifdef FBCON_HAS_CFB2
case 2:
display->dispsw = &fbcon_cfb2;
break;
#endif
#ifdef FBCON_HAS_CFB4
case 4:
display->dispsw = &fbcon_cfb4;
break;
#endif
#ifdef FBCON_HAS_CFB8
static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
if (regno >= 256) /* no. of hw registers */
return 1;
/*
* Program hardware... do anything you want with transp
*/
/* grayscale works only partially under directcolor */
if (info->var.grayscale) {
/* grayscale = 0.30*R + 0.59*G + 0.11*B */
red = green = blue =
(red * 77 + green * 151 + blue * 28) >> 8;
}
/* Directcolor:
* var->{color}.offset contains start of bitfield
* var->{color}.length contains length of bitfield
* {hardwarespecific} contains width of RAMDAC
* cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
* RAMDAC[X] is programmed to (red, green, blue)
*
* Pseudocolor:
* uses offset = 0 && length = RAMDAC register width.
* var->{color}.offset is 0
* var->{color}.length contains widht of DAC
* cmap is not used
* RAMDAC[X] is programmed to (red, green, blue)
* Truecolor:
* does not use DAC. Usually 3 are present.
* var->{color}.offset contains start of bitfield
* var->{color}.length contains length of bitfield
* cmap is programmed to (red << red.offset) | (green << green.offset) |
* (blue << blue.offset) | (transp << transp.offset)
* RAMDAC does not exist
*/
#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
switch (info->fix.visual) {
case FB_VISUAL_TRUECOLOR:
case FB_VISUAL_PSEUDOCOLOR:
red = CNVT_TOHW(red, info->var.red.length);
green = CNVT_TOHW(green, info->var.green.length);
blue = CNVT_TOHW(blue, info->var.blue.length);
transp = CNVT_TOHW(transp, info->var.transp.length);
break;
case FB_VISUAL_DIRECTCOLOR:
red = CNVT_TOHW(red, 8); /* expect 8 bit DAC */
green = CNVT_TOHW(green, 8);
blue = CNVT_TOHW(blue, 8);
/* hey, there is bug in transp handling... */
transp = CNVT_TOHW(transp, 8);
break;
}
#undef CNVT_TOHW
/* Truecolor has hardware independent palette */
if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
u32 v;
if (regno >= 16)
return 1;
v = (red << info->var.red.offset) |
(green << info->var.green.offset) |
(blue << info->var.blue.offset) |
(transp << info->var.transp.offset);
switch (info->var.bits_per_pixel) {
case 8:
display->dispsw = &fbcon_cfb8;
break;
#endif
#ifdef FBCON_HAS_CFB16
break;
case 16:
display->dispsw = &fbcon_cfb16;
display->dispsw_data = fbcon_cmap.cfb16;
break;
#endif
#ifdef FBCON_HAS_CFB24
((u32 *) (info->pseudo_palette))[regno] = v;
break;
case 24:
display->dispsw = &fbcon_cfb24;
display->dispsw_data = fbcon_cmap.cfb24;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
display->dispsw = &fbcon_cfb32;
display->dispsw_data = fbcon_cmap.cfb32;
break;
#endif
default:
display->dispsw = &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);
((u32 *) (info->pseudo_palette))[regno] = v;
break;
}
return 0;
}
}
return 0;
return 0;
}
/*
* Pan or Wrap the Display
*
* This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
*/
static int vfb_pan_display(struct fb_var_screeninfo *var, int con,
static int vfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
if (var->vmode & FB_VMODE_YWRAP) {
if (var->yoffset < 0 ||
var->yoffset >= fb_display[con].var.yres_virtual ||
var->xoffset)
return -EINVAL;
} else {
if (var->xoffset+fb_display[con].var.xres >
fb_display[con].var.xres_virtual ||
var->yoffset+fb_display[con].var.yres >
fb_display[con].var.yres_virtual)
return -EINVAL;
}
fb_display[con].var.xoffset = var->xoffset;
fb_display[con].var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
fb_display[con].var.vmode |= FB_VMODE_YWRAP;
else
fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
return 0;
if (var->vmode & FB_VMODE_YWRAP) {
if (var->yoffset < 0
|| var->yoffset >= info->var.yres_virtual
|| var->xoffset)
return -EINVAL;
} else {
if (var->xoffset + var->xres > info->var.xres_virtual ||
var->yoffset + var->yres > info->var.yres_virtual)
return -EINVAL;
}
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
info->var.vmode |= FB_VMODE_YWRAP;
else
info->var.vmode &= ~FB_VMODE_YWRAP;
return 0;
}
/*
* Get the Colormap
* Most drivers don't need their own mmap function
*/
static int vfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
static int vfb_mmap(struct fb_info *info, struct file *file,
struct vm_area_struct *vma)
{
if (con == info->currcon) /* current console? */
return fb_get_cmap(cmap, kspc, vfb_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
cmap, kspc ? 0 : 2);
return 0;
return -EINVAL;
}
int __init vfb_setup(char *options)
{
char *this_opt;
char *this_opt;
fb_info.fontname[0] = '\0';
vfb_enable = 1;
vfb_enable = 1;
if (!options || !*options)
return 1;
if (!options || !*options)
return 0;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!strncmp(this_opt, "font:", 5))
strcpy(fb_info.fontname, this_opt+5);
}
return 0;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt)
continue;
if (!strncmp(this_opt, "disable", 7))
vfb_enable = 0;
}
return 1;
}
/*
* Initialisation
*/
int __init vfb_init(void)
{
if (!vfb_enable)
return -ENXIO;
if (!(videomemory = (u_long)vmalloc(videomemorysize)))
return -ENOMEM;
strcpy(fb_info.modename, vfb_name);
fb_info.changevar = NULL;
fb_info.node = NODEV;
fb_info.fbops = &vfb_ops;
fb_info.screen_base = (char *)videomemory;
fb_info.disp = &disp;
fb_info.currcon = -1;
fb_info.switch_con = &vfbcon_switch;
fb_info.updatevar = &vfbcon_updatevar;
fb_info.flags = FBINFO_FLAG_DEFAULT;
vfb_set_var(&vfb_default, -1, &fb_info);
if (register_framebuffer(&fb_info) < 0) {
vfree((void *)videomemory);
return -EINVAL;
}
printk(KERN_INFO "fb%d: Virtual frame buffer device, using %ldK of video memory\n",
GET_FB_IDX(fb_info.node), videomemorysize>>10);
return 0;
}
static int vfbcon_switch(int con, struct fb_info *info)
{
/* Do we have to save the colormap? */
if (fb_display[info->currcon].cmap.len)
fb_get_cmap(&fb_display[info->currcon].cmap, 1, vfb_getcolreg, info);
info->currcon = con;
/* Install new colormap */
do_install_cmap(con, info);
return 0;
}
/*
* Update the `var' structure (called by fbcon.c)
*/
static int vfbcon_updatevar(int con, struct fb_info *info)
{
/* Nothing */
return 0;
}
static u_long get_line_length(int xres_virtual, int bpp)
{
u_long length;
length = xres_virtual*bpp;
length = (length+31)&-32;
length >>= 3;
return(length);
}
static void vfb_encode_fix(struct fb_fix_screeninfo *fix,
struct fb_var_screeninfo *var)
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, vfb_name);
fix->smem_start = videomemory;
fix->smem_len = videomemorysize;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
switch (var->bits_per_pixel) {
case 1:
fix->visual = FB_VISUAL_MONO01;
break;
case 2:
case 4:
case 8:
fix->visual = FB_VISUAL_PSEUDOCOLOR;
break;
case 16:
case 24:
case 32:
fix->visual = FB_VISUAL_TRUECOLOR;
break;
}
fix->ywrapstep = 1;
fix->xpanstep = 1;
fix->ypanstep = 1;
fix->line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
}
static void set_color_bitfields(struct fb_var_screeninfo *var)
{
switch (var->bits_per_pixel) {
case 1:
case 8:
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 0;
var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break;
case 16: /* RGB 565 */
var->red.offset = 0;
var->red.length = 5;
var->green.offset = 5;
var->green.length = 6;
var->blue.offset = 11;
var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
break;
case 24: /* RGB 888 */
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 8;
var->green.length = 8;
var->blue.offset = 16;
var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break;
case 32: /* RGBA 8888 */
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 8;
var->green.length = 8;
var->blue.offset = 16;
var->blue.length = 8;
var->transp.offset = 24;
var->transp.length = 8;
break;
}
var->red.msb_right = 0;
var->green.msb_right = 0;
var->blue.msb_right = 0;
var->transp.msb_right = 0;
}
/*
* Read a single color register and split it into
* colors/transparent. Return != 0 for invalid regno.
*/
static int vfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info)
{
if (regno > 255)
return 1;
*red = (palette[regno].red<<8) | palette[regno].red;
*green = (palette[regno].green<<8) | palette[regno].green;
*blue = (palette[regno].blue<<8) | palette[regno].blue;
*transp = 0;
return 0;
}
/*
* Set a single color register. The values supplied are already
* rounded down to the hardware's capabilities (according to the
* entries in the var structure). Return != 0 for invalid regno.
*/
int retval;
if (!vfb_enable)
return -ENXIO;
/*
* For real video cards we use ioremap.
*/
if (!(videomemory = vmalloc(videomemorysize)))
return -ENOMEM;
/*
* VFB must clear memory to prevent kernel info
* leakage into userspace
* VGA-based drivers MUST NOT clear memory if
* they want to be able to take over vgacon
*/
memset(videomemory, 0, videomemorysize);
fb_info.screen_base = videomemory;
fb_info.node = NODEV;
fb_info.fbops = &vfb_ops;
retval = fb_find_mode(&fb_info.var, &fb_info, mode_option,
NULL, 0, NULL, 8);
if (!retval || (retval == 4))
fb_info.var = vfb_default;
fb_info.fix = vfb_fix;
fb_info.pseudo_palette = &vfb_pseudo_palette;
fb_info.flags = FBINFO_FLAG_DEFAULT;
strcpy(fb_info.modename, vesafb_fix.id);
fb_info.changevar = NULL;
fb_info.currcon = -1;
fb_info.disp = &disp;
fb_info.switch_con = gen_switch;
fb_info.updatevar = gen_update_var;
fb_alloc_cmap(&fb_info.cmap, 256, 0);
if (register_framebuffer(&fb_info) < 0) {
vfree(videomemory);
return -EINVAL;
}
static int vfb_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;
red >>= 8;
green >>= 8;
blue >>= 8;
palette[regno].red = red;
palette[regno].green = green;
palette[regno].blue = blue;
return 0;
printk(KERN_INFO
"fb%d: Virtual frame buffer device, using %ldK of video memory\n",
GET_FB_IDX(fb_info.node), videomemorysize >> 10);
return 0;
}
#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
static void __exit vfb_cleanup(void)
{
return vfb_init();
unregister_framebuffer(&fb_info);
vfree(videomemory);
}
void cleanup_module(void)
{
unregister_framebuffer(&fb_info);
vfree((void *)videomemory);
}
module_init(vfb_init);
module_exit(vfb_cleanup);
#endif /* MODULE */
MODULE_LICENSE("GPL");
#endif /* MODULE */
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