summaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Config.in42
-rw-r--r--drivers/video/Makefile16
-rw-r--r--drivers/video/atafb.c46
-rw-r--r--drivers/video/atyfb.c178
-rw-r--r--drivers/video/bwtwofb.c3
-rw-r--r--drivers/video/cgfourteenfb.c3
-rw-r--r--drivers/video/cgsixfb.c38
-rw-r--r--drivers/video/cgthreefb.c3
-rw-r--r--drivers/video/clgenfb.c15
-rw-r--r--drivers/video/controlfb.c112
-rw-r--r--drivers/video/creatorfb.c166
-rw-r--r--drivers/video/cvisionppc.h4
-rw-r--r--drivers/video/fbcon-afb.c14
-rw-r--r--drivers/video/fbcon-cfb16.c8
-rw-r--r--drivers/video/fbcon-cfb2.c8
-rw-r--r--drivers/video/fbcon-cfb24.c6
-rw-r--r--drivers/video/fbcon-cfb32.c6
-rw-r--r--drivers/video/fbcon-cfb4.c8
-rw-r--r--drivers/video/fbcon-cfb8.c10
-rw-r--r--drivers/video/fbcon-ilbm.c14
-rw-r--r--drivers/video/fbcon-iplan2p2.c6
-rw-r--r--drivers/video/fbcon-iplan2p4.c6
-rw-r--r--drivers/video/fbcon-iplan2p8.c6
-rw-r--r--drivers/video/fbcon-mac.c2
-rw-r--r--drivers/video/fbcon-mfb.c8
-rw-r--r--drivers/video/fbcon-vga.c6
-rw-r--r--drivers/video/fbcon.c434
-rw-r--r--drivers/video/fbgen.c3
-rw-r--r--drivers/video/fbmem.c73
-rw-r--r--drivers/video/fm2fb.c572
-rw-r--r--drivers/video/igafb.c2
-rw-r--r--drivers/video/leofb.c257
-rw-r--r--drivers/video/matroxfb.c77
-rw-r--r--drivers/video/mdacon.c2
-rw-r--r--drivers/video/offb.c2
-rw-r--r--drivers/video/pm2fb.c571
-rw-r--r--drivers/video/pm2fb.h39
-rw-r--r--drivers/video/promcon.c23
-rw-r--r--drivers/video/q40fb.c362
-rw-r--r--drivers/video/retz3fb.c10
-rw-r--r--drivers/video/sbusfb.c22
-rw-r--r--drivers/video/sgivwfb.c1037
-rw-r--r--drivers/video/sgivwfb.h660
-rw-r--r--drivers/video/skeletonfb.c10
-rw-r--r--drivers/video/tcxfb.c3
-rw-r--r--drivers/video/vesafb.c17
-rw-r--r--drivers/video/virgefb.c347
47 files changed, 4442 insertions, 815 deletions
diff --git a/drivers/video/Config.in b/drivers/video/Config.in
index cb04cf0c0..3cbc22762 100644
--- a/drivers/video/Config.in
+++ b/drivers/video/Config.in
@@ -4,12 +4,17 @@
if [ "$CONFIG_FB" = "y" ]; then
define_bool CONFIG_DUMMY_CONSOLE y
- if [ "$CONFIG_APUS" = "y" ]; then
- bool 'Permedia2 support' CONFIG_FB_PM2
- if [ "$CONFIG_FB_PM2" = "y" ]; then
- bool ' enable FIFO disconnect feature' CONFIG_FB_PM2_FIFO_DISCONNECT
- if [ "$CONFIG_APUS" = "y" ]; then
- bool ' Phase5 CVisionPPC/BVisionPPC support' CONFIG_FB_PM2_CVPPC
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_PCI" = "y" ]; then
+ bool 'Permedia2 support (experimental)' CONFIG_FB_PM2
+ if [ "$CONFIG_FB_PM2" = "y" ]; then
+ if [ "$CONFIG_PCI" = "y" ]; then
+ bool ' enable FIFO disconnect feature' CONFIG_FB_PM2_FIFO_DISCONNECT
+ bool ' generic Permedia2 PCI board support' CONFIG_FB_PM2_PCI
+ fi
+ if [ "$CONFIG_AMIGA" = "y" ]; then
+ bool ' Phase5 CVisionPPC/BVisionPPC support' CONFIG_FB_PM2_CVPPC
+ fi
fi
fi
fi
@@ -19,6 +24,9 @@ if [ "$CONFIG_FB" = "y" ]; then
if [ "$CONFIG_APOLLO" = "y" ]; then
define_bool CONFIG_FB_APOLLO y
fi
+ if [ "$CONFIG_Q40" = "y" ]; then
+ define_bool CONFIG_FB_Q40 y
+ fi
if [ "$CONFIG_AMIGA" = "y" ]; then
bool 'Amiga native chipset support' CONFIG_FB_AMIGA
if [ "$CONFIG_FB_AMIGA" != "n" ]; then
@@ -33,6 +41,7 @@ if [ "$CONFIG_FB" = "y" ]; then
bool 'Amiga CyberVision3D support (experimental)' CONFIG_FB_VIRGE
tristate 'Amiga RetinaZ3 support' CONFIG_FB_RETINAZ3
tristate 'Amiga CLgen driver' CONFIG_FB_CLGEN
+ bool 'Amiga FrameMaster II/Rainbow II support (experimental)' CONFIG_FB_FM2
fi
fi
if [ "$CONFIG_ATARI" = "y" ]; then
@@ -64,6 +73,9 @@ if [ "$CONFIG_FB" = "y" ]; then
bool 'VESA VGA graphics console' CONFIG_FB_VESA
define_bool CONFIG_VIDEO_SELECT y
fi
+ if [ "$CONFIG_VISWS" = "y" ]; then
+ tristate 'SGI Visual Workstation framebuffer support' CONFIG_FB_SGIVW
+ fi
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
if [ "$CONFIG_PCI" != "n" ]; then
tristate 'Matrox acceleration' CONFIG_FB_MATROX
@@ -166,7 +178,8 @@ if [ "$CONFIG_FB" = "y" ]; then
"$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 \
- "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_PM2" = "y" ]; then
+ "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_PM2" = "y" -o
+ "$CONFIG_FB_SGIVW = "y" ]; then
define_bool CONFIG_FBCON_CFB8 y
else
if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
@@ -179,28 +192,31 @@ if [ "$CONFIG_FB" = "y" ]; then
"$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 \
- "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" ]; then
+ "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
+ "$CONFIG_FB_SGIVW = "m" ]; then
define_bool CONFIG_FBCON_CFB8 m
fi
fi
if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \
"$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_VESA" = "y" -o \
"$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \
+ "$CONFIG_FB_Q40" = "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 \
"$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
- "$CONFIG_FB_PM2" = "y" ]; then
+ "$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" ]; then
define_bool CONFIG_FBCON_CFB16 y
else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
"$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_VESA" = "m" -o \
"$CONFIG_FB_VIRTUAL" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \
+ "$CONFIG_FB_Q40" = "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 \
"$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
- "$CONFIG_FB_PM2" = "m" ]; then
+ "$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_SGIVW" = "m" ]; then
define_bool CONFIG_FBCON_CFB16 m
fi
fi
@@ -219,14 +235,16 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_VESA" = "y" -o "$CONFIG_FB_VIRTUAL" = "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" ]; then
+ "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
+ "$CONFIG_FB_FM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" ]; then
define_bool CONFIG_FBCON_CFB32 y
else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
"$CONFIG_FB_VESA" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_TGA" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
- "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" ]; then
+ "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
+ "$CONFIG_FB_SGIVW" = "m" ]; then
define_bool CONFIG_FBCON_CFB32 m
fi
fi
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 5c049664a..25b78efb9 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -88,6 +88,10 @@ ifeq ($(CONFIG_FB_APOLLO),y)
L_OBJS += dnfb.o
endif
+ifeq ($(CONFIG_FB_Q40),y)
+L_OBJS += q40fb.o
+endif
+
ifeq ($(CONFIG_FB_ATARI),y)
L_OBJS += atafb.o
else
@@ -128,6 +132,14 @@ else
endif
endif
+ifeq ($(CONFIG_FB_SGIVW),y)
+L_OBJS += sgivwfb.o
+else
+ ifeq ($(CONFIG_FB_SGIVW),m)
+ M_OBJS += sgivwfb.o
+ endif
+endif
+
ifeq ($(CONFIG_FB_MAC),y)
L_OBJS += macfb.o
endif
@@ -198,6 +210,10 @@ ifdef CONFIG_FB_G364
L_OBJS := $(L_OBJS) g364fb.o
endif
+ifdef CONFIG_FB_FM2
+L_OBJS := $(L_OBJS) fm2fb.o
+endif
+
ifeq ($(CONFIG_FB_SBUS),y)
L_OBJS += sbusfb.o
ifeq ($(CONFIG_FB_CREATOR),y)
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index f33d118b7..e35a79e0b 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -103,7 +103,7 @@ static int sttt_xres_virtual=640,sttt_yres_virtual=400;
static int ovsc_offset=0, ovsc_addlen=0;
static struct atafb_par {
- unsigned long screen_base;
+ void *screen_base;
int yres_virtual;
#if defined ATAFB_TT || defined ATAFB_STE
union {
@@ -167,8 +167,8 @@ static int DontCalcRes = 0;
static struct fb_info fb_info;
-static unsigned long screen_base; /* base address of screen */
-static unsigned long real_screen_base; /* (only for Overscan) */
+static void *screen_base; /* base address of screen */
+static void *real_screen_base; /* (only for Overscan) */
static int screen_len;
@@ -193,7 +193,7 @@ static unsigned external_yres;
static unsigned external_depth;
static int external_pmode;
-static unsigned long external_addr = 0;
+static void *external_addr = 0;
static unsigned long external_len;
static unsigned long external_vgaiobase = 0;
static unsigned int external_bitspercol = 6;
@@ -299,7 +299,7 @@ extern unsigned char fontdata_8x16[];
* Read a single color register and split it into
* colors/transparent. Return != 0 for invalid regno.
*
- * void (*set_screen_base)( unsigned long s_base )
+ * void (*set_screen_base)(void *s_base)
* Set the base address of the displayed frame buffer. Only called
* if yres_virtual > yres or xres_virtual > xres.
*
@@ -328,7 +328,7 @@ static struct fb_hwswitch {
int (*setcolreg)( unsigned regno, unsigned red,
unsigned green, unsigned blue,
unsigned transp, struct fb_info *info );
- void (*set_screen_base)( unsigned long s_base );
+ void (*set_screen_base)(void *s_base);
int (*blank)( int blank_mode );
int (*pan_display)( struct fb_var_screeninfo *var,
struct atafb_par *par);
@@ -464,7 +464,7 @@ static int tt_encode_fix( struct fb_fix_screeninfo *fix,
int mode;
strcpy(fix->id,"Atari Builtin");
- fix->smem_start = (char *)real_screen_base;
+ fix->smem_start = real_screen_base;
fix->smem_len = screen_len;
fix->type=FB_TYPE_INTERLEAVED_PLANES;
fix->type_aux=2;
@@ -797,7 +797,7 @@ static int falcon_encode_fix( struct fb_fix_screeninfo *fix,
struct atafb_par *par )
{
strcpy(fix->id, "Atari Builtin");
- fix->smem_start = (char *)real_screen_base;
+ fix->smem_start = real_screen_base;
fix->smem_len = screen_len;
fix->type = FB_TYPE_INTERLEAVED_PLANES;
fix->type_aux = 2;
@@ -1760,7 +1760,7 @@ static int stste_encode_fix( struct fb_fix_screeninfo *fix,
int mode;
strcpy(fix->id,"Atari Builtin");
- fix->smem_start = (char *)real_screen_base;
+ fix->smem_start = real_screen_base;
fix->smem_len = screen_len;
fix->type = FB_TYPE_INTERLEAVED_PLANES;
fix->type_aux = 2;
@@ -2024,7 +2024,7 @@ static int stste_detect( void )
return 1;
}
-static void stste_set_screen_base(unsigned long s_base)
+static void stste_set_screen_base(void *s_base)
{
unsigned long addr;
addr= virt_to_phys(s_base);
@@ -2104,8 +2104,8 @@ static int ext_encode_fix( struct fb_fix_screeninfo *fix,
{
strcpy(fix->id,"Unknown Extern");
- fix->smem_start=(char *)external_addr;
- fix->smem_len=(external_len + PAGE_SIZE -1) & PAGE_MASK;
+ fix->smem_start=external_addr;
+ fix->smem_len = PAGE_ALIGN(external_len);
if (external_depth == 1) {
fix->type = FB_TYPE_PACKED_PIXELS;
/* The letters 'n' and 'i' in the "atavideo=external:" stand
@@ -2295,7 +2295,7 @@ static int ext_detect( void )
/* ------ This is the same for most hardware types -------- */
-static void set_screen_base(unsigned long s_base)
+static void set_screen_base(void *s_base)
{
unsigned long addr;
addr= virt_to_phys(s_base);
@@ -2804,15 +2804,13 @@ __initfunc(void atafb_init(void))
#ifdef ATAFB_EXT
if (!external_addr) {
#endif /* ATAFB_EXT */
- mem_req = default_mem_req + ovsc_offset +
- ovsc_addlen;
- mem_req = ((mem_req + PAGE_SIZE - 1) & PAGE_MASK) + PAGE_SIZE;
- screen_base = (unsigned long)atari_stram_alloc(mem_req, NULL,
- "atafb");
+ mem_req = default_mem_req + ovsc_offset + ovsc_addlen;
+ mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE;
+ screen_base = atari_stram_alloc(mem_req, NULL, "atafb");
if (!screen_base)
panic("Cannot allocate screen memory");
- memset((char *) screen_base, 0, mem_req);
- pad = ((screen_base + PAGE_SIZE-1) & PAGE_MASK) - screen_base;
+ memset(screen_base, 0, mem_req);
+ pad = -(unsigned long)screen_base & (PAGE_SIZE-1);
screen_base+=pad;
real_screen_base=screen_base+ovsc_offset;
screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK;
@@ -2820,9 +2818,9 @@ __initfunc(void atafb_init(void))
if (CPU_IS_040_OR_060) {
/* On a '040+, the cache mode of video RAM must be set to
* write-through also for internal video hardware! */
- cache_push( virt_to_phys(screen_base), screen_len );
- kernel_set_cachemode( screen_base, screen_len,
- IOMAP_WRITETHROUGH );
+ cache_push(virt_to_phys(screen_base), screen_len);
+ kernel_set_cachemode(screen_base, screen_len,
+ IOMAP_WRITETHROUGH);
}
#ifdef ATAFB_EXT
}
@@ -2836,7 +2834,7 @@ __initfunc(void atafb_init(void))
screen_base =
real_screen_base = external_addr;
screen_len = external_len & PAGE_MASK;
- memset ((char *) screen_base, 0, external_len);
+ memset (screen_base, 0, external_len);
}
#endif /* ATAFB_EXT */
diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c
index 6a3625d23..1f9e41ac8 100644
--- a/drivers/video/atyfb.c
+++ b/drivers/video/atyfb.c
@@ -1,4 +1,4 @@
-/* $Id: atyfb.c,v 1.98 1999/01/14 08:50:53 geert Exp $
+/* $Id: atyfb.c,v 1.106 1999/04/16 11:20:49 geert Exp $
* linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
*
* Copyright (C) 1997-1998 Geert Uytterhoeven
@@ -66,6 +66,8 @@
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <video/macmodes.h>
+#include <asm/adb.h>
+#include <asm/pmu.h>
#endif
#ifdef __sparc__
#include <asm/pbm.h>
@@ -383,7 +385,6 @@ void atyfb_of_init(struct device_node *dp);
#endif
void atyfb_setup(char *options, int *ints);
-
static int currcon = 0;
static struct fb_ops atyfb_ops = {
@@ -439,10 +440,10 @@ static struct aty_features {
/* mach64CT family / mach64GT (3D RAGE) class */
{ 0x4c42, 0x4c42, "3D RAGE LT PRO (AGP)" },
- { 0x4c42, 0x4c44, "3D RAGE LT PRO" },
- { 0x4c42, 0x4c47, "3D RAGE LT PRO" },
- { 0x4c42, 0x4c49, "3D RAGE LT PRO" },
- { 0x4c42, 0x4c50, "3D RAGE LT PRO" },
+ { 0x4c44, 0x4c44, "3D RAGE LT PRO" },
+ { 0x4c47, 0x4c47, "3D RAGE LT PRO" },
+ { 0x4c49, 0x4c49, "3D RAGE LT PRO" },
+ { 0x4c50, 0x4c50, "3D RAGE LT PRO" },
{ 0x4c54, 0x4c54, "3D RAGE LT" },
{ 0x4754, 0x4754, "3D RAGE (GT)" },
{ 0x4755, 0x4755, "3D RAGE II+ (GTB)" },
@@ -777,7 +778,8 @@ aty_set_cursor_color(struct fb_info_aty *fb, u8 *pixel,
return;
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -804,7 +806,8 @@ aty_set_cursor_shape(struct fb_info_aty *fb)
return;
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -838,7 +841,8 @@ aty_set_cursor(struct fb_info_aty *fb, int on)
return;
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -908,7 +912,8 @@ atyfb_cursor(struct display *p, int mode, int x, int y)
return;
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -1282,7 +1287,7 @@ static int aty_crtc_to_var(const struct crtc *crtc,
bpp = 16;
var->red.offset = 11;
var->red.length = 5;
- var->green.offset = 6;
+ var->green.offset = 5;
var->green.length = 6;
var->blue.offset = 0;
var->blue.length = 5;
@@ -1642,30 +1647,24 @@ static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
pll_ext_cntl = mpostdiv; /* xclk == mclk */
switch (vclk_post_div) {
- case 1:
- vpostdiv = 0;
- break;
case 2:
vpostdiv = 1;
break;
case 3:
- vpostdiv = 0;
pll_ext_cntl |= 0x10;
+ case 1:
+ vpostdiv = 0;
break;
+ case 6:
+ pll_ext_cntl |= 0x10;
case 4:
vpostdiv = 2;
break;
- case 6:
- vpostdiv = 2;
+ case 12:
pll_ext_cntl |= 0x10;
- break;
case 8:
vpostdiv = 3;
break;
- case 12:
- vpostdiv = 3;
- pll_ext_cntl |= 0x10;
- break;
}
vclk_post_div = vpostdiv;
@@ -1688,7 +1687,7 @@ static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per)
1, 2, 4, 8,
3, 0, 6, 12
};
- u8 vpostdiv = vclk_post_div_tab[((pll_ext_cntl & 0x10) >> 1) |
+ u8 vpostdiv = vclk_post_div_tab[((pll_ext_cntl & 0x10) >> 2) |
(vclk_post_div & 3)];
if (vpostdiv == 0)
return -EINVAL;
@@ -2112,7 +2111,8 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
if (info->fb_info.changevar)
(*info->fb_info.changevar)(con);
}
- if (con == currcon)
+ if (!info->fb_info.display_fg ||
+ info->fb_info.display_fg->vc_num == con)
atyfb_set_par(&par, info);
if (oldbpp != var->bits_per_pixel) {
if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
@@ -2157,7 +2157,7 @@ static int atyfb_pan_display(struct fb_var_screeninfo *var, int con,
static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
- if (con == currcon) /* current console? */
+ if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */
return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
@@ -2176,16 +2176,21 @@ static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
int err;
+ struct display *disp;
- if (!fb_display[con].cmap.len) { /* no colormap allocated? */
- int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
- if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0)))
+ if (con >= 0)
+ disp = &fb_display[con];
+ else
+ disp = info->disp;
+ if (!disp->cmap.len) { /* no colormap allocated? */
+ int size = disp->var.bits_per_pixel == 16 ? 32 : 256;
+ if ((err = fb_alloc_cmap(&disp->cmap, size, 0)))
return err;
}
- if (con == currcon) /* current console? */
+ if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */
return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info);
else
- fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+ fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
return 0;
}
@@ -2196,6 +2201,12 @@ static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
#ifdef __sparc__
struct fb_info_aty *fb = (struct fb_info_aty *)info;
struct fbtype fbtyp;
+ struct display *disp;
+
+ if (con >= 0)
+ disp = &fb_display[con];
+ else
+ disp = info->disp;
switch (cmd) {
case FBIOGTYPE:
@@ -2203,7 +2214,7 @@ static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
fbtyp.fb_width = fb->current_par.crtc.vxres;
fbtyp.fb_height = fb->current_par.crtc.vyres;
fbtyp.fb_depth = fb->current_par.crtc.bpp;
- fbtyp.fb_cmsize = fb_display[con].cmap.len;
+ fbtyp.fb_cmsize = disp->cmap.len;
fbtyp.fb_size = fb->total_vram;
copy_to_user_ret((struct fbtype *)arg, &fbtyp, sizeof(fbtyp), -EFAULT);
break;
@@ -2321,8 +2332,6 @@ static int atyfb_mmap(struct fb_info *info, struct file *file,
if (!map_size)
return -EINVAL;
- vma->vm_file = file;
- file->f_count++;
vma->vm_flags |= VM_IO;
if (!fb->mmaped) {
@@ -2353,10 +2362,10 @@ static void atyfb_save_palette(struct fb_info *fb, int enter)
for (i = 0; i < 256; i++) {
tmp = aty_ld_8(DAC_CNTL, info) & 0xfc;
- if ((Gx == GT_CHIP_ID) || (Gx == GU_CHIP_ID) ||
- (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) ||
- (Gx == GD_CHIP_ID) || (Gx == GI_CHIP_ID) ||
- (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID))
+ if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
+ Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
+ Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
+ Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID)
tmp |= 0x2;
aty_st_8(DAC_CNTL, tmp, info);
aty_st_8(DAC_MASK, 0xff, info);
@@ -2785,7 +2794,7 @@ __initfunc(void atyfb_init(void))
*/
for (i = 0; i < 6 && pdev->base_address[i]; i++)
/* nothing */;
- j = i + 3;
+ j = i + 4;
info->mmap_map = kmalloc(j * sizeof(*info->mmap_map), GFP_ATOMIC);
if (!info->mmap_map) {
@@ -2813,15 +2822,33 @@ __initfunc(void atyfb_init(void))
size &= ~1;
size = ~(size) + 1;
+ /*
+ * Map the framebuffer a second time, this time without
+ * the braindead _PAGE_IE setting. This is used by the
+ * fixed Xserver, but we need to maintain the old mapping
+ * to stay compatible with older ones...
+ */
if (base == addr) {
- info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
- info->mmap_map[j].poff = __pa((base + 0x800000)
- & PAGE_MASK);
- info->mmap_map[j].size = 0x800000;
- info->mmap_map[j].prot_mask = _PAGE_CACHE;
- info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE;
- size -= 0x800000;
- j++;
+ info->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
+ info->mmap_map[j].poff = __pa(base & PAGE_MASK);
+ info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
+ info->mmap_map[j].prot_mask = _PAGE_CACHE;
+ info->mmap_map[j].prot_flag = _PAGE_E;
+ j++;
+ }
+
+ /*
+ * Here comes the old framebuffer mapping with _PAGE_IE
+ * set for the big endian half of the framebuffer...
+ */
+ if (base == addr) {
+ info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
+ info->mmap_map[j].poff = __pa((base+0x800000) & PAGE_MASK);
+ info->mmap_map[j].size = 0x800000;
+ info->mmap_map[j].prot_mask = _PAGE_CACHE;
+ info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE;
+ size -= 0x800000;
+ j++;
}
info->mmap_map[j].voff = pbase & PAGE_MASK;
@@ -3296,6 +3323,11 @@ static void atyfbcon_blank(int blank, struct fb_info *fb)
struct fb_info_aty *info = (struct fb_info_aty *)fb;
u8 gen_cntl;
+#if defined(CONFIG_PPC)
+ if ((_machine == _MACH_Pmac) && blank)
+ pmu_enable_backlight(0);
+#endif
+
gen_cntl = aty_ld_8(CRTC_GEN_CNTL, info);
if (blank > 0)
switch (blank-1) {
@@ -3315,6 +3347,11 @@ static void atyfbcon_blank(int blank, struct fb_info *fb)
else
gen_cntl &= ~(0x4c);
aty_st_8(CRTC_GEN_CNTL, gen_cntl, info);
+
+#if defined(CONFIG_PPC)
+ if ((_machine == _MACH_Pmac) && !blank)
+ pmu_enable_backlight(1);
+#endif
}
@@ -3359,9 +3396,10 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
info->palette[regno].green = green;
info->palette[regno].blue = blue;
i = aty_ld_8(DAC_CNTL, info) & 0xfc;
- if ((Gx == GT_CHIP_ID) || (Gx == GU_CHIP_ID) || (Gx == LG_CHIP_ID) ||
- (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) || (Gx == GI_CHIP_ID) ||
- (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID))
+ if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
+ Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
+ Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
+ Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID)
i |= 0x2; /*DAC_CNTL|0x2 turns off the extra brightness for gt*/
aty_st_8(DAC_CNTL, i, info);
aty_st_8(DAC_MASK, 0xff, info);
@@ -3545,7 +3583,8 @@ static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx,
#ifdef __sparc__
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -3567,7 +3606,8 @@ static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy,
#ifdef __sparc__
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -3591,7 +3631,8 @@ static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, int c,
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -3607,7 +3648,8 @@ static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -3622,7 +3664,8 @@ static void fbcon_aty8_clear_margins(struct vc_data *conp, struct display *p,
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -3645,7 +3688,8 @@ static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, int c,
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -3661,7 +3705,8 @@ static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -3676,7 +3721,8 @@ static void fbcon_aty16_clear_margins(struct vc_data *conp, struct display *p,
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -3699,7 +3745,8 @@ static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, int c,
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -3715,7 +3762,8 @@ static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p,
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -3730,7 +3778,8 @@ static void fbcon_aty24_clear_margins(struct vc_data *conp, struct display *p,
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -3753,7 +3802,8 @@ static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, int c,
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -3769,7 +3819,8 @@ static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
@@ -3784,7 +3835,8 @@ static void fbcon_aty32_clear_margins(struct vc_data *conp, struct display *p,
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
#ifdef __sparc__
- if (fb->mmaped && currcon == fb->vtconsole)
+ if (fb->mmaped && (!fb->fb_info.display_fg
+ || fb->fb_info.display_fg->vc_num == fb->vtconsole))
return;
#endif
diff --git a/drivers/video/bwtwofb.c b/drivers/video/bwtwofb.c
index 00db47d10..0735ca1b3 100644
--- a/drivers/video/bwtwofb.c
+++ b/drivers/video/bwtwofb.c
@@ -1,4 +1,4 @@
-/* $Id: bwtwofb.c,v 1.6 1998/09/15 15:45:35 jj Exp $
+/* $Id: bwtwofb.c,v 1.7 1999/01/26 10:55:02 jj Exp $
* bwtwofb.c: BWtwo frame buffer driver
*
* Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -199,6 +199,7 @@ char __init *bwtwofb_init(struct fb_info_sbusfb *fb)
strcpy(fb->info.modename, "BWtwo");
strcpy(fix->id, "BWtwo");
fix->line_length = fb->var.xres_virtual>>3;
+ fix->accel = FB_ACCEL_SUN_BWTWO;
disp->scrollmode = SCROLL_YREDRAW;
disp->inverse = 1;
diff --git a/drivers/video/cgfourteenfb.c b/drivers/video/cgfourteenfb.c
index f22389921..c5dfaad6e 100644
--- a/drivers/video/cgfourteenfb.c
+++ b/drivers/video/cgfourteenfb.c
@@ -1,4 +1,4 @@
-/* $Id: cgfourteenfb.c,v 1.3 1998/09/04 15:43:41 jj Exp $
+/* $Id: cgfourteenfb.c,v 1.4 1999/01/26 10:55:03 jj Exp $
* cgfourteenfb.c: CGfourteen frame buffer driver
*
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -355,6 +355,7 @@ __initfunc(char *cgfourteenfb_init(struct fb_info_sbusfb *fb))
strcpy(fb->info.modename, "CGfourteen");
strcpy(fix->id, "CGfourteen");
fix->line_length = fb->var.xres_virtual;
+ fix->accel = FB_ACCEL_SUN_CG14;
disp->scrollmode = SCROLL_YREDRAW;
disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
diff --git a/drivers/video/cgsixfb.c b/drivers/video/cgsixfb.c
index 2891b4877..a62fd12ad 100644
--- a/drivers/video/cgsixfb.c
+++ b/drivers/video/cgsixfb.c
@@ -1,4 +1,4 @@
-/* $Id: cgsixfb.c,v 1.12 1998/11/27 00:02:04 anton Exp $
+/* $Id: cgsixfb.c,v 1.16 1999/03/09 14:01:49 davem Exp $
* cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
*
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -352,8 +352,8 @@ static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned sh
do {
i = fbc->s;
} while (i & 0x10000000);
- fbc->fg = attr_fgcol(p,*s);
- fbc->bg = attr_bgcol(p,*s);
+ fbc->fg = attr_fgcol(p, scr_readw(s));
+ fbc->bg = attr_bgcol(p, scr_readw(s));
fbc->mode = 0x140000;
fbc->alu = 0xe880fc30;
fbc->pixelm = ~(0);
@@ -379,15 +379,15 @@ static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned sh
fbc->x1 = (x += 4 * fontwidth(p)) - 1;
fbc->y0 = y;
if (fontheightlog(p)) {
- fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
- fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
- fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
- fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+ fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+ fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+ fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+ fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
} else {
- fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
- fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
- fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
- fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+ fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+ fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+ fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+ fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
}
if (fontwidth(p) == 8) {
for (i = 0; i < fontheight(p); i++)
@@ -408,11 +408,11 @@ static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned sh
fbc->x1 = (x += 2 * fontwidth(p)) - 1;
fbc->y0 = y;
if (fontheightlog(p)) {
- fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
- fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
+ fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
+ fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
} else {
- fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
- fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
+ fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
+ fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
}
for (i = 0; i < fontheight(p); i++) {
fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
@@ -428,9 +428,9 @@ static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned sh
fbc->x1 = (x += fontwidth(p)) - 1;
fbc->y0 = y;
if (fontheightlog(p))
- i = ((*s++ & p->charmask) << fontheightlog(p));
+ i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
else
- i = ((*s++ & p->charmask) * fontheight(p));
+ i = ((scr_readw(s++) & p->charmask) * fontheight(p));
if (fontwidth(p) <= 8) {
fd1 = p->fontdata + i;
for (i = 0; i < fontheight(p); i++)
@@ -535,6 +535,7 @@ static void cg6_reset (struct fb_info_sbusfb *fb)
struct cg6_tec *tec = fb->s.cg6.tec;
struct cg6_fbc *fbc = fb->s.cg6.fbc;
u32 mode;
+ int i;
/* Turn off stuff in the Transform Engine. */
tec->tec_matrix = 0;
@@ -557,6 +558,9 @@ static void cg6_reset (struct fb_info_sbusfb *fb)
* back to back store/loads on the mode register, so copy it
* out instead. */
mode = fbc->mode;
+ do {
+ i = fbc->s;
+ } while (i & 0x10000000);
mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK |
CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK |
diff --git a/drivers/video/cgthreefb.c b/drivers/video/cgthreefb.c
index 882669d8f..91611c674 100644
--- a/drivers/video/cgthreefb.c
+++ b/drivers/video/cgthreefb.c
@@ -1,4 +1,4 @@
-/* $Id: cgthreefb.c,v 1.3 1998/09/04 15:43:43 jj Exp $
+/* $Id: cgthreefb.c,v 1.4 1999/01/26 10:55:01 jj Exp $
* cgthreefb.c: CGthree frame buffer driver
*
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -186,6 +186,7 @@ __initfunc(char *cgthreefb_init(struct fb_info_sbusfb *fb))
strcpy(fb->info.modename, "CGthree");
strcpy(fix->id, "CGthree");
fix->line_length = fb->var.xres_virtual;
+ fix->accel = FB_ACCEL_SUN_CGTHREE;
disp->scrollmode = SCROLL_YREDRAW;
if (!disp->screen_base)
diff --git a/drivers/video/clgenfb.c b/drivers/video/clgenfb.c
index 6e09ae666..3f95ae58c 100644
--- a/drivers/video/clgenfb.c
+++ b/drivers/video/clgenfb.c
@@ -204,8 +204,8 @@ static int clgen_pan_display(const struct fb_var_screeninfo *var,
struct fb_info_gen *info);
static int clgen_blank(int blank_mode, struct fb_info_gen *info);
-static void clgen_set_dispsw(const void *par, struct display *disp,
- struct fb_info_gen *info);
+static void clgen_set_disp(const void *par, struct display *disp,
+ struct fb_info_gen *info);
/* function table of the above functions */
static struct fbgen_hwswitch clgen_hwswitch =
@@ -220,7 +220,7 @@ static struct fbgen_hwswitch clgen_hwswitch =
clgen_setcolreg,
clgen_pan_display,
clgen_blank,
- clgen_set_dispsw
+ clgen_set_disp
};
/* Text console acceleration */
@@ -1372,13 +1372,14 @@ static void switch_monitor(int on)
}
}
-static void clgen_set_dispsw(const void *par, struct display *disp,
- struct fb_info_gen *info)
+static void clgen_set_disp(const void *par, struct display *disp,
+ struct fb_info_gen *info)
{
struct clgenfb_par *_par = (struct clgenfb_par*) par;
struct clgenfb_info *info2 = (struct clgenfb_info *)info;
- printk("clgen_get_dispsw(): ");
+ printk("clgen_set_disp(): ");
+ disp->screen_base = info2->fbmem;
switch (_par->var.bits_per_pixel)
{
#ifdef FBCON_HAS_MFB
@@ -1670,7 +1671,7 @@ __initfunc(void clgenfb_setup(char *options, int *ints))
int init_module(void)
{
printk("init_module()\n");
- clgenfb_init(0);
+ clgenfb_init();
return 0;
}
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 129c4e396..2a783fc9b 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -377,7 +377,7 @@ static int controlfb_switch(int con, struct fb_info *info)
control_set_hardware(p, &par);
control_set_dispsw(&fb_display[con], par.cmode, p);
- if(fb_display[oldcon].var.yoffset != fb_display[con].var.yoffset);
+ if(fb_display[oldcon].var.yoffset != fb_display[con].var.yoffset)
controlfb_updatevar(con, info);
do_install_cmap(con, info);
@@ -447,21 +447,24 @@ static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
struct fb_info_control *p = (struct fb_info_control *) info;
- int i;
+ u_int i;
+ __u8 r, g, b;
if (regno > 255)
return 1;
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- p->palette[regno].red = red;
- p->palette[regno].green = green;
- p->palette[regno].blue = blue;
+
+ r = red >> 8;
+ g = green >> 8;
+ b = blue >> 8;
+
+ p->palette[regno].red = r;
+ p->palette[regno].green = g;
+ p->palette[regno].blue = b;
out_8(&p->cmap_regs->addr, regno); /* tell clut what addr to fill */
- out_8(&p->cmap_regs->lut, red); /* send one color channel at */
- out_8(&p->cmap_regs->lut, green); /* a time... */
- out_8(&p->cmap_regs->lut, blue);
+ out_8(&p->cmap_regs->lut, r); /* send one color channel at */
+ out_8(&p->cmap_regs->lut, g); /* a time... */
+ out_8(&p->cmap_regs->lut, b);
if (regno < 16)
switch (p->par.cmode) {
@@ -501,8 +504,9 @@ extern struct fb_info *console_fb_info;
static inline int control_vram_reqd(int video_mode, int color_mode)
{
- return control_reg_init[video_mode-1]->vres
- * control_reg_init[video_mode-1]->hres << color_mode;
+ return (control_reg_init[video_mode-1]->vres
+ * control_reg_init[video_mode-1]->hres << color_mode)
+ + control_reg_init[video_mode-1]->offset[color_mode];
}
static void set_control_clock(unsigned char *params)
@@ -557,6 +561,7 @@ __initfunc(static void init_control(struct fb_info_control *p))
par_set = 1; /* Debug */
control_par_to_var(par, &var);
+ var.activate = FB_ACTIVATE_NOW;
control_set_var(&var, -1, &p->info);
p->info.flags = FBINFO_FLAG_DEFAULT;
@@ -616,11 +621,11 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro
for (i = 0; i < 16; ++i, ++rp)
out_le32(&rp->r, init->regs[i]);
- out_le32(&p->control_regs->pitch.r, init->hres << cmode);
+ out_le32(&p->control_regs->pitch.r, par->vxres << cmode);
out_le32(&p->control_regs->mode.r, init->mode[cmode]);
out_le32(&p->control_regs->flags.r, flags);
out_le32(&p->control_regs->start_addr.r,
- par->yoffset * (par->vxres << par->cmode));
+ par->yoffset * (par->vxres << cmode));
out_le32(&p->control_regs->reg18.r, 0x1e5);
out_le32(&p->control_regs->reg19.r, 0);
@@ -762,8 +767,6 @@ static int control_var_to_par(struct fb_var_screeninfo *var,
int xres = var->xres;
int yres = var->yres;
int bpp = var->bits_per_pixel;
-
- struct control_regvals *init;
struct fb_info_control *p = (struct fb_info_control *) fb_info;
/*
@@ -776,7 +779,7 @@ static int control_var_to_par(struct fb_var_screeninfo *var,
*/
/* swiped by jonh from atyfb.c */
if (xres <= 512 && yres <= 384)
- par->vmode = VMODE_512_384_60; /* 512x384, 60Hz */
+ par->vmode = VMODE_512_384_60; /* 512x384, 60Hz */
else if (xres <= 640 && yres <= 480)
par->vmode = VMODE_640_480_67; /* 640x480, 67Hz */
else if (xres <= 640 && yres <= 870)
@@ -844,8 +847,7 @@ static int control_var_to_par(struct fb_var_screeninfo *var,
}
/* Check if we know about the wanted video mode */
- init = control_reg_init[par->vmode-1];
- if (init == NULL) {
+ if (control_reg_init[par->vmode - 1] == NULL) {
printk(KERN_ERR "init is null in control_var_to_par().\n");
/* I'm not sure if control has any specific requirements -- */
/* if we have a regvals struct, we're good to go? */
@@ -1010,7 +1012,7 @@ static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeni
fix->smem_start = (void *)(p->frame_buffer_phys
+ control_reg_init[par->vmode-1]->offset[par->cmode]);
- fix->smem_len = p->total_vram;
+ fix->smem_len = p->total_vram - control_reg_init[par->vmode-1]->offset[par->cmode];
fix->visual = (par->cmode == CMODE_8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
fix->line_length = par->vxres << par->cmode;
@@ -1046,6 +1048,70 @@ static void control_par_to_display(struct fb_par_control *par,
control_set_dispsw(disp, par->cmode, p);
}
+static void control_cfb16_revc(struct display *p, int xx, int yy)
+{
+ u8 *dest;
+ int bytes = p->next_line, rows;
+
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p)*2;
+ for (rows = fontheight(p); rows--; dest += bytes) {
+ switch (fontwidth(p)) {
+ case 16:
+ ((u32 *)dest)[6] ^= 0x3def3def; ((u32 *)dest)[7] ^= 0x3def3def;
+ /* FALL THROUGH */
+ case 12:
+ ((u32 *)dest)[4] ^= 0x3def3def; ((u32 *)dest)[5] ^= 0x3def3def;
+ /* FALL THROUGH */
+ case 8:
+ ((u32 *)dest)[2] ^= 0x3def3def; ((u32 *)dest)[3] ^= 0x3def3def;
+ /* FALL THROUGH */
+ case 4:
+ ((u32 *)dest)[0] ^= 0x3def3def; ((u32 *)dest)[1] ^= 0x3def3def;
+ }
+ }
+}
+
+static void control_cfb32_revc(struct display *p, int xx, int yy)
+{
+ u8 *dest;
+ int bytes = p->next_line, rows;
+
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4;
+ for (rows = fontheight(p); rows--; dest += bytes) {
+ switch (fontwidth(p)) {
+ case 16:
+ ((u32 *)dest)[12] ^= 0x0f0f0f0f; ((u32 *)dest)[13] ^= 0x0f0f0f0f;
+ ((u32 *)dest)[14] ^= 0x0f0f0f0f; ((u32 *)dest)[15] ^= 0x0f0f0f0f;
+ /* FALL THROUGH */
+ case 12:
+ ((u32 *)dest)[8] ^= 0x0f0f0f0f; ((u32 *)dest)[9] ^= 0x0f0f0f0f;
+ ((u32 *)dest)[10] ^= 0x0f0f0f0f; ((u32 *)dest)[11] ^= 0x0f0f0f0f;
+ /* FALL THROUGH */
+ case 8:
+ ((u32 *)dest)[4] ^= 0x0f0f0f0f; ((u32 *)dest)[5] ^= 0x0f0f0f0f;
+ ((u32 *)dest)[6] ^= 0x0f0f0f0f; ((u32 *)dest)[7] ^= 0x0f0f0f0f;
+ /* FALL THROUGH */
+ case 4:
+ ((u32 *)dest)[0] ^= 0x0f0f0f0f; ((u32 *)dest)[1] ^= 0x0f0f0f0f;
+ ((u32 *)dest)[2] ^= 0x0f0f0f0f; ((u32 *)dest)[3] ^= 0x0f0f0f0f;
+ /* FALL THROUGH */
+ }
+ }
+}
+
+static struct display_switch control_cfb16 = {
+ fbcon_cfb16_setup, fbcon_cfb16_bmove, fbcon_cfb16_clear, fbcon_cfb16_putc,
+ fbcon_cfb16_putcs, control_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins,
+ FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+
+static struct display_switch control_cfb32 = {
+ fbcon_cfb32_setup, fbcon_cfb32_bmove, fbcon_cfb32_clear, fbcon_cfb32_putc,
+ fbcon_cfb32_putcs, control_cfb32_revc, NULL, NULL, fbcon_cfb32_clear_margins,
+ FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+
+
static void control_set_dispsw(struct display *disp, int cmode, struct fb_info_control *p)
{
switch (cmode) {
@@ -1056,13 +1122,13 @@ static void control_set_dispsw(struct display *disp, int cmode, struct fb_info_c
#endif
#ifdef FBCON_HAS_CFB16
case CMODE_16:
- disp->dispsw = &fbcon_cfb16;
+ disp->dispsw = &control_cfb16;
disp->dispsw_data = p->fbcon_cmap.cfb16;
break;
#endif
#ifdef FBCON_HAS_CFB32
case CMODE_32:
- disp->dispsw = &fbcon_cfb32;
+ disp->dispsw = &control_cfb32;
disp->dispsw_data = p->fbcon_cmap.cfb32;
break;
#endif
diff --git a/drivers/video/creatorfb.c b/drivers/video/creatorfb.c
index 69242992d..81421a7ff 100644
--- a/drivers/video/creatorfb.c
+++ b/drivers/video/creatorfb.c
@@ -1,7 +1,7 @@
-/* $Id: creatorfb.c,v 1.17 1998/12/28 11:23:37 jj Exp $
+/* $Id: creatorfb.c,v 1.27 1999/03/28 12:37:12 jj Exp $
* creatorfb.c: Creator/Creator3D frame buffer driver
*
- * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
*/
#include <linux/module.h>
@@ -132,18 +132,10 @@
struct ffb_fbc {
/* Next vertex registers */
- u32 xxx1[3];
- volatile u32 alpha;
- volatile u32 red;
- volatile u32 green;
- volatile u32 blue;
- volatile u32 depth;
- volatile u32 y;
- volatile u32 x;
- u32 xxx2[2];
- volatile u32 ryf;
- volatile u32 rxf;
- u32 xxx3[2];
+ u32 xxx1[3]; volatile u32 alpha; volatile u32 red;
+ volatile u32 green; volatile u32 blue; volatile u32 depth; volatile
+ u32 y; volatile u32 x; u32 xxx2[2]; volatile u32 ryf; volatile u32
+ rxf; u32 xxx3[2];
volatile u32 dmyf;
volatile u32 dmxf;
@@ -276,16 +268,17 @@ struct ffb_fbc {
volatile u32 mer;
};
-static __inline__ void FFBFifo(struct ffb_fbc *ffb, int n)
+static __inline__ void FFBFifo(struct fb_info_sbusfb *fb, int n)
{
- int limit = 10000;
+ struct ffb_fbc *fbc;
+ int cache = fb->s.ffb.fifo_cache;
- do {
- if((ffb->ucsr & FFB_UCSR_FIFO_MASK) >= (n + 4))
- break;
- if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
- ffb->ucsr = FFB_UCSR_ALL_ERRORS;
- } while(--limit > 0);
+ if (cache - n < 0) {
+ fbc = fb->s.ffb.fbc;
+ do { cache = (fbc->ucsr & FFB_UCSR_FIFO_MASK) - 8;
+ } while (cache - n < 0);
+ }
+ fb->s.ffb.fifo_cache = cache - n;
}
static __inline__ void FFBWait(struct ffb_fbc *ffb)
@@ -340,40 +333,45 @@ static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
{
struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
register struct ffb_fbc *fbc = fb->s.ffb.fbc;
- int x, y, w, h;
+ u64 yx, hw;
+ int fg;
- FFBWait(fbc);
- FFBFifo(fbc, 6);
- fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
- fbc->drawop = FFB_DRAWOP_RECTANGLE;
+ fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
+ if (fg != fb->s.ffb.fg_cache) {
+ FFBFifo(fb, 5);
+ fbc->fg = fg;
+ fb->s.ffb.fg_cache = fg;
+ } else
+ FFBFifo(fb, 4);
if (fontheightlog(p)) {
- y = sy << fontheightlog(p); h = height << fontheightlog(p);
+ yx = (u64)sy << (fontheightlog(p) + 32); hw = (u64)height << (fontheightlog(p) + 32);
} else {
- y = sy * fontheight(p); h = height * fontheight(p);
+ yx = (u64)(sy * fontheight(p)) << 32; hw = (u64)(height * fontheight(p)) << 32;
}
if (fontwidthlog(p)) {
- x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
+ yx += sx << fontwidthlog(p); hw += width << fontwidthlog(p);
} else {
- x = sx * fontwidth(p); w = width * fontwidth(p);
+ yx += sx * fontwidth(p); hw += width * fontwidth(p);
}
- fbc->by = y + fb->y_margin;
- fbc->bx = x + fb->x_margin;
- fbc->bh = h;
- fbc->bw = w;
+ *(volatile u64 *)&fbc->by = yx + fb->s.ffb.yx_margin;
+ *(volatile u64 *)&fbc->bh = hw;
}
static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
int count, unsigned short *boxes)
{
register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+ int fg;
- FFBWait(fbc);
- FFBFifo(fbc, 2);
- fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
- fbc->drawop = FFB_DRAWOP_RECTANGLE;
+ fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
+ if (fg != fb->s.ffb.fg_cache) {
+ FFBFifo(fb, 1);
+ fbc->fg = fg;
+ fb->s.ffb.fg_cache = fg;
+ }
while (count-- > 0) {
- FFBFifo(fbc, 4);
+ FFBFifo(fb, 4);
fbc->by = boxes[1];
fbc->bx = boxes[0];
fbc->bh = boxes[3] - boxes[1];
@@ -388,6 +386,7 @@ static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int
register struct ffb_fbc *fbc = fb->s.ffb.fbc;
int i, xy;
u8 *fd;
+ u64 fgbg;
if (fontheightlog(p)) {
xy = (yy << (16 + fontheightlog(p)));
@@ -404,14 +403,16 @@ static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int
xy += (xx << fontwidthlog(p)) + fb->s.ffb.xy_margin;
else
xy += (xx * fontwidth(p)) + fb->s.ffb.xy_margin;
- FFBWait(fbc);
- FFBFifo(fbc, 5);
- fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
- fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
- fbc->fontw = fontwidth(p);
- fbc->fontinc = 0x10000;
+ fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,c)])) << 32) |
+ ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
+ if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
+ FFBFifo(fb, 2);
+ *(volatile u64 *)&fbc->fg = fgbg;
+ *(u64 *)&fb->s.ffb.fg_cache = fgbg;
+ }
+ FFBFifo(fb, 2 + fontheight(p));
fbc->fontxy = xy;
- FFBFifo(fbc, fontheight(p));
+ fbc->fontw = fontwidth(p);
if (fontwidth(p) <= 8) {
for (i = 0; i < fontheight(p); i++)
fbc->font = *fd++ << 24;
@@ -430,11 +431,15 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
register struct ffb_fbc *fbc = fb->s.ffb.fbc;
int i, xy;
u8 *fd1, *fd2, *fd3, *fd4;
-
- FFBWait(fbc);
- FFBFifo(fbc, 2);
- fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,*s)];
- fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,*s)];
+ u64 fgbg;
+
+ fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,scr_readw(s))])) << 32) |
+ ((u32 *)p->dispsw_data)[attr_bgcol(p,scr_readw(s))];
+ if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
+ FFBFifo(fb, 2);
+ *(volatile u64 *)&fbc->fg = fgbg;
+ *(u64 *)&fb->s.ffb.fg_cache = fgbg;
+ }
xy = fb->s.ffb.xy_margin;
if (fontwidthlog(p))
xy += (xx << fontwidthlog(p));
@@ -447,22 +452,20 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
if (fontwidth(p) <= 8) {
while (count >= 4) {
count -= 4;
- FFBFifo(fbc, 3);
+ FFBFifo(fb, 2 + fontheight(p));
fbc->fontw = 4 * fontwidth(p);
- fbc->fontinc = 0x10000;
fbc->fontxy = xy;
if (fontheightlog(p)) {
- fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
- fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
- fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
- fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+ fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+ fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+ fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+ fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
} else {
- fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
- fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
- fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
- fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+ fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+ fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+ fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+ fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
}
- FFBFifo(fbc, fontheight(p));
if (fontwidth(p) == 8) {
for (i = 0; i < fontheight(p); i++)
fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
@@ -478,18 +481,16 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
} else {
while (count >= 2) {
count -= 2;
- FFBFifo(fbc, 3);
+ FFBFifo(fb, 2 + fontheight(p));
fbc->fontw = 2 * fontwidth(p);
- fbc->fontinc = 0x10000;
fbc->fontxy = xy;
if (fontheightlog(p)) {
- fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
- fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
+ fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
+ fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
} else {
- fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
- fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
+ fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
+ fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
}
- FFBFifo(fbc, fontheight(p));
for (i = 0; i < fontheight(p); i++) {
fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
fd1 += 2; fd2 += 2;
@@ -499,15 +500,13 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
}
while (count) {
count--;
- FFBFifo(fbc, 3);
+ FFBFifo(fb, 2 + fontheight(p));
fbc->fontw = fontwidth(p);
- fbc->fontinc = 0x10000;
fbc->fontxy = xy;
if (fontheightlog(p))
- i = ((*s++ & p->charmask) << fontheightlog(p));
+ i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
else
- i = ((*s++ & p->charmask) * fontheight(p));
- FFBFifo(fbc, fontheight(p));
+ i = ((scr_readw(s++) & p->charmask) * fontheight(p));
if (fontwidth(p) <= 8) {
fd1 = p->fontdata + i;
for (i = 0; i < fontheight(p); i++)
@@ -554,8 +553,12 @@ static struct display_switch ffb_dispsw __initdata = {
static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
{
+ register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+
fb->s.ffb.xy_margin = (y_margin << 16) + x_margin;
+ fb->s.ffb.yx_margin = (((u64)y_margin) << 32) + x_margin;
p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
+ FFBWait(fbc);
}
static inline void ffb_curs_enable (struct fb_info_sbusfb *fb, int enable)
@@ -619,11 +622,16 @@ static void ffb_switch_from_graph (struct fb_info_sbusfb *fb)
register struct ffb_fbc *fbc = fb->s.ffb.fbc;
FFBWait(fbc);
- FFBFifo(fbc, 4);
+ fb->s.ffb.fifo_cache = 0;
+ FFBFifo(fb, 8);
fbc->ppc = FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST;
fbc->fbc = 0x2000707f;
fbc->rop = FFB_ROP_NEW;
+ fbc->drawop = FFB_DRAWOP_RECTANGLE;
fbc->pmask = 0xffffffff;
+ fbc->fontinc = 0x10000;
+ fbc->fg = fb->s.ffb.fg_cache;
+ fbc->bg = fb->s.ffb.bg_cache;
FFBWait(fbc);
}
@@ -675,6 +683,7 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
disp->scrollmode = SCROLL_YREDRAW;
disp->screen_base = (char *)__va(regs[0].phys_addr) + FFB_DFB24_POFF + 8192 * fb->y_margin + 4 * fb->x_margin;
fb->s.ffb.xy_margin = (fb->y_margin << 16) + fb->x_margin;
+ fb->s.ffb.yx_margin = (((u64)fb->y_margin) << 32) + fb->x_margin;
fb->s.ffb.fbc = (struct ffb_fbc *)((char *)__va(regs[0].phys_addr) + FFB_FBC_REGS_POFF);
fb->s.ffb.dac = (struct ffb_dac *)((char *)__va(regs[0].phys_addr) + FFB_DAC_POFF);
fb->dispsw = ffb_dispsw;
@@ -710,5 +719,10 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
sprintf(idstring, "%s at %016lx type %d DAC %d", fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev);
+ /* Elite3D has different DAC revision numbering, and no DAC revisions
+ have the reversed meaning of cursor enable */
+ if (afb)
+ fb->s.ffb.dac_rev = 10;
+
return idstring;
}
diff --git a/drivers/video/cvisionppc.h b/drivers/video/cvisionppc.h
index 4a137548f..0afc0d04e 100644
--- a/drivers/video/cvisionppc.h
+++ b/drivers/video/cvisionppc.h
@@ -4,7 +4,7 @@
*
* Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
* --------------------------------------------------------------------------
- * $Id: cvisionppc.h,v 1.1.2.1 1999/01/12 19:52:59 geert Exp $
+ * $Id: cvisionppc.h,v 1.8 1999/01/28 13:18:07 illo Exp $
* --------------------------------------------------------------------------
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file README.legal in the main directory of this archive
@@ -21,7 +21,7 @@
struct cvppc_par {
unsigned char* pci_config;
unsigned char* pci_bridge;
- unsigned long user_flags;
+ u32 user_flags;
};
#define CSPPC_PCI_BRIDGE 0xfffe0000
diff --git a/drivers/video/fbcon-afb.c b/drivers/video/fbcon-afb.c
index 205c1347d..3b9d4bb93 100644
--- a/drivers/video/fbcon-afb.c
+++ b/drivers/video/fbcon-afb.c
@@ -290,12 +290,12 @@ void fbcon_afb_putcs(struct vc_data *conp, struct display *p,
int fg0, bg0, fg, bg;
dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
- fg0 = attr_fgcol(p,*s);
- bg0 = attr_bgcol(p,*s);
+ fg0 = attr_fgcol(p, scr_readw(s));
+ bg0 = attr_bgcol(p, scr_readw(s));
while (count--)
if (xx&3 || count < 3) { /* Slow version */
- c1 = *s++ & p->charmask;
+ c1 = scr_readw(s++) & p->charmask;
dest1 = dest0++;
xx++;
@@ -322,10 +322,10 @@ void fbcon_afb_putcs(struct vc_data *conp, struct display *p,
dest1 += p->next_plane;
} while (--i);
} else { /* Fast version */
- c1 = s[0] & p->charmask;
- c2 = s[1] & p->charmask;
- c3 = s[2] & p->charmask;
- c4 = s[3] & p->charmask;
+ c1 = scr_readw(&s[0]) & p->charmask;
+ c2 = scr_readw(&s[1]) & p->charmask;
+ c3 = scr_readw(&s[2]) & p->charmask;
+ c4 = scr_readw(&s[3]) & p->charmask;
dest1 = dest0;
cdat10 = p->fontdata+c1*fontheight(p);
diff --git a/drivers/video/fbcon-cfb16.c b/drivers/video/fbcon-cfb16.c
index a05848f5b..9fef8171e 100644
--- a/drivers/video/fbcon-cfb16.c
+++ b/drivers/video/fbcon-cfb16.c
@@ -177,8 +177,8 @@ void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p,
u32 eorx, fgx, bgx;
dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
- fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, *s)];
- bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, *s)];
+ fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, scr_readw(s))];
+ bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, scr_readw(s))];
fgx |= (fgx << 16);
bgx |= (bgx << 16);
eorx = fgx ^ bgx;
@@ -187,7 +187,7 @@ void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p,
case 4:
case 8:
while (count--) {
- c = *s++ & p->charmask;
+ c = scr_readw(s++) & p->charmask;
cdat = p->fontdata + c * fontheight(p);
for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) {
u8 bits = *cdat++;
@@ -204,7 +204,7 @@ void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p,
case 12:
case 16:
while (count--) {
- c = *s++ & p->charmask;
+ c = scr_readw(s++) & p->charmask;
cdat = p->fontdata + (c * fontheight(p) << 1);
for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) {
u8 bits = *cdat++;
diff --git a/drivers/video/fbcon-cfb2.c b/drivers/video/fbcon-cfb2.c
index e25fadaae..5b339a4fa 100644
--- a/drivers/video/fbcon-cfb2.c
+++ b/drivers/video/fbcon-cfb2.c
@@ -50,7 +50,7 @@ static u_char nibbletab_cfb2[]={
void fbcon_cfb2_setup(struct display *p)
{
- p->next_line = p->var.xres_virtual>>2;
+ p->next_line = p->line_length ? p->line_length : p->var.xres_virtual>>2;
p->next_plane = 0;
}
@@ -156,15 +156,15 @@ void fbcon_cfb2_putcs(struct vc_data *conp, struct display *p, const unsigned sh
u32 eorx, fgx, bgx;
dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * 2;
- fgx=3/*attr_fgcol(p,*s)*/;
- bgx=attr_bgcol(p,*s);
+ fgx=3/*attr_fgcol(p,scr_readw(s))*/;
+ bgx=attr_bgcol(p,scr_readw(s));
fgx |= (fgx << 2);
fgx |= (fgx << 4);
bgx |= (bgx << 2);
bgx |= (bgx << 4);
eorx = fgx ^ bgx;
while (count--) {
- c = *s++ & p->charmask;
+ c = scr_readw(s++) & p->charmask;
cdat = p->fontdata + c * fontheight(p);
for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
diff --git a/drivers/video/fbcon-cfb24.c b/drivers/video/fbcon-cfb24.c
index 488aac290..17e8ee08a 100644
--- a/drivers/video/fbcon-cfb24.c
+++ b/drivers/video/fbcon-cfb24.c
@@ -187,11 +187,11 @@ void fbcon_cfb24_putcs(struct vc_data *conp, struct display *p,
u32 eorx, fgx, bgx, d1, d2, d3, d4;
dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 3;
- fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, *s)];
- bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, *s)];
+ fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, scr_readw(s))];
+ bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, scr_readw(s))];
eorx = fgx ^ bgx;
while (count--) {
- c = *s++ & p->charmask;
+ c = scr_readw(s++) & p->charmask;
if (fontwidth(p) <= 8)
cdat = p->fontdata + c * fontheight(p);
diff --git a/drivers/video/fbcon-cfb32.c b/drivers/video/fbcon-cfb32.c
index cd1e80a7d..b66ec2bad 100644
--- a/drivers/video/fbcon-cfb32.c
+++ b/drivers/video/fbcon-cfb32.c
@@ -163,11 +163,11 @@ void fbcon_cfb32_putcs(struct vc_data *conp, struct display *p,
u32 eorx, fgx, bgx;
dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4;
- fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, *s)];
- bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, *s)];
+ fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, scr_readw(s))];
+ bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, scr_readw(s))];
eorx = fgx ^ bgx;
while (count--) {
- c = *s++ & p->charmask;
+ c = scr_readw(s++) & p->charmask;
if (fontwidth(p) <= 8)
cdat = p->fontdata + c * fontheight(p);
else
diff --git a/drivers/video/fbcon-cfb4.c b/drivers/video/fbcon-cfb4.c
index 78b87ffe7..6248c28ee 100644
--- a/drivers/video/fbcon-cfb4.c
+++ b/drivers/video/fbcon-cfb4.c
@@ -50,7 +50,7 @@ static u16 nibbletab_cfb4[] = {
void fbcon_cfb4_setup(struct display *p)
{
- p->next_line = p->var.xres_virtual>>1;
+ p->next_line = p->line_length ? p->line_length : p->var.xres_virtual>>1;
p->next_plane = 0;
}
@@ -158,8 +158,8 @@ void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p,
u32 eorx, fgx, bgx;
dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * 4;
- fgx=attr_fgcol(p,*s);
- bgx=attr_bgcol(p,*s);
+ fgx=attr_fgcol(p,scr_readw(s));
+ bgx=attr_bgcol(p,scr_readw(s));
fgx |= (fgx << 4);
fgx |= (fgx << 8);
fgx |= (fgx << 16);
@@ -168,7 +168,7 @@ void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p,
bgx |= (bgx << 16);
eorx = fgx ^ bgx;
while (count--) {
- c = *s++ & p->charmask;
+ c = scr_readw(s++) & p->charmask;
cdat = p->fontdata + c * fontheight(p);
for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
diff --git a/drivers/video/fbcon-cfb8.c b/drivers/video/fbcon-cfb8.c
index bfa98c719..0acf7c989 100644
--- a/drivers/video/fbcon-cfb8.c
+++ b/drivers/video/fbcon-cfb8.c
@@ -163,8 +163,8 @@ void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p,
u32 eorx, fgx, bgx;
dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
- fgx=attr_fgcol(p,*s);
- bgx=attr_bgcol(p,*s);
+ fgx=attr_fgcol(p,scr_readw(s));
+ bgx=attr_bgcol(p,scr_readw(s));
fgx |= (fgx << 8);
fgx |= (fgx << 16);
bgx |= (bgx << 8);
@@ -173,7 +173,7 @@ void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p,
switch (fontwidth(p)) {
case 4:
while (count--) {
- c = *s++ & p->charmask;
+ c = scr_readw(s++) & p->charmask;
cdat = p->fontdata + c * fontheight(p);
for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes)
@@ -183,7 +183,7 @@ void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p,
break;
case 8:
while (count--) {
- c = *s++ & p->charmask;
+ c = scr_readw(s++) & p->charmask;
cdat = p->fontdata + c * fontheight(p);
for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
@@ -196,7 +196,7 @@ void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p,
case 12:
case 16:
while (count--) {
- c = *s++ & p->charmask;
+ c = scr_readw(s++) & p->charmask;
cdat = p->fontdata + (c * fontheight(p) << 1);
for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
diff --git a/drivers/video/fbcon-ilbm.c b/drivers/video/fbcon-ilbm.c
index 183f05a46..fbba519d9 100644
--- a/drivers/video/fbcon-ilbm.c
+++ b/drivers/video/fbcon-ilbm.c
@@ -154,12 +154,12 @@ void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p,
int fg0, bg0, fg, bg;
dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
- fg0 = attr_fgcol(p,*s);
- bg0 = attr_bgcol(p,*s);
+ fg0 = attr_fgcol(p,scr_readw(s));
+ bg0 = attr_bgcol(p,scr_readw(s));
while (count--)
if (xx&3 || count < 3) { /* Slow version */
- c1 = *s++ & p->charmask;
+ c1 = scr_readw(s++) & p->charmask;
dest = dest0++;
xx++;
@@ -185,10 +185,10 @@ void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p,
}
}
} else { /* Fast version */
- c1 = s[0] & p->charmask;
- c2 = s[1] & p->charmask;
- c3 = s[2] & p->charmask;
- c4 = s[3] & p->charmask;
+ c1 = scr_readw(&s[0]) & p->charmask;
+ c2 = scr_readw(&s[1]) & p->charmask;
+ c3 = scr_readw(&s[2]) & p->charmask;
+ c4 = scr_readw(&s[3]) & p->charmask;
dest = dest0;
cdat1 = p->fontdata+c1*fontheight(p);
diff --git a/drivers/video/fbcon-iplan2p2.c b/drivers/video/fbcon-iplan2p2.c
index 0c0bfa21f..0dfdc6107 100644
--- a/drivers/video/fbcon-iplan2p2.c
+++ b/drivers/video/fbcon-iplan2p2.c
@@ -361,12 +361,12 @@ void fbcon_iplan2p2_putcs(struct vc_data *conp, struct display *p,
else
dest0 = (p->screen_base + yy * bytes * fontheight(p) +
(xx>>1)*4 + (xx & 1));
- fgx = expand2w(COLOR_2P(attr_fgcol(p,*s)));
- bgx = expand2w(COLOR_2P(attr_bgcol(p,*s)));
+ fgx = expand2w(COLOR_2P(attr_fgcol(p,scr_readw(s))));
+ bgx = expand2w(COLOR_2P(attr_bgcol(p,scr_readw(s))));
eorx = fgx ^ bgx;
while (count--) {
- c = *s++ & p->charmask;
+ c = scr_readw(s++) & p->charmask;
if (fontheightlog(p))
cdat = p->fontdata + (c << fontheightlog(p));
else
diff --git a/drivers/video/fbcon-iplan2p4.c b/drivers/video/fbcon-iplan2p4.c
index 2c1d67a77..805c9170b 100644
--- a/drivers/video/fbcon-iplan2p4.c
+++ b/drivers/video/fbcon-iplan2p4.c
@@ -371,8 +371,8 @@ void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p,
else
dest0 = (p->screen_base + yy * bytes * fontheight(p) +
(xx>>1)*8 + (xx & 1));
- fgx = expand4l(attr_fgcol(p,*s));
- bgx = expand4l(attr_bgcol(p,*s));
+ fgx = expand4l(attr_fgcol(p,scr_readw(s)));
+ bgx = expand4l(attr_bgcol(p,scr_readw(s)));
eorx = fgx ^ bgx;
while (count--) {
@@ -383,7 +383,7 @@ void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p,
* cache :-(
*/
- c = *s++ & p->charmask;
+ c = scr_readw(s++) & p->charmask;
if (fontheightlog(p))
cdat = p->fontdata + (c << fontheightlog(p));
else
diff --git a/drivers/video/fbcon-iplan2p8.c b/drivers/video/fbcon-iplan2p8.c
index c730eb39c..411dc5ae9 100644
--- a/drivers/video/fbcon-iplan2p8.c
+++ b/drivers/video/fbcon-iplan2p8.c
@@ -404,8 +404,8 @@ void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p,
dest0 = (p->screen_base + yy * bytes * fontheight(p) +
(xx>>1)*16 + (xx & 1));
- expand8dl(attr_fgcol(p,*s), &fgx1, &fgx2);
- expand8dl(attr_bgcol(p,*s), &bgx1, &bgx2);
+ expand8dl(attr_fgcol(p,scr_readw(s)), &fgx1, &fgx2);
+ expand8dl(attr_bgcol(p,scr_readw(s)), &bgx1, &bgx2);
eorx1 = fgx1 ^ bgx1; eorx2 = fgx2 ^ bgx2;
while (count--) {
@@ -417,7 +417,7 @@ void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p,
* cache :-(
*/
- c = *s++ & p->charmask;
+ c = scr_readw(s++) & p->charmask;
if (fontheightlog(p))
cdat = p->fontdata + (c << fontheightlog(p));
else
diff --git a/drivers/video/fbcon-mac.c b/drivers/video/fbcon-mac.c
index f2508e4cb..2c6486c41 100644
--- a/drivers/video/fbcon-mac.c
+++ b/drivers/video/fbcon-mac.c
@@ -301,7 +301,7 @@ void fbcon_mac_putcs(struct vc_data *conp, struct display *p,
u16 c;
while (count--) {
- c = *s++;
+ c = scr_readw(s++);
fbcon_mac_putc(conp, p, c, yy, xx++);
}
}
diff --git a/drivers/video/fbcon-mfb.c b/drivers/video/fbcon-mfb.c
index 32f1ea8d4..76caf5cc9 100644
--- a/drivers/video/fbcon-mfb.c
+++ b/drivers/video/fbcon-mfb.c
@@ -117,12 +117,12 @@ void fbcon_mfb_putcs(struct vc_data *conp, struct display *p,
u16 c;
dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
- bold = attr_bold(p,*s);
- revs = attr_reverse(p,*s);
- underl = attr_underline(p,*s);
+ bold = attr_bold(p,scr_readw(s));
+ revs = attr_reverse(p,scr_readw(s));
+ underl = attr_underline(p,scr_readw(s));
while (count--) {
- c = *s++ & p->charmask;
+ c = scr_readw(s++) & p->charmask;
dest = dest0++;
cdat = p->fontdata+c*fontheight(p);
for (rows = fontheight(p); rows--; dest += p->next_line) {
diff --git a/drivers/video/fbcon-vga.c b/drivers/video/fbcon-vga.c
index fa4d387b8..05f843d25 100644
--- a/drivers/video/fbcon-vga.c
+++ b/drivers/video/fbcon-vga.c
@@ -155,11 +155,11 @@ void fbcon_vga_putcs(struct vc_data *conp, struct display *p,
u16 sattr;
if (conp->vc_can_do_color)
while (count--)
- vga_writew(*s++, dst++);
+ vga_writew(scr_readw(s++), dst++);
else {
- sattr = fbcon_vga_attr(p, *s);
+ sattr = fbcon_vga_attr(p, scr_readw(s));
while (count--)
- vga_writew(sattr | ((int) (*s++) & 0xff), dst++);
+ vga_writew(sattr | ((int) (scr_readw(s++)) & 0xff), dst++);
}
}
diff --git a/drivers/video/fbcon.c b/drivers/video/fbcon.c
index 033118f61..b3e56f322 100644
--- a/drivers/video/fbcon.c
+++ b/drivers/video/fbcon.c
@@ -26,7 +26,7 @@
*
* Hardware cursor support added by Emmanuel Marty (core@ggi-project.org)
* Smart redraw scrolling, arbitrary font width support, 512char font support
- * added by
+ * and software scrollback added by
* Jakub Jelinek (jj@ultra.linux.cz)
*
* Random hacking by Martin Mares <mj@ucw.cz>
@@ -111,6 +111,12 @@
struct display fb_display[MAX_NR_CONSOLES];
static int logo_lines;
static int logo_shown = -1;
+/* Software scrollback */
+extern int fbcon_softback_size;
+static unsigned long softback_buf, softback_curr;
+static unsigned long softback_in;
+static unsigned long softback_top, softback_end;
+static int softback_lines;
#define REFCOUNT(fd) (((int *)(fd))[-1])
#define FNTSIZE(fd) (((int *)(fd))[-2])
@@ -118,7 +124,12 @@ static int logo_shown = -1;
#define FNTSUM(fd) (((int *)(fd))[-4])
#define FONT_EXTRA_WORDS 4
-static void fbcon_free_font(struct display *p);
+#define CM_SOFTBACK (8)
+
+#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * conp->vc_size_row)
+
+static void fbcon_free_font(struct display *);
+static int fbcon_set_origin(struct vc_data *);
/*
* Emmanuel: fbcon will now use a hardware cursor if the
@@ -422,6 +433,27 @@ static void fbcon_setup(int con, int init, int logo)
logo = 0;
p->var.xoffset = p->var.yoffset = p->yscroll = 0; /* reset wrap/pan */
+
+ if (con == fg_console && p->type != FB_TYPE_TEXT) {
+ if (fbcon_softback_size) {
+ if (!softback_buf) {
+ softback_buf = (unsigned long)kmalloc(fbcon_softback_size, GFP_KERNEL);
+ if (!softback_buf) {
+ fbcon_softback_size = 0;
+ softback_top = 0;
+ }
+ }
+ } else {
+ if (softback_buf) {
+ kfree((void *)softback_buf);
+ softback_buf = 0;
+ softback_top = 0;
+ }
+ }
+ if (softback_buf)
+ softback_in = softback_top = softback_curr = softback_buf;
+ softback_lines = 0;
+ }
for (i = 0; i < MAX_NR_CONSOLES; i++)
if (i != con && fb_display[i].fb_info == p->fb_info &&
@@ -579,6 +611,17 @@ static void fbcon_setup(int con, int init, int logo)
logo_shown = -2;
conp->vc_top = logo_lines;
}
+
+ if (con == fg_console && softback_buf) {
+ int l = fbcon_softback_size / conp->vc_size_row;
+ if (l > 5)
+ softback_end = softback_buf + l * conp->vc_size_row;
+ else {
+ /* Smaller scrollback makes no sense, and 0 would screw
+ the operation totally */
+ softback_top = 0;
+ }
+ }
}
@@ -703,17 +746,29 @@ static void fbcon_cursor(struct vc_data *conp, int mode)
{
int unit = conp->vc_num;
struct display *p = &fb_display[unit];
+ int y = conp->vc_y;
+
+ if (mode & CM_SOFTBACK) {
+ mode &= ~CM_SOFTBACK;
+ if (softback_lines) {
+ if (y + softback_lines >= conp->vc_rows)
+ mode = CM_ERASE;
+ else
+ y += softback_lines;
+ }
+ } else if (softback_lines)
+ fbcon_set_origin(conp);
/* do we have a hardware cursor ? */
if (p->dispsw->cursor) {
p->cursor_x = conp->vc_x;
- p->cursor_y = conp->vc_y;
+ p->cursor_y = y;
p->dispsw->cursor(p, mode, p->cursor_x, real_y(p, p->cursor_y));
return;
}
/* Avoid flickering if there's no real change. */
- if (p->cursor_x == conp->vc_x && p->cursor_y == conp->vc_y &&
+ if (p->cursor_x == conp->vc_x && p->cursor_y == y &&
(mode == CM_ERASE) == !cursor_on)
return;
@@ -722,7 +777,7 @@ static void fbcon_cursor(struct vc_data *conp, int mode)
p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y));
p->cursor_x = conp->vc_x;
- p->cursor_y = conp->vc_y;
+ p->cursor_y = y;
switch (mode) {
case CM_ERASE:
@@ -836,6 +891,94 @@ static __inline__ void ypan_down(int unit, struct vc_data *conp,
scrollback_current = 0;
}
+static void fbcon_redraw_softback(struct vc_data *conp, struct display *p, long delta)
+{
+ unsigned short *d, *s;
+ unsigned long n;
+ int line = 0;
+ int count = conp->vc_rows;
+
+ d = (u16 *)softback_curr;
+ if (d == (u16 *)softback_in)
+ d = (u16 *)conp->vc_origin;
+ n = softback_curr + delta * conp->vc_size_row;
+ softback_lines -= delta;
+ if (delta < 0) {
+ if (softback_curr < softback_top && n < softback_buf) {
+ n += softback_end - softback_buf;
+ if (n < softback_top) {
+ softback_lines -= (softback_top - n) / conp->vc_size_row;
+ n = softback_top;
+ }
+ } else if (softback_curr >= softback_top && n < softback_top) {
+ softback_lines -= (softback_top - n) / conp->vc_size_row;
+ n = softback_top;
+ }
+ } else {
+ if (softback_curr > softback_in && n >= softback_end) {
+ n += softback_buf - softback_end;
+ if (n > softback_in) {
+ n = softback_in;
+ softback_lines = 0;
+ }
+ } else if (softback_curr <= softback_in && n > softback_in) {
+ n = softback_in;
+ softback_lines = 0;
+ }
+ }
+ if (n == softback_curr)
+ return;
+ softback_curr = n;
+ s = (u16 *)softback_curr;
+ if (s == (u16 *)softback_in)
+ s = (u16 *)conp->vc_origin;
+ while (count--) {
+ unsigned short *start;
+ unsigned short *le;
+ unsigned short c;
+ int x = 0;
+ unsigned short attr = 1;
+
+ start = s;
+ le = advance_row(s, 1);
+ do {
+ c = scr_readw(s);
+ if (attr != (c & 0xff00)) {
+ attr = c & 0xff00;
+ if (s > start) {
+ p->dispsw->putcs(conp, p, start, s - start,
+ real_y(p, line), x);
+ x += s - start;
+ start = s;
+ }
+ }
+ if (c == scr_readw(d)) {
+ if (s > start) {
+ p->dispsw->putcs(conp, p, start, s - start,
+ real_y(p, line), x);
+ x += s - start + 1;
+ start = s + 1;
+ } else {
+ x++;
+ start++;
+ }
+ }
+ s++;
+ d++;
+ } while (s < le);
+ if (s > start)
+ p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x);
+ line++;
+ if (d == (u16 *)softback_end)
+ d = (u16 *)softback_buf;
+ if (d == (u16 *)softback_in)
+ d = (u16 *)conp->vc_origin;
+ if (s == (u16 *)softback_end)
+ s = (u16 *)softback_buf;
+ if (s == (u16 *)softback_in)
+ s = (u16 *)conp->vc_origin;
+ }
+}
static void fbcon_redraw(struct vc_data *conp, struct display *p,
int line, int count, int offset)
@@ -846,8 +989,7 @@ static void fbcon_redraw(struct vc_data *conp, struct display *p,
while (count--) {
unsigned short *start = s;
- unsigned short *le = (unsigned short *)
- ((unsigned long)s + conp->vc_size_row);
+ unsigned short *le = advance_row(s, 1);
unsigned short c;
int x = 0;
unsigned short attr = 1;
@@ -940,13 +1082,32 @@ void fbcon_redraw_bmove(struct display *p, int sy, int sx, int dy, int dx, int h
}
}
+static inline void fbcon_softback_note(struct vc_data *conp, int t, int count)
+{
+ unsigned short *p = (unsigned short *)
+ (conp->vc_origin + t * conp->vc_size_row);
+ while (count) {
+ scr_memcpyw((u16 *)softback_in, p, conp->vc_size_row);
+ count--;
+ p = advance_row(p, 1);
+ softback_in += conp->vc_size_row;
+ if (softback_in == softback_end)
+ softback_in = softback_buf;
+ if (softback_in == softback_top) {
+ softback_top += conp->vc_size_row;
+ if (softback_top == softback_end)
+ softback_top = softback_buf;
+ }
+ }
+ softback_curr = softback_in;
+}
+
static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir,
int count)
{
int unit = conp->vc_num;
struct display *p = &fb_display[unit];
int scroll_partial = !(p->scrollmode & __SCROLL_YNOPARTIAL);
- int logos_left = 0; int logos_width = conp->vc_cols;
if (!p->can_soft_blank && console_blanked)
return 0;
@@ -955,7 +1116,7 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir,
return 0;
fbcon_cursor(conp, CM_ERASE);
-
+
/*
* ++Geert: Only use ywrap/ypan if the console is in text mode
* ++Andrew: Only use ypan on hardware text mode when scrolling the
@@ -964,34 +1125,25 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir,
switch (dir) {
case SM_UP:
- /* K.Garloff@ping.de, 98/10/21: If logo is diplayed, only save logo
- * and not the hole top region. In combination with the logo being
- * displayed on the right side, this allows scrollback feature
- * when bootlogo is displayed. */
- if (t != 0 && logo_shown == fg_console) {
- struct display *p = &fb_display[unit];
- int lw = (smp_num_cpus * (LOGO_W + 8) - 7) / fontwidth(p) + 1;
- logos_left = conp->vc_cols - lw;
- while (logos_left < 0) logos_left += (LOGO_W + 8 - 7) / fontwidth(p);
- logos_width = conp->vc_cols - logos_left;
- }
if (count > conp->vc_rows) /* Maximum realistic size */
count = conp->vc_rows;
+ if (softback_top)
+ fbcon_softback_note(conp, t, count);
+ if (logo_shown >= 0) goto redraw_up;
switch (p->scrollmode & __SCROLL_YMASK) {
case __SCROLL_YMOVE:
- if (t > 0) p->dispsw->bmove(p, 0, logos_left, count,
- logos_left, t, logos_width);
- p->dispsw->bmove(p, count, 0, 0, 0, b-count,
+ p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count,
conp->vc_cols);
- p->dispsw->clear(conp, p, b-count, 0, count,
+ p->dispsw->clear(conp, p, b-count, 0, count,
conp->vc_cols);
break;
case __SCROLL_YWRAP:
- if (b-t-count > 2*conp->vc_rows/3) {
+ if (b-t-count > 3*conp->vc_rows>>2) {
if (t > 0)
- fbcon_bmove(conp, 0, logos_left, count, logos_left, t, logos_width);
- ywrap_up(unit, conp, p, count);
+ fbcon_bmove(conp, 0, 0, count, 0, t,
+ conp->vc_cols);
+ ywrap_up(unit, conp, p, count);
if (conp->vc_rows-b > 0)
fbcon_bmove(conp, b-count, 0, b, 0,
conp->vc_rows-b, conp->vc_cols);
@@ -1004,11 +1156,12 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir,
break;
case __SCROLL_YPAN:
- if (( !scroll_partial && (b-t == conp->vc_rows)) ||
- ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2))) {
+ if (( p->yscroll + count <= 2 * (p->vrows - conp->vc_rows)) &&
+ (( !scroll_partial && (b-t == conp->vc_rows)) ||
+ ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2)))) {
if (t > 0)
- fbcon_bmove(conp, 0, logos_left, count, logos_left, t,
- logos_width);
+ fbcon_bmove(conp, 0, 0, count, 0, t,
+ conp->vc_cols);
ypan_up(unit, conp, p, count);
if (conp->vc_rows-b > 0)
fbcon_bmove(conp, b-count, 0, b, 0,
@@ -1063,8 +1216,9 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir,
break;
case __SCROLL_YPAN:
- if (( !scroll_partial && (b-t == conp->vc_rows)) ||
- ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2))) {
+ if (( count-p->yscroll <= p->vrows-conp->vc_rows) &&
+ (( !scroll_partial && (b-t == conp->vc_rows)) ||
+ ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2)))) {
if (conp->vc_rows-b > 0)
fbcon_bmove(conp, b, 0, b-count, 0,
conp->vc_rows-b, conp->vc_cols);
@@ -1112,7 +1266,7 @@ static void fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
(sx <= p->cursor_x) && (p->cursor_x < sx+width)) ||
((dy <= p->cursor_y) && (p->cursor_y < dy+height) &&
(dx <= p->cursor_x) && (p->cursor_x < dx+width)))
- fbcon_cursor(conp, CM_ERASE);
+ fbcon_cursor(conp, CM_ERASE|CM_SOFTBACK);
/* Split blits that cross physical y_wrap case.
* Pathological case involves 4 blits, better to use recursive
@@ -1162,6 +1316,21 @@ static int fbcon_switch(struct vc_data *conp)
struct display *p = &fb_display[unit];
struct fb_info *info = p->fb_info;
+ if (softback_top) {
+ int l = fbcon_softback_size / conp->vc_size_row;
+ if (softback_lines)
+ fbcon_set_origin(conp);
+ softback_top = softback_curr = softback_in = softback_buf;
+ softback_lines = 0;
+
+ if (l > 5)
+ softback_end = softback_buf + l * conp->vc_size_row;
+ else {
+ /* Smaller scrollback makes no sense, and 0 would screw
+ the operation totally */
+ softback_top = 0;
+ }
+ }
if (logo_shown >= 0) {
struct vc_data *conp2 = vc_cons[logo_shown].d;
@@ -1227,8 +1396,22 @@ static int fbcon_blank(struct vc_data *conp, int blank)
mymemset(p->screen_base,
p->var.xres_virtual*p->var.yres_virtual*
p->var.bits_per_pixel>>3);
- } else
- p->dispsw->clear(conp, p, 0, 0, conp->vc_rows, conp->vc_cols);
+ } else {
+ unsigned short oldc;
+ u_int height;
+ u_int y_break;
+
+ oldc = conp->vc_video_erase_char;
+ conp->vc_video_erase_char &= p->charmask;
+ height = conp->vc_rows;
+ y_break = p->vrows-p->yscroll;
+ if (height > y_break) {
+ p->dispsw->clear(conp, p, real_y(p, 0), 0, y_break, conp->vc_cols);
+ p->dispsw->clear(conp, p, real_y(p, y_break), 0, height-y_break, conp->vc_cols);
+ } else
+ p->dispsw->clear(conp, p, real_y(p, 0), 0, height, conp->vc_cols);
+ conp->vc_video_erase_char = oldc;
+ }
return 0;
} else {
/* Tell console.c that it has to restore the screen itself */
@@ -1320,6 +1503,9 @@ static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int
return -ENXIO;
}
+ if (CON_IS_VISIBLE(p->conp) && softback_lines)
+ fbcon_set_origin(p->conp);
+
resize = (w != fontwidth(p)) || (h != fontheight(p));
if (p->userfont)
old_data = p->fontdata;
@@ -1390,6 +1576,7 @@ static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int
fbcon_font_widths(p);
if (resize) {
+ struct vc_data *conp = p->conp;
/* reset wrap/pan */
p->var.xoffset = p->var.yoffset = p->yscroll = 0;
p->vrows = p->var.yres_virtual/h;
@@ -1397,6 +1584,16 @@ static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int
p->vrows--;
updatescrollmode(p);
vc_resize_con( p->var.yres/h, p->var.xres/w, unit );
+ if (CON_IS_VISIBLE(conp) && softback_buf) {
+ int l = fbcon_softback_size / conp->vc_size_row;
+ if (l > 5)
+ softback_end = softback_buf + l * conp->vc_size_row;
+ else {
+ /* Smaller scrollback makes no sense, and 0 would screw
+ the operation totally */
+ softback_top = 0;
+ }
+ }
} else if (CON_IS_VISIBLE(p->conp) && vt_cons[unit]->vc_mode == KD_TEXT) {
if (p->dispsw->clear_margins)
p->dispsw->clear_margins(p->conp, p, 0);
@@ -1432,9 +1629,6 @@ static inline int fbcon_set_font(int unit, struct console_font_op *op)
int h = op->height;
int size = h;
int i, k;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
- int j;
-#endif
u8 *new_data, *data = op->data, *p;
#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
@@ -1476,6 +1670,7 @@ static inline int fbcon_set_font(int unit, struct console_font_op *op)
}
} else if (w <= 24) {
for (i = 0; i < op->charcount; i++) {
+ int j;
for (j = 0; j < h; j++) {
memcpy(p, data, 3);
p[3] = 0;
@@ -1505,6 +1700,7 @@ static inline int fbcon_set_font(int unit, struct console_font_op *op)
fb_display[i].fontdata &&
FNTSUM(fb_display[i].fontdata) == k &&
FNTSIZE(fb_display[i].fontdata) == size &&
+ fontwidth(&fb_display[i]) == w &&
!memcmp(fb_display[i].fontdata, new_data, size)) {
kfree(new_data - FONT_EXTRA_WORDS*sizeof(int));
new_data = fb_display[i].fontdata;
@@ -1586,10 +1782,119 @@ static int fbcon_set_palette(struct vc_data *conp, unsigned char *table)
return p->fb_info->fbops->fb_set_cmap(&palette_cmap, 1, unit, p->fb_info);
}
+static u16 *fbcon_screen_pos(struct vc_data *conp, int offset)
+{
+ int line;
+ unsigned long p;
+
+ if (conp->vc_num != fg_console || !softback_lines)
+ return (u16 *)(conp->vc_origin + offset);
+ line = offset / conp->vc_size_row;
+ if (line >= softback_lines)
+ return (u16 *)(conp->vc_origin + offset - softback_lines * conp->vc_size_row);
+ p = softback_curr + offset;
+ if (p >= softback_end)
+ p += softback_buf - softback_end;
+ return (u16 *)p;
+}
+
+static unsigned long fbcon_getxy(struct vc_data *conp, unsigned long pos, int *px, int *py)
+{
+ int x, y;
+ unsigned long ret;
+ if (pos >= conp->vc_origin && pos < conp->vc_scr_end) {
+ unsigned long offset = (pos - conp->vc_origin) / 2;
+
+ x = offset % conp->vc_cols;
+ y = offset / conp->vc_cols;
+ if (conp->vc_num == fg_console)
+ y += softback_lines;
+ ret = pos + (conp->vc_cols - x) * 2;
+ } else if (conp->vc_num == fg_console && softback_lines) {
+ unsigned long offset = (pos - softback_curr) / 2;
+
+ x = offset % conp->vc_cols;
+ y = offset / conp->vc_cols;
+ if (pos < softback_curr)
+ y += (softback_end - softback_buf) / conp->vc_size_row;
+ ret = pos + (conp->vc_cols - x) * 2;
+ if (ret == softback_end)
+ ret = softback_buf;
+ if (ret == softback_in)
+ ret = conp->vc_origin;
+ } else {
+ /* Should not happen */
+ x = y = 0;
+ ret = conp->vc_origin;
+ }
+ if (px) *px = x;
+ if (py) *py = y;
+ return ret;
+}
+
+/* As we might be inside of softback, we may work with non-contiguous buffer,
+ that's why we have to use a separate routine. */
+static void fbcon_invert_region(struct vc_data *conp, u16 *p, int cnt)
+{
+ while (cnt--) {
+ if (!conp->vc_can_do_color)
+ *p++ ^= 0x0800;
+ else if (conp->vc_hi_font_mask == 0x100) {
+ u16 a = *p;
+ a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4);
+ *p++ = a;
+ } else {
+ u16 a = *p;
+ a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
+ *p++ = a;
+ }
+ if (p == (u16 *)softback_end)
+ p = (u16 *)softback_buf;
+ if (p == (u16 *)softback_in)
+ p = (u16 *)conp->vc_origin;
+ }
+}
+
static int fbcon_scrolldelta(struct vc_data *conp, int lines)
{
int unit, offset, limit, scrollback_old;
struct display *p;
+
+ unit = fg_console;
+ p = &fb_display[unit];
+ if (softback_top) {
+ if (conp->vc_num != unit)
+ return 0;
+ if (vt_cons[unit]->vc_mode != KD_TEXT || !lines)
+ return 0;
+ if (logo_shown >= 0) {
+ struct vc_data *conp2 = vc_cons[logo_shown].d;
+
+ if (conp2->vc_top == logo_lines && conp2->vc_bottom == conp2->vc_rows)
+ conp2->vc_top = 0;
+ if (logo_shown == unit) {
+ unsigned long p, q;
+ int i;
+
+ p = softback_in;
+ q = conp->vc_origin + logo_lines * conp->vc_size_row;
+ for (i = 0; i < logo_lines; i++) {
+ if (p == softback_top) break;
+ if (p == softback_buf) p = softback_end;
+ p -= conp->vc_size_row;
+ q -= conp->vc_size_row;
+ scr_memcpyw((u16 *)q, (u16 *)p, conp->vc_size_row);
+ }
+ softback_in = p;
+ update_region(unit, conp->vc_origin, logo_lines * conp->vc_cols);
+ }
+ logo_shown = -1;
+ }
+ fbcon_cursor(conp, CM_ERASE|CM_SOFTBACK);
+ fbcon_redraw_softback(conp, p, lines);
+ fbcon_cursor(conp, CM_DRAW|CM_SOFTBACK);
+ return 0;
+ }
if (!scrollback_phys_max)
return -ENOSYS;
@@ -1603,8 +1908,6 @@ static int fbcon_scrolldelta(struct vc_data *conp, int lines)
if (scrollback_current == scrollback_old)
return 0;
- unit = fg_console;
- p = &fb_display[unit];
if (!p->can_soft_blank &&
(console_blanked || vt_cons[unit]->vc_mode != KD_TEXT || !lines))
return 0;
@@ -1633,6 +1936,13 @@ static int fbcon_scrolldelta(struct vc_data *conp, int lines)
return 0;
}
+static int fbcon_set_origin(struct vc_data *conp)
+{
+ if (softback_lines && !console_blanked)
+ fbcon_scrolldelta(conp, softback_lines);
+ return 0;
+}
+
static inline unsigned safe_shift(unsigned d,int n)
{
return n<0 ? d>>-n : d<<n;
@@ -1652,7 +1962,7 @@ __initfunc(static int fbcon_show_logo( void ))
/* Return if the frame buffer is not mapped */
if (!fb)
return 0;
-
+
/* Set colors if visual is PSEUDOCOLOR and we have enough colors, or for
* DIRECTCOLOR */
if ((p->visual == FB_VISUAL_PSEUDOCOLOR && depth >= 4) ||
@@ -1704,9 +2014,12 @@ __initfunc(static int fbcon_show_logo( void ))
logo = linux_logo_bw;
logo_depth = 1;
}
+
+ if (p->fb_info->fbops->fb_rasterimg)
+ p->fb_info->fbops->fb_rasterimg(p->fb_info, 1);
- for (x = p->var.xres - LOGO_W; x > 0 && x > (int)p->var.xres
- - smp_num_cpus * (LOGO_W + 8); x -= (LOGO_W + 8)) {
+ for (x = 0; x < smp_num_cpus * (LOGO_W + 8) &&
+ x < p->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) {
#if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \
defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS)
@@ -1730,12 +2043,18 @@ __initfunc(static int fbcon_show_logo( void ))
val = (*src << redshift) |
(*src << greenshift) |
(*src << blueshift);
+ if (bdepth == 4 && !((long)dst & 3)) {
+ /* Some cards require 32bit access */
+ *(u32 *)dst = val;
+ dst += 4;
+ } else {
#ifdef __LITTLE_ENDIAN
- for( i = 0; i < bdepth; ++i )
+ for( i = 0; i < bdepth; ++i )
#else
- for( i = bdepth-1; i >= 0; --i )
+ for( i = bdepth-1; i >= 0; --i )
#endif
- *dst++ = val >> (i*8);
+ *dst++ = val >> (i*8);
+ }
}
}
}
@@ -1798,12 +2117,18 @@ __initfunc(static int fbcon_show_logo( void ))
val = safe_shift((linux_logo_red[*src-32] & redmask), redshift) |
safe_shift((linux_logo_green[*src-32] & greenmask), greenshift) |
safe_shift((linux_logo_blue[*src-32] & bluemask), blueshift);
+ if (bdepth == 4 && !((long)dst & 3)) {
+ /* Some cards require 32bit access */
+ *(u32 *)dst = val;
+ dst += 4;
+ } else {
#ifdef __LITTLE_ENDIAN
- for( i = 0; i < bdepth; ++i )
+ for( i = 0; i < bdepth; ++i )
#else
- for( i = bdepth-1; i >= 0; --i )
+ for( i = bdepth-1; i >= 0; --i )
#endif
- *dst++ = val >> (i*8);
+ *dst++ = val >> (i*8);
+ }
}
}
done = 1;
@@ -1914,6 +2239,9 @@ __initfunc(static int fbcon_show_logo( void ))
#endif
}
+ if (p->fb_info->fbops->fb_rasterimg)
+ p->fb_info->fbops->fb_rasterimg(p->fb_info, 0);
+
/* Modes not yet supported: packed pixels with depth != 8 (does such a
* thing exist in reality?) */
@@ -1939,10 +2267,12 @@ struct consw fb_con = {
con_font_op: fbcon_font_op,
con_set_palette: fbcon_set_palette,
con_scrolldelta: fbcon_scrolldelta,
- con_set_origin: NULL,
+ con_set_origin: fbcon_set_origin,
con_save_screen: NULL,
con_build_attr: NULL,
- con_invert_region: NULL,
+ con_invert_region: fbcon_invert_region,
+ con_screen_pos: fbcon_screen_pos,
+ con_getxy: fbcon_getxy,
};
diff --git a/drivers/video/fbgen.c b/drivers/video/fbgen.c
index c3c42ed5e..ff14807a0 100644
--- a/drivers/video/fbgen.c
+++ b/drivers/video/fbgen.c
@@ -244,7 +244,6 @@ void fbgen_set_disp(int con, struct fb_info_gen *info)
memset(&fix, 0, sizeof(struct fb_fix_screeninfo));
fbhw->encode_fix(&fix, &par, info);
- display->screen_base = phys_to_virt((unsigned long)fix.smem_start);
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
@@ -256,7 +255,7 @@ void fbgen_set_disp(int con, struct fb_info_gen *info)
display->can_soft_blank = 1;
else
display->can_soft_blank = 0;
- fbhw->set_dispsw(&par, display, info);
+ fbhw->set_disp(&par, display, info);
#if 0 /* FIXME: generic inverse is not supported yet */
display->inverse = (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
#else
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index d8e6b0829..34c57ddb5 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -88,12 +88,20 @@ extern void sbusfb_setup(char *options, int *ints);
extern void valkyriefb_init(void);
extern void valkyriefb_setup(char *options, int *ints);
extern void g364fb_init(void);
+extern void fm2fb_init(void);
+extern void fm2fb_setup(char *options, int *ints);
+extern void q40fb_init(void);
+extern void sgivwfb_init(void);
+extern void sgivwfb_setup(char* options, int *ints);
static struct {
const char *name;
void (*init)(void);
void (*setup)(char *options, int *ints);
} fb_drivers[] __initdata = {
+#ifdef CONFIG_FB_SGIVW
+ { "sgivw", sgivwfb_init, sgivwfb_setup },
+#endif
#ifdef CONFIG_FB_RETINAZ3
{ "retz3", retz3fb_init, retz3fb_setup },
#endif
@@ -136,6 +144,9 @@ static struct {
#ifdef CONFIG_APOLLO
{ "apollo", dnfb_init, NULL },
#endif
+#ifdef CONFIG_FB_Q40
+ { "q40fb", q40fb_init, NULL },
+#endif
#ifdef CONFIG_FB_S3TRIO
{ "s3trio", s3triofb_init, s3triofb_setup },
#endif
@@ -160,6 +171,9 @@ static struct {
#ifdef CONFIG_FB_G364
{ "g364", g364fb_init, NULL },
#endif
+#ifdef CONFIG_FB_FM2
+ { "fm2fb", fm2fb_init, fm2fb_setup },
+#endif
#ifdef CONFIG_GSP_RESOLVER
/* Not a real frame buffer device... */
{ "resolver", NULL, resolver_video_setup },
@@ -181,6 +195,7 @@ static int num_pref_init_funcs __initdata = 0;
struct fb_info *registered_fb[FB_MAX];
int num_registered_fb = 0;
+int fbcon_softback_size = 32768;
char con2fb_map[MAX_NR_CONSOLES];
@@ -188,17 +203,24 @@ static int first_fb_vc = 0;
static int last_fb_vc = MAX_NR_CONSOLES-1;
static int fbcon_is_default = 1;
-static inline int PROC_CONSOLE(void)
+static int PROC_CONSOLE(struct fb_info *info)
{
+ int fgc;
+
+ if (info->display_fg != NULL)
+ fgc = info->display_fg->vc_num;
+ else
+ return -1;
+
if (!current->tty)
- return fg_console;
+ return fgc;
if (current->tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
/* XXX Should report error here? */
- return fg_console;
+ return fgc;
if (MINOR(current->tty->device) < 1)
- return fg_console;
+ return fgc;
return MINOR(current->tty->device) - 1;
}
@@ -233,7 +255,7 @@ fb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
if (! fb || ! info->disp)
return -ENODEV;
- fb->fb_get_fix(&fix,PROC_CONSOLE(), info);
+ fb->fb_get_fix(&fix,PROC_CONSOLE(info), info);
base_addr=info->disp->screen_base;
copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
if (copy_to_user(buf, base_addr+p, copy_size))
@@ -257,7 +279,7 @@ fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
if (! fb || ! info->disp)
return -ENODEV;
- fb->fb_get_fix(&fix, PROC_CONSOLE(), info);
+ fb->fb_get_fix(&fix, PROC_CONSOLE(info), info);
base_addr=info->disp->screen_base;
copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
if (copy_from_user(base_addr+p, buf, copy_size))
@@ -273,7 +295,7 @@ static int set_all_vcs(int fbidx, struct fb_ops *fb,
int unit, err;
var->activate |= FB_ACTIVATE_TEST;
- err = fb->fb_set_var(var, PROC_CONSOLE(), info);
+ err = fb->fb_set_var(var, PROC_CONSOLE(info), info);
var->activate &= ~FB_ACTIVATE_TEST;
if (err)
return err;
@@ -350,7 +372,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return -ENODEV;
switch (cmd) {
case FBIOGET_VSCREENINFO:
- if ((i = fb->fb_get_var(&var, PROC_CONSOLE(), info)))
+ if ((i = fb->fb_get_var(&var, PROC_CONSOLE(info), info)))
return i;
return copy_to_user((void *) arg, &var,
sizeof(var)) ? -EFAULT : 0;
@@ -359,29 +381,29 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return -EFAULT;
i = var.activate & FB_ACTIVATE_ALL
? set_all_vcs(fbidx, fb, &var, info)
- : fb->fb_set_var(&var, PROC_CONSOLE(), info);
+ : fb->fb_set_var(&var, PROC_CONSOLE(info), info);
if (i)
return i;
if (copy_to_user((void *) arg, &var, sizeof(var)))
return -EFAULT;
return 0;
case FBIOGET_FSCREENINFO:
- if ((i = fb->fb_get_fix(&fix, PROC_CONSOLE(), info)))
+ if ((i = fb->fb_get_fix(&fix, PROC_CONSOLE(info), info)))
return i;
return copy_to_user((void *) arg, &fix, sizeof(fix)) ?
-EFAULT : 0;
case FBIOPUTCMAP:
if (copy_from_user(&cmap, (void *) arg, sizeof(cmap)))
return -EFAULT;
- return (fb->fb_set_cmap(&cmap, 0, PROC_CONSOLE(), info));
+ return (fb->fb_set_cmap(&cmap, 0, PROC_CONSOLE(info), info));
case FBIOGETCMAP:
if (copy_from_user(&cmap, (void *) arg, sizeof(cmap)))
return -EFAULT;
- return (fb->fb_get_cmap(&cmap, 0, PROC_CONSOLE(), info));
+ return (fb->fb_get_cmap(&cmap, 0, PROC_CONSOLE(info), info));
case FBIOPAN_DISPLAY:
if (copy_from_user(&var, (void *) arg, sizeof(var)))
return -EFAULT;
- if ((i=fb->fb_pan_display(&var, PROC_CONSOLE(), info)))
+ if ((i=fb->fb_pan_display(&var, PROC_CONSOLE(info), info)))
return i;
if (copy_to_user((void *) arg, &var, sizeof(var)))
return -EFAULT;
@@ -415,7 +437,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
set_con2fb_map(i, con2fb.framebuffer);
return 0;
default:
- return fb->fb_ioctl(inode, file, cmd, arg, PROC_CONSOLE(),
+ return fb->fb_ioctl(inode, file, cmd, arg, PROC_CONSOLE(info),
info);
}
}
@@ -435,7 +457,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
return -ENODEV;
if (fb->fb_mmap)
return fb->fb_mmap(info, file, vma);
- fb->fb_get_fix(&fix, PROC_CONSOLE(), info);
+ fb->fb_get_fix(&fix, PROC_CONSOLE(info), info);
/* frame buffer memory */
start = (unsigned long)fix.smem_start;
@@ -445,7 +467,7 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
if (vma->vm_offset >= len) {
/* memory mapped io */
vma->vm_offset -= len;
- fb->fb_get_var(&var, PROC_CONSOLE(), info);
+ fb->fb_get_var(&var, PROC_CONSOLE(info), info);
if (var.accel_flags)
return -EINVAL;
start = (unsigned long)fix.mmio_start;
@@ -485,8 +507,6 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
if (remap_page_range(vma->vm_start, vma->vm_offset,
vma->vm_end - vma->vm_start, vma->vm_page_prot))
return -EAGAIN;
- vma->vm_file = file;
- file->f_count++;
return 0;
}
@@ -648,6 +668,21 @@ __initfunc(void video_setup(char *options, int *ints))
if (!options || !*options)
return;
+ if (!strncmp(options, "scrollback:", 11)) {
+ options += 11;
+ if (*options) {
+ fbcon_softback_size = simple_strtoul(options, &options, 0);
+ if (*options == 'k' || *options == 'K') {
+ fbcon_softback_size *= 1024;
+ options++;
+ }
+ if (*options != ',')
+ return;
+ options++;
+ } else
+ return;
+ }
+
if (!strncmp(options, "map:", 4)) {
options += 4;
if (*options)
@@ -658,7 +693,7 @@ __initfunc(void video_setup(char *options, int *ints))
}
return;
}
-
+
if (!strncmp(options, "vc:", 3)) {
options += 3;
if (*options)
diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c
new file mode 100644
index 000000000..e5ab75e08
--- /dev/null
+++ b/drivers/video/fm2fb.c
@@ -0,0 +1,572 @@
+/*
+ * linux/drivers/video/fm2fb.c -- BSC FrameMaster II/Rainbow II frame buffer
+ * device
+ *
+ * Copyright (C) 1998 Steffen A. Mork (mork@ls7.cs.uni-dortmund.de)
+ * Copyright (C) 1999 Geert Uytterhoeven
+ *
+ * Written for 2.0.x by Steffen A. Mork
+ * Ported to 2.1.x by Geert Uytterhoeven
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/mm.h>
+#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:
+ *
+ * The BSC FrameMaster II (or Rainbow II) is a simple very dumb
+ * frame buffer which allows to display 24 bit true color images.
+ * Each pixel is 32 bit width so it's very easy to maintain the
+ * frame buffer. One long word has the following layout:
+ * AARRGGBB which means: AA the alpha channel byte, RR the red
+ * channel, GG the green channel and BB the blue channel.
+ *
+ * The FrameMaster II supports the following video modes.
+ * - PAL/NTSC
+ * - interlaced/non interlaced
+ * - composite sync/sync/sync over green
+ *
+ * The resolution is to the following both ones:
+ * - 768x576 (PAL)
+ * - 768x480 (NTSC)
+ *
+ * This means that pixel access per line is fixed due to the
+ * fixed line width. In case of maximal resolution the frame
+ * buffer needs an amount of memory of 1.769.472 bytes which
+ * is near to 2 MByte (the allocated address space of Zorro2).
+ * The memory is channel interleaved. That means every channel
+ * owns four VRAMs. Unfortunatly most FrameMasters II are
+ * not assembled with memory for the alpha channel. In this
+ * case it could be possible to add the frame buffer into the
+ * normal memory pool.
+ *
+ * At relative address 0x1ffff8 of the frame buffers base address
+ * there exists a control register with the number of
+ * four control bits. They have the following meaning:
+ * bit value meaning
+ *
+ * 0 1 0=interlaced/1=non interlaced
+ * 1 2 0=video out disabled/1=video out enabled
+ * 2 4 0=normal mode as jumpered via JP8/1=complement mode
+ * 3 8 0=read onboard ROM/1 normal operation (required)
+ *
+ * As mentioned above there are several jumper. I think there
+ * is not very much information about the FrameMaster II in
+ * the world so I add these information for completeness.
+ *
+ * JP1 interlace selection (1-2 non interlaced/2-3 interlaced)
+ * JP2 wait state creation (leave as is!)
+ * JP3 wait state creation (leave as is!)
+ * JP4 modulate composite sync on green output (1-2 composite
+ * sync on green channel/2-3 normal composite sync)
+ * JP5 create test signal, shorting this jumper will create
+ * a white screen
+ * JP6 sync creation (1-2 composite sync/2-3 H-sync output)
+ * JP8 video mode (1-2 PAL/2-3 NTSC)
+ *
+ * With the following jumpering table you can connect the
+ * FrameMaster II to a normal TV via SCART connector:
+ * JP1: 2-3
+ * JP4: 2-3
+ * JP6: 2-3
+ * JP8: 1-2 (means PAL for Europe)
+ *
+ * NOTE:
+ * There is no other possibility to change the video timings
+ * except the interlaced/non interlaced, sync control and the
+ * video mode PAL (50 Hz)/NTSC (60 Hz). Inside this
+ * FrameMaster II driver are assumed values to avoid anomalies
+ * to a future X server. Except the pixel clock is really
+ * constant at 30 MHz.
+ *
+ * 9 pin female video connector:
+ *
+ * 1 analog red 0.7 Vss
+ * 2 analog green 0.7 Vss
+ * 3 analog blue 0.7 Vss
+ * 4 H-sync TTL
+ * 5 V-sync TTL
+ * 6 ground
+ * 7 ground
+ * 8 ground
+ * 9 ground
+ *
+ * Some performance notes:
+ * The FrameMaster II was not designed to display a console
+ * this driver would do! It was designed to display still true
+ * color images. Imagine: When scroll up a text line there
+ * must copied ca. 1.7 MBytes to another place inside this
+ * frame buffer. This means 1.7 MByte read and 1.7 MByte write
+ * over the slow 16 bit wide Zorro2 bus! A scroll of one
+ * line needs 1 second so do not expect to much from this
+ * driver - he is at the limit!
+ *
+ */
+
+
+/*
+ * definitions
+ */
+
+#define FRAMEMASTER_SIZE 0x200000
+#define FRAMEMASTER_REG 0x1ffff8
+
+#define FRAMEMASTER_NOLACE 1
+#define FRAMEMASTER_ENABLE 2
+#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;
+
+#define arraysize(x) (sizeof(x)/sizeof(*(x)))
+
+static int currcon = 0;
+static struct display disp;
+static struct fb_info fb_info;
+static struct { u_char red, green, blue, pad; } palette[16];
+#ifdef FBCON_HAS_CFB32
+static u32 fbcon_cfb32_cmap[16];
+#endif
+
+static struct fb_fix_screeninfo fb_fix;
+static struct fb_var_screeninfo fb_var;
+
+static int fm2fb_mode __initdata = -1;
+
+#define FM2FB_MODE_PAL 0
+#define FM2FB_MODE_NTSC 1
+
+static struct fb_var_screeninfo fb_var_modes[] __initdata = {
+ {
+ /* 768 x 576, 32 bpp (PAL) */
+ 768, 576, 768, 576, 0, 0, 32, 0,
+ { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 8, 0 },
+ 0, FB_ACTIVATE_NOW, -1, -1, FB_ACCEL_NONE,
+ 33333, 10, 102, 10, 5, 80, 34, FB_SYNC_COMP_HIGH_ACT, 0
+ }, {
+ /* 768 x 480, 32 bpp (NTSC - not supported yet */
+ 768, 480, 768, 480, 0, 0, 32, 0,
+ { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 8, 0 },
+ 0, FB_ACTIVATE_NOW, -1, -1, FB_ACCEL_NONE,
+ 33333, 10, 102, 10, 5, 80, 34, FB_SYNC_COMP_HIGH_ACT, 0
+ }
+};
+
+
+ /*
+ * Interface used by the world
+ */
+
+static int fm2fb_open(struct fb_info *info, int user);
+static int fm2fb_release(struct fb_info *info, int user);
+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_pan_display(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_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info);
+static int fm2fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+ u_long arg, int con, struct fb_info *info);
+
+
+ /*
+ * Interface to the low level console driver
+ */
+
+void fm2fb_init(void);
+static int fm2fbcon_switch(int con, struct fb_info *info);
+static int fm2fbcon_updatevar(int con, struct fb_info *info);
+static void fm2fbcon_blank(int blank, 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 int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info);
+static void do_install_cmap(int con, struct fb_info *info);
+
+
+static struct fb_ops fm2fb_ops = {
+ fm2fb_open, fm2fb_release, fm2fb_get_fix, fm2fb_get_var, fm2fb_set_var,
+ fm2fb_get_cmap, fm2fb_set_cmap, fm2fb_pan_display, fm2fb_ioctl
+};
+
+
+ /*
+ * Open/Release the frame buffer device
+ */
+
+static int fm2fb_open(struct fb_info *info, int user)
+{
+ /*
+ * Nothing, only a usage count for the moment
+ */
+
+ MOD_INC_USE_COUNT;
+ return(0);
+}
+
+static int fm2fb_release(struct fb_info *info, int user)
+{
+ MOD_DEC_USE_COUNT;
+ return(0);
+}
+
+
+ /*
+ * Get the Fixed Part of the Display
+ */
+
+static int fm2fb_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 fm2fb_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 fm2fb_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;
+ }
+ if (oldbpp != var->bits_per_pixel) {
+ if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
+ return err;
+ do_install_cmap(con, info);
+ }
+ return 0;
+}
+
+
+ /*
+ * Pan or Wrap the Display
+ *
+ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+
+static int fm2fb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ if (var->xoffset || var->yoffset)
+ return -EINVAL;
+ else
+ return 0;
+}
+
+ /*
+ * Get the Colormap
+ */
+
+static int fm2fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ if (con == currcon) /* current console? */
+ return fb_get_cmap(cmap, kspc, 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;
+}
+
+ /*
+ * Set the Colormap
+ */
+
+static int fm2fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ int err;
+
+ if (!fb_display[con].cmap.len) { /* no colormap allocated? */
+ if ((err = fb_alloc_cmap(&fb_display[con].cmap, 256, 0)))
+ return err;
+ }
+ if (con == currcon) { /* current console? */
+ err = fb_set_cmap(cmap, kspc, fm2fb_setcolreg, info);
+ return err;
+ } else
+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+ return 0;
+}
+
+
+static int fm2fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+ u_long arg, int con, struct fb_info *info)
+{
+ return -EINVAL;
+}
+
+
+ /*
+ * Initialisation
+ */
+
+__initfunc(void fm2fb_init(void))
+{
+ int key, is_fm;
+ const struct ConfigDev *cd = NULL;
+ unsigned long board, *ptr;
+ int x, y;
+
+ if (!(key = is_fm = zorro_find(ZORRO_PROD_BSC_FRAMEMASTER_II, 0, 0)) &&
+ !(key = zorro_find(ZORRO_PROD_HELFRICH_RAINBOW_II, 0, 0)))
+ return;
+ cd = zorro_get_board(key);
+ if (!(board = (u_long)cd->cd_BoardAddr))
+ return;
+ zorro_config_board(key, 0);
+
+ /* assigning memory to kernel space */
+ fm2fb_mem_phys = board;
+ fm2fb_mem = ioremap(board, 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 */
+ }
+ fm2fbcon_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 = (char *)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 = (char *)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.screen_base = (char *)fm2fb_mem;
+ 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 = -1;
+ fb_info.fbops = &fm2fb_ops;
+ 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.blank = &fm2fbcon_blank;
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+ fm2fb_set_var(&fb_var, -1, &fb_info);
+
+ if (register_framebuffer(&fb_info) < 0)
+ return;
+
+ printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node),
+ fb_fix.id);
+}
+
+__initfunc(void fm2fb_setup(char *options, int *ints))
+{
+ char *this_opt;
+
+ if (!options || !*options)
+ return;
+
+ for (this_opt = strtok(options, ","); this_opt;
+ this_opt = strtok(NULL, ",")) {
+ if (!strncmp(this_opt, "pal", 3))
+ fm2fb_mode = FM2FB_MODE_PAL;
+ else if (!strncmp(this_opt, "ntsc", 4))
+ fm2fb_mode = FM2FB_MODE_NTSC;
+ }
+}
+
+
+static int fm2fbcon_switch(int con, struct fb_info *info)
+{
+ /* Do we have to save the colormap? */
+ if (fb_display[currcon].cmap.len)
+ fb_get_cmap(&fb_display[currcon].cmap, 1, fm2fb_getcolreg, info);
+
+ currcon = con;
+ /* Install new colormap */
+ do_install_cmap(con, info);
+ 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 void fm2fbcon_blank(int blank, struct fb_info *info)
+{
+ unsigned char t = FRAMEMASTER_ROM;
+
+ if (!blank)
+ t |= FRAMEMASTER_ENABLE | FRAMEMASTER_NOLACE;
+ fm2fb_reg[0] = t;
+}
+
+ /*
+ * 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;
+}
+
+
+static void do_install_cmap(int con, struct fb_info *info)
+{
+ if (con != currcon)
+ return;
+ if (fb_display[con].cmap.len)
+ fb_set_cmap(&fb_display[con].cmap, 1, fm2fb_setcolreg, info);
+ else
+ fb_set_cmap(fb_default_cmap(256), 1, fm2fb_setcolreg, info);
+}
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index e3a86c868..d6173e77e 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -304,8 +304,6 @@ static int igafb_mmap(struct fb_info *info, struct file *file,
if (!map_size)
return -EINVAL;
- vma->vm_file = file;
- file->f_count++;
vma->vm_flags |= VM_IO;
if (!fb->mmaped) {
diff --git a/drivers/video/leofb.c b/drivers/video/leofb.c
index 6bfd09fd8..0a273fe43 100644
--- a/drivers/video/leofb.c
+++ b/drivers/video/leofb.c
@@ -1,7 +1,7 @@
-/* $Id: leofb.c,v 1.4 1998/09/04 15:43:45 jj Exp $
+/* $Id: leofb.c,v 1.6 1999/04/01 13:03:25 jj Exp $
* leofb.c: Leo (ZX) 24/8bit frame buffer driver
*
- * Copyright (C) 1996,1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
* Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
*/
@@ -80,12 +80,12 @@ struct leo_lc_ss0_krn {
struct leo_lc_ss0_usr {
volatile u32 csr;
- volatile u32 attrs;
- volatile u32 fontc;
- volatile u32 fontc2;
+ volatile u32 addrspace;
+ volatile u32 fontmsk;
+ volatile u32 fontt;
volatile u32 extent;
volatile u32 src;
- u32 xxx1[1];
+ u32 dst;
volatile u32 copy;
volatile u32 fill;
};
@@ -98,19 +98,42 @@ struct leo_lc_ss1_usr {
u8 unknown;
};
-struct leo_ld_ss0 {
+struct leo_ld {
u8 xxx0[0xe00];
- u32 xxx1[2];
- volatile u32 unk;
- u32 xxx2[1];
- volatile u32 unk2;
- volatile u32 unk3;
- u32 xxx3[2];
+ volatile u32 csr;
+ volatile u32 wid;
+ volatile u32 wmask;
+ volatile u32 widclip;
+ volatile u32 vclipmin;
+ volatile u32 vclipmax;
+ volatile u32 pickmin; /* SS1 only */
+ volatile u32 pickmax; /* SS1 only */
volatile u32 fg;
volatile u32 bg;
- u8 xxx4[0x05c];
+ volatile u32 src; /* Copy/Scroll (SS0 only) */
+ volatile u32 dst; /* Copy/Scroll/Fill (SS0 only) */
+ volatile u32 extent; /* Copy/Scroll/Fill size (SS0 only) */
+ u32 xxx1[3];
+ volatile u32 setsem; /* SS1 only */
+ volatile u32 clrsem; /* SS1 only */
+ volatile u32 clrpick; /* SS1 only */
+ volatile u32 clrdat; /* SS1 only */
+ volatile u32 alpha; /* SS1 only */
+ u8 xxx2[0x2c];
+ volatile u32 winbg;
volatile u32 planemask;
volatile u32 rop;
+ volatile u32 z;
+ volatile u32 dczf; /* SS1 only */
+ volatile u32 dczb; /* SS1 only */
+ volatile u32 dcs; /* SS1 only */
+ volatile u32 dczs; /* SS1 only */
+ volatile u32 pickfb; /* SS1 only */
+ volatile u32 pickbb; /* SS1 only */
+ volatile u32 dcfc; /* SS1 only */
+ volatile u32 forcecol; /* SS1 only */
+ volatile u32 door[8]; /* SS1 only */
+ volatile u32 pick[5]; /* SS1 only */
};
#define LEO_SS1_MISC_ENABLE 0x00000001
@@ -126,17 +149,17 @@ struct leo_ld_gbl {
static struct sbus_mmap_map leo_mmap_map[] = {
{ LEO_SS0_MAP, LEO_OFF_SS0, 0x800000 },
- { LEO_LC_SS0_USR_MAP, LEO_OFF_LC_SS0_USR, PAGE_SIZE },
- { LEO_LD_SS0_MAP, LEO_OFF_LD_SS0, PAGE_SIZE },
- { LEO_LX_CURSOR_MAP, LEO_OFF_LX_CURSOR, PAGE_SIZE },
+ { LEO_LC_SS0_USR_MAP, LEO_OFF_LC_SS0_USR, 0x1000 },
+ { LEO_LD_SS0_MAP, LEO_OFF_LD_SS0, 0x1000 },
+ { LEO_LX_CURSOR_MAP, LEO_OFF_LX_CURSOR, 0x1000 },
{ LEO_SS1_MAP, LEO_OFF_SS1, 0x800000 },
- { LEO_LC_SS1_USR_MAP, LEO_OFF_LC_SS1_USR, PAGE_SIZE },
- { LEO_LD_SS1_MAP, LEO_OFF_LD_SS1, PAGE_SIZE },
- { LEO_UNK_MAP, LEO_OFF_UNK, PAGE_SIZE },
- { LEO_LX_KRN_MAP, LEO_OFF_LX_KRN, PAGE_SIZE },
- { LEO_LC_SS0_KRN_MAP, LEO_OFF_LC_SS0_KRN, PAGE_SIZE },
- { LEO_LC_SS1_KRN_MAP, LEO_OFF_LC_SS1_KRN, PAGE_SIZE },
- { LEO_LD_GBL_MAP, LEO_OFF_LD_GBL, PAGE_SIZE },
+ { LEO_LC_SS1_USR_MAP, LEO_OFF_LC_SS1_USR, 0x1000 },
+ { LEO_LD_SS1_MAP, LEO_OFF_LD_SS1, 0x1000 },
+ { LEO_UNK_MAP, LEO_OFF_UNK, 0x1000 },
+ { LEO_LX_KRN_MAP, LEO_OFF_LX_KRN, 0x1000 },
+ { LEO_LC_SS0_KRN_MAP, LEO_OFF_LC_SS0_KRN, 0x1000 },
+ { LEO_LC_SS1_KRN_MAP, LEO_OFF_LC_SS1_KRN, 0x1000 },
+ { LEO_LD_GBL_MAP, LEO_OFF_LD_GBL, 0x1000 },
{ LEO_UNK2_MAP, LEO_OFF_UNK2, 0x100000 },
{ 0, 0, 0 }
};
@@ -152,19 +175,14 @@ static void leo_clear(struct vc_data *conp, struct display *p, int sy, int sx,
{
struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
- register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0;
+ register struct leo_ld *ss = fb->s.leo.ld_ss0;
int x, y, w, h;
int i;
do {
i = us->csr;
} while (i & 0x20000000);
- ss->unk = 0xffff;
- ss->unk2 = 0;
- ss->unk3 = fb->s.leo.extent;
- ss->fg = (attr_bgcol_ec(p,conp)<<24) | 0x030703;
- ss->planemask = 0xff000000;
- ss->rop = 0xd0840;
+ ss->fg = (attr_bgcol_ec(p,conp)<<24);
if (fontheightlog(p)) {
y = sy << fontheightlog(p); h = height << fontheightlog(p);
} else {
@@ -176,9 +194,8 @@ static void leo_clear(struct vc_data *conp, struct display *p, int sy, int sx,
x = sx * fontwidth(p); w = width * fontwidth(p);
}
us->extent = (w - 1) | ((h - 1) << 11);
- i = us->attrs;
us->fill = (x + fb->x_margin) | ((y + fb->y_margin) << 11) |
- ((i & 3) << 29) | ((i & 8) ? 0x80000000 : 0);
+ 0x80000000;
}
static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
@@ -186,23 +203,17 @@ static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
{
int i;
register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
- register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0;
+ register struct leo_ld *ss = fb->s.leo.ld_ss0;
- do {
- i = us->csr;
- } while (i & 0x20000000);
- ss->unk = 0xffff;
- ss->unk2 = 0;
- ss->unk3 = fb->s.leo.extent;
- ss->fg = (attr_bgcol(p,s)<<24) | 0x030703;
- ss->planemask = 0xff000000;
- ss->rop = 0xd0840;
+ ss->fg = (attr_bgcol(p,s)<<24);
while (count-- > 0) {
+ do {
+ i = us->csr;
+ } while (i & 0x20000000);
us->extent = (boxes[2] - boxes[0] - 1) |
((boxes[3] - boxes[1] - 1) << 11);
- i = us->attrs;
- us->fill = boxes[0] | (boxes[1] << 11) |
- ((i & 3) << 29) | ((i & 8) ? 0x80000000 : 0);
+ us->fill = boxes[0] | (boxes[1] << 11) | 0x80000000;
+ boxes += 4;
}
}
@@ -210,7 +221,7 @@ static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int
{
struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
- register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0;
+ register struct leo_ld *ss = fb->s.leo.ld_ss0;
int i, x, y;
u8 *fd;
u32 *u;
@@ -235,11 +246,7 @@ static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int
} while (i & 0x20000000);
ss->fg = attr_fgcol(p,c) << 24;
ss->bg = attr_bgcol(p,c) << 24;
- ss->rop = 0x310040;
- ss->planemask = 0xff000000;
- us->fontc2 = 0xFFFFFFFE;
- us->attrs = 4;
- us->fontc = 0xFFFFFFFF<<(32-fontwidth(p));
+ us->fontmsk = 0xFFFFFFFF<<(32-fontwidth(p));
u = ((u32 *)p->screen_base) + y + x;
if (fontwidth(p) <= 8) {
for (i = 0; i < fontheight(p); i++, u += 2048)
@@ -257,7 +264,7 @@ static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned sh
{
struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
- register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0;
+ register struct leo_ld *ss = fb->s.leo.ld_ss0;
int i, x, y;
u8 *fd1, *fd2, *fd3, *fd4;
u32 *u;
@@ -265,13 +272,9 @@ static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned sh
do {
i = us->csr;
} while (i & 0x20000000);
- ss->fg = attr_fgcol(p,*s) << 24;
- ss->bg = attr_bgcol(p,*s) << 24;
- ss->rop = 0x310040;
- ss->planemask = 0xff000000;
- us->fontc2 = 0xFFFFFFFE;
- us->attrs = 4;
- us->fontc = 0xFFFFFFFF<<(32-fontwidth(p));
+ ss->fg = attr_fgcol(p,scr_readw(s)) << 24;
+ ss->bg = attr_bgcol(p,scr_readw(s)) << 24;
+ us->fontmsk = 0xFFFFFFFF<<(32-fontwidth(p));
if (fontwidthlog(p))
x = (xx << fontwidthlog(p));
else
@@ -282,20 +285,20 @@ static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned sh
y = (yy * fontheight(p)) << 11;
u = ((u32 *)p->screen_base) + y + x;
if (fontwidth(p) <= 8) {
- us->fontc = 0xFFFFFFFF<<(32-4*fontwidth(p));
+ us->fontmsk = 0xFFFFFFFF<<(32-4*fontwidth(p));
x = 4*fontwidth(p) - fontheight(p)*2048;
while (count >= 4) {
count -= 4;
if (fontheightlog(p)) {
- fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
- fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
- fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
- fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+ fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+ fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+ fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
+ fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
} else {
- fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
- fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
- fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
- fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+ fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+ fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+ fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
+ fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
}
if (fontwidth(p) == 8) {
for (i = 0; i < fontheight(p); i++, u += 2048)
@@ -310,16 +313,16 @@ static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned sh
}
}
} else {
- us->fontc = 0xFFFFFFFF<<(32-2*fontwidth(p));
+ us->fontmsk = 0xFFFFFFFF<<(32-2*fontwidth(p));
x = 2*fontwidth(p) - fontheight(p)*2048;
while (count >= 2) {
count -= 2;
if (fontheightlog(p)) {
- fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
- fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
+ fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
+ fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
} else {
- fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
- fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
+ fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
+ fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
}
for (i = 0; i < fontheight(p); i++, u += 2048) {
*u = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
@@ -328,14 +331,14 @@ static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned sh
u += x;
}
}
- us->fontc = 0xFFFFFFFF<<(32-fontwidth(p));
+ us->fontmsk = 0xFFFFFFFF<<(32-fontwidth(p));
x = fontwidth(p) - fontheight(p)*2048;
while (count) {
count--;
if (fontheightlog(p))
- i = ((*s++ & p->charmask) << fontheightlog(p));
+ i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
else
- i = ((*s++ & p->charmask) * fontheight(p));
+ i = ((scr_readw(s++) & p->charmask) * fontheight(p));
if (fontwidth(p) <= 8) {
fd1 = p->fontdata + i;
for (i = 0; i < fontheight(p); i++, u += 2048)
@@ -457,8 +460,8 @@ static void leo_unblank (struct fb_info_sbusfb *fb)
fb->s.leo.lx_krn->krn_csr |= LEO_KRN_CSR_ENABLE;
}
-__initfunc(static int
-leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl))
+static int __init
+leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl)
{
struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
struct fb_wid_item *wi;
@@ -476,6 +479,8 @@ leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl))
lx_krn->krn_type = 0x5800 + j;
lx_krn->krn_value = wi->wi_values[0];
}
+ lx_krn->krn_type = LEO_KRN_TYPE_WID;
+ lx_krn->krn_csr = 3;
return 0;
}
@@ -484,9 +489,43 @@ static void leo_margins (struct fb_info_sbusfb *fb, struct display *p, int x_mar
p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
}
+static void leo_switch_from_graph (struct fb_info_sbusfb *fb)
+{
+ register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
+ register struct leo_ld *ss = fb->s.leo.ld_ss0;
+
+ ss->wid = 0xffffffff;
+ ss->wmask = 0xffff;
+ ss->vclipmin = 0;
+ ss->vclipmax = fb->s.leo.extent;
+ ss->planemask = 0xff000000;
+ ss->rop = 0x310850;
+ ss->widclip = 0;
+ us->addrspace = 4;
+ us->fontt = 0;
+}
+
+static void __init leo_rasterimg (struct fb_info_sbusfb *fb, int start)
+{
+ register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
+ register struct leo_ld *ss = fb->s.leo.ld_ss0;
+
+ if (start) {
+ ss->wid = 1;
+ ss->planemask = 0xffffff;
+ ss->rop = 0x310b90;
+ us->addrspace = 0;
+ } else {
+ ss->wid = 0xffffffff;
+ ss->planemask = 0xff000000;
+ ss->rop = 0x310850;
+ us->addrspace = 4;
+ }
+}
+
static char idstring[40] __initdata = { 0 };
-__initfunc(char *leofb_init(struct fb_info_sbusfb *fb))
+char * __init leofb_init(struct fb_info_sbusfb *fb)
{
struct fb_fix_screeninfo *fix = &fb->fix;
struct fb_var_screeninfo *var = &fb->var;
@@ -496,44 +535,53 @@ __initfunc(char *leofb_init(struct fb_info_sbusfb *fb))
struct fb_wid_item wi;
struct fb_wid_list wl;
int i;
+ register struct leo_lc_ss0_usr *us;
+ register struct leo_ld *ss;
+ struct fb_ops *fbops;
strcpy(fb->info.modename, "Leo");
strcpy(fix->id, "Leo");
- fix->visual = 0xff; /* We only know how to do acceleration and know nothing
- about the actual memory layout */
+ fix->visual = FB_VISUAL_TRUECOLOR;
fix->line_length = 8192;
fix->accel = FB_ACCEL_SUN_LEO;
+ var->bits_per_pixel = 32;
+ var->green.offset = 8;
+ var->blue.offset = 16;
var->accel_flags = FB_ACCELF_TEXT;
+ fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
+ if (!fbops) return NULL;
+
+ *fbops = *fb->info.fbops;
+ fbops->fb_rasterimg = leo_rasterimg;
+ fb->info.fbops = fbops;
+
disp->scrollmode = SCROLL_YREDRAW;
if (!disp->screen_base)
disp->screen_base = (char *)sparc_alloc_io(phys + LEO_OFF_SS0, 0,
0x800000, "leo_ram", fb->iospace, 0);
disp->screen_base += 8192 * fb->y_margin + 4 * fb->x_margin;
- fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *)
+ us = fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *)
sparc_alloc_io(phys + LEO_OFF_LC_SS0_USR, 0,
- PAGE_SIZE, "leo_lc_ss0_usr", fb->iospace, 0);
- fb->s.leo.ld_ss0 = (struct leo_ld_ss0 *)
+ 0x1000, "leo_lc_ss0_usr", fb->iospace, 0);
+ ss = fb->s.leo.ld_ss0 = (struct leo_ld *)
sparc_alloc_io(phys + LEO_OFF_LD_SS0, 0,
- PAGE_SIZE, "leo_ld_ss0", fb->iospace, 0);
+ 0x1000, "leo_ld_ss0", fb->iospace, 0);
fb->s.leo.ld_ss1 = (struct leo_ld_ss1 *)
sparc_alloc_io(phys + LEO_OFF_LD_SS1, 0,
- PAGE_SIZE, "leo_ld_ss1", fb->iospace, 0);
+ 0x1000, "leo_ld_ss1", fb->iospace, 0);
fb->s.leo.lx_krn = (struct leo_lx_krn *)
sparc_alloc_io(phys + LEO_OFF_LX_KRN, 0,
- PAGE_SIZE, "leo_lx_krn", fb->iospace, 0);
+ 0x1000, "leo_lx_krn", fb->iospace, 0);
fb->s.leo.cursor = (struct leo_cursor *)
sparc_alloc_io(phys + LEO_OFF_LX_CURSOR, 0,
sizeof(struct leo_cursor), "leo_lx_cursor", fb->iospace, 0);
fb->dispsw = leo_dispsw;
-
+
fb->s.leo.extent = (type->fb_width-1) | ((type->fb_height-1) << 16);
- fb->s.leo.ld_ss0->unk = 0xffff;
- fb->s.leo.ld_ss0->unk2 = 0;
- fb->s.leo.ld_ss0->unk3 = fb->s.leo.extent;
wl.wl_count = 1;
wl.wl_list = &wi;
wi.wi_type = FB_WID_DBL_8;
@@ -546,17 +594,27 @@ __initfunc(char *leofb_init(struct fb_info_sbusfb *fb))
wi.wi_index = 2;
wi.wi_values [0] = 0x20;
leo_wid_put (fb, &wl);
+ wi.wi_type = FB_WID_DBL_24;
+ wi.wi_index = 1;
+ wi.wi_values [0] = 0x30;
+ leo_wid_put (fb, &wl);
fb->s.leo.ld_ss1->ss1_misc |= LEO_SS1_MISC_ENABLE;
- fb->s.leo.ld_ss0->fg = 0x30703;
- fb->s.leo.ld_ss0->planemask = 0xff000000;
- fb->s.leo.ld_ss0->rop = 0xd0840;
- fb->s.leo.lc_ss0_usr->extent = (type->fb_width-1) | ((type->fb_height-1) << 11);
- i = fb->s.leo.lc_ss0_usr->attrs;
- fb->s.leo.lc_ss0_usr->fill = (0) | ((0) << 11) | ((i & 3) << 29) | ((i & 8) ? 0x80000000 : 0);
+ ss->wid = 0xffffffff;
+ ss->wmask = 0xffff;
+ ss->vclipmin = 0;
+ ss->vclipmax = fb->s.leo.extent;
+ ss->fg = 0;
+ ss->planemask = 0xff000000;
+ ss->rop = 0x310850;
+ ss->widclip = 0;
+ us->extent = (type->fb_width-1) | ((type->fb_height-1) << 11);
+ us->addrspace = 4;
+ us->fill = 0x80000000;
+ us->fontt = 0;
do {
- i = fb->s.leo.lc_ss0_usr->csr;
+ i = us->csr;
} while (i & 0x20000000);
fb->margins = leo_margins;
@@ -565,6 +623,7 @@ __initfunc(char *leofb_init(struct fb_info_sbusfb *fb))
fb->setcursormap = leo_setcursormap;
fb->setcurshape = leo_setcurshape;
fb->restore_palette = leo_restore_palette;
+ fb->switch_from_graph = leo_switch_from_graph;
fb->fill = leo_fill;
fb->blank = leo_blank;
fb->unblank = leo_unblank;
diff --git a/drivers/video/matroxfb.c b/drivers/video/matroxfb.c
index 5cfb98f52..eb6126965 100644
--- a/drivers/video/matroxfb.c
+++ b/drivers/video/matroxfb.c
@@ -4,7 +4,7 @@
*
* (c) 1998,1999 Petr Vandrovec <vandrove@vc.cvut.cz>
*
- * Version: 1.9 1999/01/04
+ * Version: 1.15 1999/04/19
*
* MTRR stuff: 1998 Tom Rini <tmrini@ntplx.net>
*
@@ -24,6 +24,9 @@
* "Daniel Haun" <haund@usa.net>
* Testing, hardware cursor fixes
*
+ * "Scott Wood" <sawst46+@pitt.edu>
+ * Fixes
+ *
* "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
* Betatesting
*
@@ -54,6 +57,9 @@
* "H. Peter Arvin" <hpa@transmeta.com>
* Ideas
*
+ * "Cort Dougan" <cort@cs.nmt.edu>
+ * CHRP fixes and PReP cleanup
+ *
* (following author is not in any relation with this code, but his code
* is included in this driver)
*
@@ -184,14 +190,8 @@
#if defined(__m68k__)
#define MAP_BUSTOVIRT
#else
-#if defined(CONFIG_PPC) && defined(CONFIG_PREP) && defined(_ISA_MEM_BASE)
-/* do not tell me that PPC is not broken... if ioremap() oops with
- invalid value written to msr... */
-#define MAP_ISAMEMBASE
-#else
#define MAP_IOREMAP
#endif
-#endif
#ifdef DEBUG
#define dprintk(X...) printk(X)
@@ -351,13 +351,9 @@ static inline int mga_ioremap(unsigned long phys, unsigned long size, int flags,
#ifdef MAP_BUSTOVIRT
virt->vaddr = bus_to_virt(phys);
#else
-#ifdef MAP_ISAMEMBASE
- virt->vaddr = (void*)(phys + _ISA_MEM_BASE);
-#else
#error "Your architecture does not have neither ioremap nor bus_to_virt... Giving up"
#endif
#endif
-#endif
return (virt->vaddr == 0); /* 0, !0... 0, error_code in future */
}
@@ -452,7 +448,7 @@ struct matrox_accel_data {
#define CPMINFO const struct matrox_fb_info* minfo,
#define PMINFO minfo,
-static inline struct matrox_fb_info* mxinfo(struct display* p) {
+static inline struct matrox_fb_info* mxinfo(const struct display* p) {
return (struct matrox_fb_info*)p->fb_info;
}
@@ -474,7 +470,7 @@ struct display global_disp;
#define PMINFO
#if 0
-static inline struct matrox_fb_info* mxinfo(struct display* p) {
+static inline struct matrox_fb_info* mxinfo(const struct display* p) {
return &global_mxinfo;
}
#endif
@@ -1473,7 +1469,7 @@ static void matrox_cfbX_fastputcs(u_int32_t fgx, u_int32_t bgx, struct display*
mga_outl(M_FCOL, fgx);
mga_outl(M_BCOL, bgx);
while (count--) {
- u_int32_t ar3 = ACCESS_FBINFO(fastfont.mgabase) + (*s++ & p->charmask)*charcell;
+ u_int32_t ar3 = ACCESS_FBINFO(fastfont.mgabase) + (scr_readw(s++) & p->charmask)*charcell;
mga_fifo(4);
mga_outl(M_FXBNDRY, ((xx + fontwidth(p) - 1) << 16) | xx);
@@ -1531,7 +1527,7 @@ static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, c
fxbndry = ((xx + fontwidth(p) - 1) << 16) | xx;
mmio = ACCESS_FBINFO(mmio.vbase);
while (count--) {
- u_int8_t* chardata = p->fontdata + (*s++ & p->charmask)*charcell;
+ u_int8_t* chardata = p->fontdata + (scr_readw(s++) & p->charmask)*charcell;
mga_fifo(5);
mga_writel(mmio, M_FXBNDRY, fxbndry);
@@ -1586,8 +1582,8 @@ static void matrox_cfb8_putcs(struct vc_data* conp, struct display* p, const uns
DBG_HEAVY("matroxfb_cfb8_putcs");
- fgx = attr_fgcol(p, *s);
- bgx = attr_bgcol(p, *s);
+ fgx = attr_fgcol(p, scr_readw(s));
+ bgx = attr_bgcol(p, scr_readw(s));
fgx |= (fgx << 8);
fgx |= (fgx << 16);
bgx |= (bgx << 8);
@@ -1603,8 +1599,8 @@ static void matrox_cfb16_putcs(struct vc_data* conp, struct display* p, const un
DBG_HEAVY("matroxfb_cfb16_putcs");
- fgx = ((u_int16_t*)p->dispsw_data)[attr_fgcol(p, *s)];
- bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol(p, *s)];
+ fgx = ((u_int16_t*)p->dispsw_data)[attr_fgcol(p, scr_readw(s))];
+ bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol(p, scr_readw(s))];
fgx |= (fgx << 16);
bgx |= (bgx << 16);
ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
@@ -1618,8 +1614,8 @@ static void matrox_cfb32_putcs(struct vc_data* conp, struct display* p, const un
DBG_HEAVY("matroxfb_cfb32_putcs");
- fgx = ((u_int32_t*)p->dispsw_data)[attr_fgcol(p, *s)];
- bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol(p, *s)];
+ fgx = ((u_int32_t*)p->dispsw_data)[attr_fgcol(p, scr_readw(s))];
+ bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol(p, scr_readw(s))];
ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
}
#endif
@@ -2191,9 +2187,9 @@ static void matrox_text_putcs(struct vc_data* conp, struct display* p, const uns
step = ACCESS_FBINFO(devflags.textstep);
offs = yy * p->next_line + xx * step;
- attr = attr_fgcol(p,*s) | (attr_bgcol(p,*s) << 4);
+ attr = attr_fgcol(p, scr_readw(s)) | (attr_bgcol(p, scr_readw(s)) << 4);
while (count-- > 0) {
- unsigned int chr = ((*s++) & p->charmask) << 8;
+ unsigned int chr = ((scr_readw(s++)) & p->charmask) << 8;
if (chr & 0x10000) chr ^= 0x10008;
mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(attr|chr));
offs += step;
@@ -2395,6 +2391,10 @@ static void initMatrox(WPMINFO struct display* p) {
DBG("initMatrox")
+ if (ACCESS_FBINFO(currcon_display) != p)
+ return;
+ if (p->dispsw && p->conp)
+ fb_con.con_cursor(p->conp, CM_ERASE);
p->dispsw_data = NULL;
if ((p->var.accel_flags & FB_ACCELF_TEXT) != FB_ACCELF_TEXT) {
if (p->type == FB_TYPE_TEXT) {
@@ -4274,6 +4274,17 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_
for (i = 0; i < 21; i++) {
outTi3026(PMINFO DACseq[i], hw->DACreg[i]);
}
+ if (oldhw) {
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0x00);
+ oldhw->DACclk[0] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
+ oldhw->DACclk[3] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0x15);
+ oldhw->DACclk[1] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
+ oldhw->DACclk[4] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
+ outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A);
+ oldhw->DACclk[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
+ oldhw->DACclk[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
+ }
if (!oldhw || memcmp(hw->DACclk, oldhw->DACclk, 6)) {
/* agrhh... setting up PLL is very slow on Millenium... */
/* Mystique PLL is locked in few ms, but Millenium PLL lock takes about 0.15 s... */
@@ -5296,7 +5307,7 @@ static struct board {
"MGA-G200 (AGP)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
0, 0,
- DEVF_VIDEO64BIT | DEVF_SWAPS,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
230000,
&vbG200,
"unknown G200 (AGP)"},
@@ -5743,20 +5754,26 @@ leave:;
}
#ifndef MODULE
+static int __init initialized = 0;
+
__initfunc(void matroxfb_init(void))
{
DBG("matroxfb_init")
-#if defined(CONFIG_FB_OF)
-/* Nothing to do, must be called from offb */
-#else
- matrox_init();
-#endif
+
+ if (!initialized) {
+ initialized = 1;
+ matrox_init();
+ }
}
#if defined(CONFIG_FB_OF)
__initfunc(int matrox_of_init(struct device_node *dp)) {
DBG("matrox_of_init");
- matrox_init();
+
+ if (!initialized) {
+ initialized = 1;
+ matrox_init();
+ }
if (!fb_list) return -ENXIO;
return 0;
}
diff --git a/drivers/video/mdacon.c b/drivers/video/mdacon.c
index 177493d68..90dc85685 100644
--- a/drivers/video/mdacon.c
+++ b/drivers/video/mdacon.c
@@ -429,7 +429,7 @@ static void mdacon_putcs(struct vc_data *c, const unsigned short *s,
u16 *dest = MDA_ADDR(x, y);
for (; count > 0; count--) {
- scr_writew(mda_convert_attr(*s++), dest++);
+ scr_writew(mda_convert_attr(scr_readw(s++)), dest++);
}
}
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index f74486863..a769e9454 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -476,6 +476,7 @@ __initfunc(static void offb_init_nodriver(struct device_node *dp))
printk("no framebuffer address found for %s\n", dp->full_name);
return;
}
+
address = (u_long)dp->addrs[i].address;
/* kludge for valkyrie */
@@ -484,6 +485,7 @@ __initfunc(static void offb_init_nodriver(struct device_node *dp))
}
offb_init_fb(dp->name, dp->full_name, width, height, depth,
pitch, address);
+
}
__initfunc(static void offb_init_fb(const char *name, const char *full_name,
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index c26958e7b..dfb0f8ae8 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -3,7 +3,9 @@
* Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
* Based on linux/drivers/video/skeletonfb.c by Geert Uytterhoeven.
* --------------------------------------------------------------------------
- * $Id: pm2fb.c,v 1.1.2.1 1999/01/12 19:53:02 geert Exp $
+ * $Id: pm2fb.c,v 1.163 1999/02/21 14:06:49 illo Exp $
+ * --------------------------------------------------------------------------
+ * TODO multiple boards support
* --------------------------------------------------------------------------
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file README.legal in the main directory of this archive
@@ -26,23 +28,27 @@
#include <linux/console.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.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 <asm/io.h>
-#include <asm/uaccess.h>
#include "pm2fb.h"
-#ifdef CONFIG_FB_PM2_CVPPC
#include "cvisionppc.h"
-#endif
#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
#error "The endianness of the target host has not been defined."
#endif
-#undef PM2FB_MASTER_DEBUG
+#if defined(CONFIG_FB_PM2_PCI) && !defined(CONFIG_PCI)
+#undef CONFIG_FB_PM2_PCI
+#warning "support for Permedia2 PCI boards with no generic PCI support!"
+#endif
+
+#define PM2FB_MASTER_DEBUG
#ifdef PM2FB_MASTER_DEBUG
#define DPRINTK(a,b...) printk("pm2fb: %s: " a, __FUNCTION__ , ## b)
#else
@@ -52,12 +58,20 @@
#define PICOS2KHZ(a) (1000000000UL/(a))
#define KHZ2PICOS(a) (1000000000UL/(a))
-#ifdef CONFIG_APUS
-#define MMAP(a,b) (unsigned char* )kernel_map((unsigned long )(a), \
- b, KERNELMAP_NOCACHE_SER, NULL)
-#else
-#define MMAP(a,b) ioremap(a, b)
-#endif
+/*
+ * The _DEFINITIVE_ memory mapping/unmapping functions.
+ * This is due to the fact that they're changing soooo often...
+ */
+#define MMAP(a,b) ioremap((unsigned long )(a), b)
+#define UNMAP(a,b) iounmap(a)
+
+/*
+ * The _DEFINITIVE_ memory i/o barrier functions.
+ * This is due to the fact that they're changing soooo often...
+ */
+#define DEFW() wmb()
+#define DEFR() rmb()
+#define DEFRW() mb()
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
@@ -67,35 +81,33 @@
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
-#ifndef __powerpc__
-#define eieio()
-#endif
-
struct pm2fb_par {
- unsigned long pixclock; /* pixclock in KHz */
- unsigned long width; /* width of virtual screen */
- unsigned long height; /* height of virtual screen */
- unsigned long hsstart; /* horiz. sync start */
- unsigned long hsend; /* horiz. sync end */
- unsigned long hbend; /* horiz. blank end (also gate end) */
- unsigned long htotal; /* total width (w/ sync & blank) */
- unsigned long vsstart; /* vert. sync start */
- unsigned long vsend; /* vert. sync end */
- unsigned long vbend; /* vert. blank end */
- unsigned long vtotal; /* total height (w/ sync & blank) */
- unsigned long stride; /* screen stride */
- unsigned long base; /* screen base (xoffset+yoffset) */
- unsigned long depth; /* screen depth (8, 16, 24 or 32) */
- unsigned long video; /* video control (hsync,vsync) */
+ u32 pixclock; /* pixclock in KHz */
+ u32 width; /* width of virtual screen */
+ u32 height; /* height of virtual screen */
+ u32 hsstart; /* horiz. sync start */
+ u32 hsend; /* horiz. sync end */
+ u32 hbend; /* horiz. blank end (also gate end) */
+ u32 htotal; /* total width (w/ sync & blank) */
+ u32 vsstart; /* vert. sync start */
+ u32 vsend; /* vert. sync end */
+ u32 vbend; /* vert. blank end */
+ u32 vtotal; /* total height (w/ sync & blank) */
+ u32 stride; /* screen stride */
+ u32 base; /* screen base (xoffset+yoffset) */
+ u32 depth; /* screen depth (8, 16, 24 or 32) */
+ u32 video; /* video control (hsync,vsync) */
};
-#define OPTF_OLD_MEM 0x00000001
-#define OPTF_YPAN 0x00000002
+#define OPTF_OLD_MEM (1L<<0)
+#define OPTF_YPAN (1L<<1)
+#define OPTF_VIRTUAL (1L<<2)
static struct {
char font[40];
- unsigned long flags;
+ u32 flags;
struct pm2fb_par user_mode;
-} pm2fb_options;
+} pm2fb_options =
+ {"\0", 0L, {25174,640,480,4,28,40,199,9,11,45,524,80,0,8,121}};
static const struct {
char name[16];
@@ -164,6 +176,15 @@ static const struct {
{"\0", },
};
+#ifdef CONFIG_FB_PM2_PCI
+struct pm2pci_par {
+ u32 mem_config;
+ u32 mem_control;
+ u32 boot_address;
+ struct pci_dev* dev;
+};
+#endif
+
static const char permedia2_name[16]="Permedia2";
static struct pm2fb_info {
@@ -172,7 +193,7 @@ static struct pm2fb_info {
board_table[] below) */
struct {
unsigned char* fb_base; /* framebuffer memory base */
- unsigned long fb_size; /* framebuffer memory size */
+ u32 fb_size; /* framebuffer memory size */
unsigned char* rg_base; /* register memory base */
unsigned char* p_fb; /* physical address of frame buffer */
unsigned char* v_fb; /* virtual address of frame buffer */
@@ -186,10 +207,13 @@ static struct pm2fb_info {
#ifdef CONFIG_FB_PM2_CVPPC
struct cvppc_par cvppc; /* CVisionPPC data */
#endif
+#ifdef CONFIG_FB_PM2_PCI
+ struct pm2pci_par pci; /* Permedia2 PCI boards data */
+#endif
} board_par;
struct pm2fb_par current_par; /* displayed screen */
int current_par_valid;
- unsigned long memclock; /* memclock (set by the per-board
+ u32 memclock; /* memclock (set by the per-board
init routine) */
struct display disp;
struct {
@@ -216,6 +240,11 @@ static int cvppc_detect(struct pm2fb_info*);
static void cvppc_init(struct pm2fb_info*);
#endif
+#ifdef CONFIG_FB_PM2_PCI
+static int pm2pci_detect(struct pm2fb_info*);
+static void pm2pci_init(struct pm2fb_info*);
+#endif
+
/*
* Table of the supported Permedia2 based boards.
* Three hooks are defined for each board:
@@ -236,6 +265,9 @@ static const struct {
void (*cleanup)(struct pm2fb_info*);
char name[32];
} board_table[] = {
+#ifdef CONFIG_FB_PM2_PCI
+ { pm2pci_detect, pm2pci_init, NULL, "Permedia2 PCI board" },
+#endif
#ifdef CONFIG_FB_PM2_CVPPC
{ cvppc_detect, cvppc_init, NULL, "CVisionPPC/BVisionPPC" },
#endif
@@ -247,8 +279,8 @@ static const struct {
*/
#define PACKPP(p0,p1,p2) (((p2)<<6)|((p1)<<3)|(p0))
static const struct {
- unsigned short width;
- unsigned short pp;
+ u16 width;
+ u16 pp;
} pp_table[] = {
{ 32, PACKPP(1, 0, 0) }, { 64, PACKPP(1, 1, 0) },
{ 96, PACKPP(1, 1, 1) }, { 128, PACKPP(2, 1, 1) },
@@ -286,14 +318,14 @@ static int pm2fb_setcolreg(unsigned regno,
static int pm2fb_blank(int blank_mode, struct fb_info_gen* info);
static int pm2fb_pan_display(const struct fb_var_screeninfo* var,
struct fb_info_gen* info);
-static void pm2fb_dispsw(const void* par, struct display* disp,
+static void pm2fb_set_disp(const void* par, struct display* disp,
struct fb_info_gen* info);
static struct fbgen_hwswitch pm2fb_hwswitch={
pm2fb_detect, pm2fb_encode_fix, pm2fb_decode_var,
pm2fb_encode_var, pm2fb_get_par, pm2fb_set_par,
pm2fb_getcolreg, pm2fb_setcolreg, pm2fb_pan_display,
- pm2fb_blank, pm2fb_dispsw
+ pm2fb_blank, pm2fb_set_disp
};
static int pm2fb_open(struct fb_info* info, int user);
@@ -309,61 +341,61 @@ static struct fb_ops pm2fb_ops={
* Begin of Permedia2 specific functions
***************************************************************************/
-inline static unsigned long RD32(unsigned char* base, long off) {
+inline static u32 RD32(unsigned char* base, s32 off) {
- return *((volatile unsigned long* )(base+off));
+ return readl(base+off);
}
-inline static void WR32(unsigned char* base, long off, unsigned long v) {
+inline static void WR32(unsigned char* base, s32 off, u32 v) {
- *((volatile unsigned long* )(base+off))=v;
+ writel(v, base+off);
}
-inline static unsigned long pm2_RD(struct pm2fb_info* p, long off) {
+inline static u32 pm2_RD(struct pm2fb_info* p, s32 off) {
return RD32(p->regions.v_regs, off);
}
-inline static void pm2_WR(struct pm2fb_info* p, long off, unsigned long v) {
+inline static void pm2_WR(struct pm2fb_info* p, s32 off, u32 v) {
WR32(p->regions.v_regs, off, v);
}
-inline static unsigned long pm2_RDAC_RD(struct pm2fb_info* p, long idx) {
+inline static u32 pm2_RDAC_RD(struct pm2fb_info* p, s32 idx) {
pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
- eieio();
+ DEFRW();
return pm2_RD(p, PM2R_RD_INDEXED_DATA);
}
-inline static void pm2_RDAC_WR(struct pm2fb_info* p, long idx,
- unsigned long v) {
+inline static void pm2_RDAC_WR(struct pm2fb_info* p, s32 idx,
+ u32 v) {
pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
- eieio();
+ DEFW();
pm2_WR(p, PM2R_RD_INDEXED_DATA, v);
}
#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
#define WAIT_FIFO(p,a)
#else
-inline static void WAIT_FIFO(struct pm2fb_info* p, unsigned long a) {
+inline static void WAIT_FIFO(struct pm2fb_info* p, u32 a) {
while(pm2_RD(p, PM2R_IN_FIFO_SPACE)<a);
- eieio();
+ DEFRW();
}
#endif
-static unsigned long partprod(unsigned long xres) {
+static u32 partprod(u32 xres) {
int i;
for (i=0; pp_table[i].width && pp_table[i].width!=xres; i++);
if (!pp_table[i].width)
- DPRINTK("invalid width %lu\n", xres);
+ DPRINTK("invalid width %u\n", xres);
return pp_table[i].pp;
}
-static unsigned long to3264(unsigned long timing, int bpp, int is64) {
+static u32 to3264(u32 timing, int bpp, int is64) {
switch (bpp) {
case 8:
@@ -383,7 +415,7 @@ static unsigned long to3264(unsigned long timing, int bpp, int is64) {
return timing;
}
-static unsigned long from3264(unsigned long timing, int bpp, int is64) {
+static u32 from3264(u32 timing, int bpp, int is64) {
switch (bpp) {
case 8:
@@ -403,14 +435,14 @@ static unsigned long from3264(unsigned long timing, int bpp, int is64) {
return timing;
}
-static void mnp(unsigned long clk, unsigned char* mm, unsigned char* nn,
+static void mnp(u32 clk, unsigned char* mm, unsigned char* nn,
unsigned char* pp) {
unsigned char m;
unsigned char n;
unsigned char p;
- unsigned long f;
- long current;
- long delta=100000;
+ u32 f;
+ s32 curr;
+ s32 delta=100000;
*mm=*nn=*pp=0;
for (n=2; n<15; n++) {
@@ -418,9 +450,9 @@ static void mnp(unsigned long clk, unsigned char* mm, unsigned char* nn,
f=PM2_REFERENCE_CLOCK*m/n;
if (f>=150000 && f<=300000) {
for (p=0; p<5; p++, f>>=1) {
- current=clk>f?clk-f:f-clk;
- if (current<delta) {
- delta=current;
+ curr=clk>f?clk-f:f-clk;
+ if (curr<delta) {
+ delta=curr;
*mm=m;
*nn=n;
*pp=p;
@@ -435,62 +467,75 @@ static void wait_pm2(struct pm2fb_info* i) {
WAIT_FIFO(i, 1);
pm2_WR(i, PM2R_SYNC, 0);
- eieio();
+ DEFRW();
do {
while (pm2_RD(i, PM2R_OUT_FIFO_WORDS)==0);
- eieio();
+ DEFR();
} while (pm2_RD(i, PM2R_OUT_FIFO)!=PM2TAG(PM2R_SYNC));
}
-static void set_memclock(struct pm2fb_info* info, unsigned long clk) {
+static void set_memclock(struct pm2fb_info* info, u32 clk) {
int i;
unsigned char m, n, p;
mnp(clk, &m, &n, &p);
WAIT_FIFO(info, 5);
pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_3, 6);
- eieio();
+ DEFW();
pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_1, m);
pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_2, n);
- eieio();
+ DEFW();
pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_3, 8|p);
- eieio();
+ DEFW();
pm2_RDAC_RD(info, PM2I_RD_MEMORY_CLOCK_STATUS);
- eieio();
+ DEFR();
for (i=256; i &&
!(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--);
}
-static void set_pixclock(struct pm2fb_info* info, unsigned long clk) {
+static void set_pixclock(struct pm2fb_info* info, u32 clk) {
int i;
unsigned char m, n, p;
mnp(clk, &m, &n, &p);
WAIT_FIFO(info, 5);
pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 0);
- eieio();
+ DEFW();
pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A1, m);
pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A2, n);
- eieio();
+ DEFW();
pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 8|p);
- eieio();
+ DEFW();
pm2_RDAC_RD(info, PM2I_RD_PIXEL_CLOCK_STATUS);
- eieio();
+ DEFR();
for (i=256; i &&
!(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--);
}
+static void clear_palette(struct pm2fb_info* p) {
+ int i=256;
+
+ WAIT_FIFO(p, 1);
+ pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, 0);
+ DEFW();
+ while (i--) {
+ WAIT_FIFO(p, 3);
+ pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
+ pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
+ pm2_WR(p, PM2R_RD_PALETTE_DATA, 0);
+ }
+}
+
static void set_color(struct pm2fb_info* p, unsigned char regno,
unsigned char r, unsigned char g, unsigned char b) {
WAIT_FIFO(p, 4);
- eieio();
pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, regno);
- eieio();
+ DEFW();
pm2_WR(p, PM2R_RD_PALETTE_DATA, r);
- eieio();
+ DEFW();
pm2_WR(p, PM2R_RD_PALETTE_DATA, g);
- eieio();
+ DEFW();
pm2_WR(p, PM2R_RD_PALETTE_DATA, b);
}
@@ -520,12 +565,13 @@ static void set_aperture(struct pm2fb_info* i, struct pm2fb_par* p) {
}
static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) {
- unsigned long clrmode=0;
- unsigned long txtmap=0;
- unsigned long xres;
+ u32 clrmode=0;
+ u32 txtmap=0;
+ u32 xres;
xres=(p->width+31)&~31;
set_aperture(i, p);
+ DEFRW();
WAIT_FIFO(i, 22);
pm2_RDAC_WR(i, PM2I_RD_COLOR_KEY_CONTROL, p->depth==8?0:
PM2F_COLOR_KEY_TEST_OFF);
@@ -565,7 +611,7 @@ static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) {
pm2_WR(i, PM2R_VS_END, p->vsend);
pm2_WR(i, PM2R_VB_END, p->vbend);
pm2_WR(i, PM2R_SCREEN_STRIDE, p->stride);
- eieio();
+ DEFW();
pm2_WR(i, PM2R_SCREEN_BASE, p->base);
pm2_RDAC_WR(i, PM2I_RD_COLOR_MODE, PM2F_RD_COLOR_MODE_RGB|
PM2F_RD_GUI_ACTIVE|clrmode);
@@ -573,6 +619,63 @@ static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) {
set_pixclock(i, p->pixclock);
};
+/*
+ * copy with packed pixels (8/16bpp only).
+ */
+static void pm2fb_pp_copy(struct pm2fb_info* i, s32 xsrc, s32 ysrc,
+ s32 x, s32 y, s32 w, s32 h) {
+ s32 scale=i->current_par.depth==8?2:1;
+ s32 offset;
+
+ if (!w || !h)
+ return;
+ WAIT_FIFO(i, 7);
+ pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE|
+ PM2F_CONFIG_FB_PACKED_DATA|
+ PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
+ pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0);
+ pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16|
+ ((xsrc-x)&0xfff));
+ offset=(x&0x3)-(xsrc&0x3);
+ pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|(x>>scale));
+ pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|((w+7)>>scale));
+ pm2_WR(i, PM2R_PACKED_DATA_LIMITS, (offset<<29)|(x<<16)|(x+w));
+ DEFW();
+ pm2_WR(i, PM2R_RENDER, PM2F_RENDER_RECTANGLE|
+ (x<xsrc?PM2F_INCREASE_X:0)|
+ (y<ysrc?PM2F_INCREASE_Y:0));
+ wait_pm2(i);
+}
+
+/*
+ * block operation. copy=0: rectangle fill, copy=1: rectangle copy.
+ */
+static void pm2fb_block_op(struct pm2fb_info* i, int copy,
+ s32 xsrc, s32 ysrc,
+ s32 x, s32 y, s32 w, s32 h,
+ u32 color) {
+
+ if (!w || !h)
+ return;
+ WAIT_FIFO(i, 6);
+ pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE|
+ PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
+ pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0);
+ if (copy)
+ pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16|
+ ((xsrc-x)&0xfff));
+ else
+ pm2_WR(i, PM2R_FB_BLOCK_COLOR, color);
+ pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|x);
+ pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|w);
+ DEFW();
+ pm2_WR(i, PM2R_RENDER, PM2F_RENDER_RECTANGLE|
+ (x<xsrc?PM2F_INCREASE_X:0)|
+ (y<ysrc?PM2F_INCREASE_Y:0)|
+ (copy?0:PM2F_RENDER_FASTFILL));
+ wait_pm2(i);
+}
+
/***************************************************************************
* Begin of generic initialization functions
***************************************************************************/
@@ -580,14 +683,14 @@ static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) {
static void pm2fb_reset(struct pm2fb_info* p) {
pm2_WR(p, PM2R_RESET_STATUS, 0);
- eieio();
+ DEFRW();
while (pm2_RD(p, PM2R_RESET_STATUS)&PM2F_BEING_RESET);
- eieio();
+ DEFRW();
#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
DPRINTK("FIFO disconnect enabled\n");
pm2_WR(p, PM2R_FIFO_DISCON, 1);
+ DEFRW();
#endif
- eieio();
if (board_table[p->board].init)
board_table[p->board].init(p);
WAIT_FIFO(p, 48);
@@ -633,8 +736,9 @@ static void pm2fb_reset(struct pm2fb_info* p) {
pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0);
pm2_RDAC_WR(p, PM2I_RD_GREEN_KEY, 0);
pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0);
- eieio();
- set_memclock(p, p->memclock);
+ clear_palette(p);
+ if (p->memclock)
+ set_memclock(p, p->memclock);
}
__initfunc(static int pm2fb_conf(struct pm2fb_info* p)) {
@@ -661,9 +765,12 @@ __initfunc(static int pm2fb_conf(struct pm2fb_info* p)) {
* Begin of per-board initialization functions
***************************************************************************/
+/*
+ * Phase5 CvisionPPC/BVisionPPC
+ */
#ifdef CONFIG_FB_PM2_CVPPC
static int cvppc_PCI_init(struct cvppc_par* p) {
- extern unsigned long powerup_PCI_present;
+ extern u32 powerup_PCI_present;
if (!powerup_PCI_present) {
DPRINTK("no PCI bridge detected\n");
@@ -683,14 +790,14 @@ static int cvppc_PCI_init(struct cvppc_par* p) {
return 0;
}
WR32(p->pci_bridge, CSPPC_BRIDGE_ENDIAN, CSPPCF_BRIDGE_BIG_ENDIAN);
- eieio();
+ DEFW();
if (pm2fb_options.flags & OPTF_OLD_MEM)
WR32(p->pci_config, PCI_CACHE_LINE_SIZE, 0xff00);
WR32(p->pci_config, PCI_BASE_ADDRESS_0, CVPPC_REGS_REGION);
WR32(p->pci_config, PCI_BASE_ADDRESS_1, CVPPC_FB_APERTURE_ONE);
WR32(p->pci_config, PCI_BASE_ADDRESS_2, CVPPC_FB_APERTURE_TWO);
WR32(p->pci_config, PCI_ROM_ADDRESS, CVPPC_ROM_ADDRESS);
- eieio();
+ DEFW();
WR32(p->pci_config, PCI_COMMAND, 0xef000000 |
PCI_COMMAND_IO |
PCI_COMMAND_MEMORY |
@@ -714,7 +821,7 @@ static void cvppc_init(struct pm2fb_info* p) {
WAIT_FIFO(p, 3);
pm2_WR(p, PM2R_MEM_CONTROL, 0);
pm2_WR(p, PM2R_BOOT_ADDRESS, 0x30);
- eieio();
+ DEFW();
if (pm2fb_options.flags & OPTF_OLD_MEM)
pm2_WR(p, PM2R_MEM_CONFIG, CVPPC_MEM_CONFIG_OLD);
else
@@ -722,70 +829,100 @@ static void cvppc_init(struct pm2fb_info* p) {
}
#endif /* CONFIG_FB_PM2_CVPPC */
-/***************************************************************************
- * Console hw acceleration
- ***************************************************************************/
-
/*
- * copy with packed pixels (8/16bpp only).
+ * Generic PCI detection routines
*/
-static void pm2fb_pp_copy(struct pm2fb_info* i, long xsrc, long ysrc,
- long x, long y, long w, long h) {
- long scale=i->current_par.depth==8?2:1;
- long offset;
-
- if (!w || !h)
- return;
- WAIT_FIFO(i, 7);
- pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE|
- PM2F_CONFIG_FB_PACKED_DATA|
- PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
- pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0);
- pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16|
- ((xsrc-x)&0xfff));
- offset=(x&0x3)-(xsrc&0x3);
- pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|(x>>scale));
- pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|((w+7)>>scale));
- pm2_WR(i, PM2R_PACKED_DATA_LIMITS, (offset<<29)|(x<<16)|(x+w));
- eieio();
- pm2_WR(i, PM2R_RENDER, PM2F_RENDER_RECTANGLE|
- (x<xsrc?PM2F_INCREASE_X:0)|
- (y<ysrc?PM2F_INCREASE_Y:0));
- wait_pm2(i);
+#ifdef CONFIG_FB_PM2_PCI
+static int pm2pci_detect(struct pm2fb_info* p) {
+ struct pm2pci_par* pci=&p->board_par.pci;
+ unsigned char* m;
+
+ memset(pci, 0, sizeof(struct pm2pci_par));
+ if (!pci_present()) {
+ DPRINTK("no PCI bus found.\n");
+ return 0;
+ }
+ DPRINTK("scanning PCI bus for known chipsets...\n");
+ if ((pci->dev=pci_find_device(PCI_VENDOR_ID_TI,
+ PCI_DEVICE_ID_TI_TVP4020, NULL))) {
+ DPRINTK("... found Texas Instruments TVP4020\n");
+ }
+ if (!pci->dev) {
+ DPRINTK("no PCI board found.\n");
+ return 0;
+ }
+ DPRINTK("PCI board @%08lx %08lx %08lx rom %08lx\n",
+ pci->dev->base_address[0],
+ pci->dev->base_address[1],
+ pci->dev->base_address[2],
+ pci->dev->rom_address);
+#ifdef __sparc__
+ p->regions.rg_base=(unsigned char* )
+ __pa(pci->dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK);
+ p->regions.fb_base=(unsigned char* )
+ __pa(pci->dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK);
+#else
+ if (pm2fb_options.flags & OPTF_VIRTUAL) {
+ p->regions.rg_base=(unsigned char* )
+ __pa(pci->dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK);
+ p->regions.fb_base=(unsigned char* )
+ __pa(pci->dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK);
+ }
+ else {
+ p->regions.rg_base=(unsigned char* )
+ (pci->dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK);
+ p->regions.fb_base=(unsigned char* )
+ (pci->dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK);
+ }
+#endif
+#ifdef __BIG_ENDIAN
+ p->regions.rg_base += PM2_REGS_SIZE;
+#endif
+ if ((m=MMAP(p->regions.rg_base, PM2_REGS_SIZE))) {
+ pci->mem_control=RD32(m, PM2R_MEM_CONTROL);
+ pci->boot_address=RD32(m, PM2R_BOOT_ADDRESS);
+ pci->mem_config=RD32(m, PM2R_MEM_CONFIG);
+ switch (pci->mem_config & PM2F_MEM_CONFIG_RAM_MASK) {
+ case PM2F_MEM_BANKS_1:
+ p->regions.fb_size=0x200000;
+ break;
+ case PM2F_MEM_BANKS_2:
+ p->regions.fb_size=0x400000;
+ break;
+ case PM2F_MEM_BANKS_3:
+ p->regions.fb_size=0x600000;
+ break;
+ case PM2F_MEM_BANKS_4:
+ p->regions.fb_size=0x800000;
+ break;
+ }
+ p->memclock=CVPPC_MEMCLOCK;
+ UNMAP(m, PM2_REGS_SIZE);
+ return 1;
+ }
+ DPRINTK("MMAP() failed.\n");
+ return 0;
}
-/*
- * block operation. copy=0: rectangle fill, copy=1: rectangle copy.
- */
-static void pm2fb_block_op(struct pm2fb_info* i, int copy,
- long xsrc, long ysrc,
- long x, long y, long w, long h,
- unsigned long color) {
+static void pm2pci_init(struct pm2fb_info* p) {
+ struct pm2pci_par* pci=&p->board_par.pci;
- if (!w || !h)
- return;
- WAIT_FIFO(i, 6);
- pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE|
- PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
- pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0);
- if (copy)
- pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16|
- ((xsrc-x)&0xfff));
- else
- pm2_WR(i, PM2R_FB_BLOCK_COLOR, color);
- pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|x);
- pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|w);
- eieio();
- pm2_WR(i, PM2R_RENDER, PM2F_RENDER_RECTANGLE|
- (x<xsrc?PM2F_INCREASE_X:0)|
- (y<ysrc?PM2F_INCREASE_Y:0)|
- (copy?0:PM2F_RENDER_FASTFILL));
- wait_pm2(i);
+ WAIT_FIFO(p, 3);
+ pm2_WR(p, PM2R_MEM_CONTROL, pci->mem_control);
+ pm2_WR(p, PM2R_BOOT_ADDRESS, pci->boot_address);
+ DEFW();
+ pm2_WR(p, PM2R_MEM_CONFIG, pci->mem_config);
}
+#endif /* CONFIG_FB_PM2_PCI */
+
+/***************************************************************************
+ * Console hw acceleration
+ ***************************************************************************/
+
static int pm2fb_blank(int blank_mode, struct fb_info_gen* info) {
struct pm2fb_info* i=(struct pm2fb_info* )info;
- unsigned long video;
+ u32 video;
if (!i->current_par_valid)
return 1;
@@ -871,7 +1008,7 @@ static void pm2fb_bmove(struct display* p, int sy, int sx,
#ifdef FBCON_HAS_CFB8
static void pm2fb_clear8(struct vc_data* conp, struct display* p,
int sy, int sx, int height, int width) {
- unsigned long c;
+ u32 c;
sx=sx*fontwidth(p);
width=width*fontwidth(p);
@@ -886,9 +1023,9 @@ static void pm2fb_clear8(struct vc_data* conp, struct display* p,
static void pm2fb_clear_margins8(struct vc_data* conp, struct display* p,
int bottom_only) {
- unsigned long c;
- unsigned long sx;
- unsigned long sy;
+ u32 c;
+ u32 sx;
+ u32 sy;
c=attr_bgcol_ec(p, conp);
c|=c<<8;
@@ -913,7 +1050,7 @@ static struct display_switch pm2_cfb8 = {
#ifdef FBCON_HAS_CFB16
static void pm2fb_clear16(struct vc_data* conp, struct display* p,
int sy, int sx, int height, int width) {
- unsigned long c;
+ u32 c;
sx=sx*fontwidth(p);
width=width*fontwidth(p);
@@ -927,9 +1064,9 @@ static void pm2fb_clear16(struct vc_data* conp, struct display* p,
static void pm2fb_clear_margins16(struct vc_data* conp, struct display* p,
int bottom_only) {
- unsigned long c;
- unsigned long sx;
- unsigned long sy;
+ u32 c;
+ u32 sx;
+ u32 sy;
c = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
c|=c<<16;
@@ -957,7 +1094,7 @@ static struct display_switch pm2_cfb16 = {
static void pm2fb_clear24(struct vc_data* conp, struct display* p,
int sy, int sx, int height, int width) {
struct pm2fb_info* i=(struct pm2fb_info* )p->fb_info;
- unsigned long c;
+ u32 c;
c=attr_bgcol_ec(p, conp);
if ( i->palette[c].red==i->palette[c].green &&
@@ -978,9 +1115,9 @@ static void pm2fb_clear24(struct vc_data* conp, struct display* p,
static void pm2fb_clear_margins24(struct vc_data* conp, struct display* p,
int bottom_only) {
struct pm2fb_info* i=(struct pm2fb_info* )p->fb_info;
- unsigned long c;
- unsigned long sx;
- unsigned long sy;
+ u32 c;
+ u32 sx;
+ u32 sy;
c=attr_bgcol_ec(p, conp);
if ( i->palette[c].red==i->palette[c].green &&
@@ -1011,7 +1148,7 @@ static struct display_switch pm2_cfb24 = {
#ifdef FBCON_HAS_CFB32
static void pm2fb_clear32(struct vc_data* conp, struct display* p,
int sy, int sx, int height, int width) {
- unsigned long c;
+ u32 c;
sx=sx*fontwidth(p);
width=width*fontwidth(p);
@@ -1024,9 +1161,9 @@ static void pm2fb_clear32(struct vc_data* conp, struct display* p,
static void pm2fb_clear_margins32(struct vc_data* conp, struct display* p,
int bottom_only) {
- unsigned long c;
- unsigned long sx;
- unsigned long sy;
+ u32 c;
+ u32 sx;
+ u32 sy;
c = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
sx=conp->vc_cols*fontwidth(p);
@@ -1065,18 +1202,55 @@ static int pm2fb_encode_fix(struct fb_fix_screeninfo* fix,
fix->accel=FB_ACCEL_3DLABS_PERMEDIA2;
fix->type=FB_TYPE_PACKED_PIXELS;
fix->visual=p->depth==8?FB_VISUAL_PSEUDOCOLOR:FB_VISUAL_TRUECOLOR;
- fix->line_length=0;
+ if (i->current_par_valid)
+ fix->line_length=i->current_par.width*(i->current_par.depth/8);
+ else
+ fix->line_length=0;
fix->xpanstep=p->depth==24?8:64/p->depth;
fix->ypanstep=1;
fix->ywrapstep=0;
return 0;
}
+#ifdef PM2FB_MASTER_DEBUG
+static void pm2fb_display_var(const struct fb_var_screeninfo* var) {
+
+ printk( KERN_DEBUG
+"- struct fb_var_screeninfo ---------------------------------------------------\n");
+ printk( KERN_DEBUG
+ "resolution: %ux%ux%u (virtual %ux%u+%u+%u)\n",
+ var->xres, var->yres, var->bits_per_pixel,
+ var->xres_virtual, var->yres_virtual,
+ var->xoffset, var->yoffset);
+ printk( KERN_DEBUG
+ "color: %c%c "
+ "R(%u,%u,%u), G(%u,%u,%u), B(%u,%u,%u), T(%u,%u,%u)\n",
+ var->grayscale?'G':'C', var->nonstd?'N':'S',
+ var->red.offset, var->red.length, var->red.msb_right,
+ var->green.offset, var->green.length, var->green.msb_right,
+ var->blue.offset, var->blue.length, var->blue.msb_right,
+ var->transp.offset, var->transp.length,
+ var->transp.msb_right);
+ printk( KERN_DEBUG
+ "timings: %ups (%u,%u)-(%u,%u)+%u+%u\n",
+ var->pixclock,
+ var->left_margin, var->upper_margin, var->right_margin,
+ var->lower_margin, var->hsync_len, var->vsync_len);
+ printk( KERN_DEBUG
+ "activate %08x accel_flags %08x sync %08x vmode %08x\n",
+ var->activate, var->accel_flags, var->sync, var->vmode);
+ printk( KERN_DEBUG
+"------------------------------------------------------------------------------\n");
+}
+
+#define pm2fb_decode_var pm2fb_wrapped_decode_var
+#endif
+
static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
void* par, struct fb_info_gen* info) {
struct pm2fb_info* i=(struct pm2fb_info* )info;
struct pm2fb_par p;
- unsigned long xres;
+ u32 xres;
int data64;
memset(&p, 0, sizeof(struct pm2fb_par));
@@ -1086,39 +1260,39 @@ static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
p.depth=p.depth>32?32:p.depth;
data64=p.depth>8;
xres=(var->xres+31)&~31;
- if (p.width==~(0L))
- p.width=xres;
- if (p.height==~(0L))
- p.height=var->yres;
if (p.width<xres+var->xoffset)
p.width=xres+var->xoffset;
if (p.height<var->yres+var->yoffset)
p.height=var->yres+var->yoffset;
if (!partprod(xres)) {
- DPRINTK("width not supported: %lu\n", xres);
+ DPRINTK("width not supported: %u\n", xres);
return -EINVAL;
}
if (p.width>2047) {
- DPRINTK("virtual width not supported: %lu\n", p.width);
+ DPRINTK("virtual width not supported: %u\n", p.width);
return -EINVAL;
}
if (var->yres<200) {
- DPRINTK("height not supported: %lu\n",
- (unsigned long )var->yres);
+ DPRINTK("height not supported: %u\n",
+ (u32 )var->yres);
return -EINVAL;
}
if (p.height<200 || p.height>2047) {
- DPRINTK("virtual height not supported: %lu\n", p.height);
+ DPRINTK("virtual height not supported: %u\n", p.height);
+ return -EINVAL;
+ }
+ if (p.depth>32) {
+ DPRINTK("depth not supported: %u\n", p.depth);
return -EINVAL;
}
if (p.width*p.height*p.depth/8>i->regions.fb_size) {
- DPRINTK("no memory for screen (%lux%lux%lu)\n",
- xres, p.height, p.depth);
+ DPRINTK("no memory for screen (%ux%ux%u)\n",
+ p.width, p.height, p.depth);
return -EINVAL;
}
p.pixclock=PICOS2KHZ(var->pixclock);
if (p.pixclock>PM2_MAX_PIXCLOCK) {
- DPRINTK("pixclock too high (%luKHz)\n", p.pixclock);
+ DPRINTK("pixclock too high (%uKHz)\n", p.pixclock);
return -EINVAL;
}
p.hsstart=to3264(var->right_margin, p.depth, data64);
@@ -1153,11 +1327,24 @@ static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
return 0;
}
+#ifdef PM2FB_MASTER_DEBUG
+#undef pm2fb_decode_var
+
+static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
+ void* par, struct fb_info_gen* info) {
+ int result;
+
+ result=pm2fb_wrapped_decode_var(var, par, info);
+ pm2fb_display_var(var);
+ return result;
+}
+#endif
+
static int pm2fb_encode_var(struct fb_var_screeninfo* var,
const void* par, struct fb_info_gen* info) {
struct pm2fb_par* p=(struct pm2fb_par* )par;
struct fb_var_screeninfo v;
- unsigned long base;
+ u32 base;
memset(&v, 0, sizeof(struct fb_var_screeninfo));
v.xres_virtual=p->width;
@@ -1266,9 +1453,9 @@ static void pm2fb_set_par(const void* par, struct fb_info_gen* info) {
return;
}
}
+ set_screen(i, p);
i->current_par=*p;
i->current_par_valid=1;
- set_screen(i, &i->current_par);
}
static int pm2fb_getcolreg(unsigned regno,
@@ -1322,7 +1509,7 @@ static int pm2fb_setcolreg(unsigned regno,
break;
#endif
default:
- DPRINTK("bad depth %lu\n",
+ DPRINTK("bad depth %u\n",
i->current_par.depth);
break;
}
@@ -1338,14 +1525,15 @@ static int pm2fb_setcolreg(unsigned regno,
return regno>255;
}
-static void pm2fb_dispsw(const void* par, struct display* disp,
+static void pm2fb_set_disp(const void* par, struct display* disp,
struct fb_info_gen* info) {
struct pm2fb_info* i=(struct pm2fb_info* )info;
- unsigned long flags;
- unsigned long depth;
+ u32 flags;
+ u32 depth;
save_flags(flags);
cli();
+ disp->screen_base=i->regions.v_fb;
switch (depth=((struct pm2fb_par* )par)->depth) {
#ifdef FBCON_HAS_CFB8
case 8:
@@ -1408,6 +1596,7 @@ __initfunc(void pm2fb_init(void)) {
memset(&fb_info, 0, sizeof(fb_info));
if (!pm2fb_conf(&fb_info))
return;
+ pm2fb_reset(&fb_info);
fb_info.disp.scrollmode=SCROLL_YNOMOVE;
fb_info.gen.parsize=sizeof(struct pm2fb_par);
fb_info.gen.fbhw=&pm2fb_hwswitch;
@@ -1420,19 +1609,18 @@ __initfunc(void pm2fb_init(void)) {
fb_info.gen.info.updatevar=&fbgen_update_var;
fb_info.gen.info.blank=&fbgen_blank;
fbgen_get_var(&fb_info.disp.var, -1, &fb_info.gen.info);
- if (fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen)<0)
- return;
+ fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen);
fbgen_set_disp(-1, &fb_info.gen);
fbgen_install_cmap(0, &fb_info.gen);
if (register_framebuffer(&fb_info.gen.info)<0) {
printk("pm2fb: unable to register.\n");
return;
}
- printk("fb%d: %s (%s), using %ldK of video memory.\n",
+ printk("fb%d: %s (%s), using %uK of video memory.\n",
GET_FB_IDX(fb_info.gen.info.node),
board_table[fb_info.board].name,
permedia2_name,
- (unsigned long )(fb_info.regions.fb_size>>10));
+ (u32 )(fb_info.regions.fb_size>>10));
MOD_INC_USE_COUNT;
}
@@ -1455,9 +1643,6 @@ __initfunc(void pm2fb_font_setup(char* options)) {
__initfunc(void pm2fb_setup(char* options, int* ints)) {
char* next;
- memset(&pm2fb_options, 0, sizeof(pm2fb_options));
- memcpy(&pm2fb_options.user_mode, &user_mode[0].par,
- sizeof(pm2fb_options.user_mode));
while (options) {
if ((next=strchr(options, ',')))
*(next++)='\0';
@@ -1469,6 +1654,8 @@ __initfunc(void pm2fb_setup(char* options, int* ints)) {
pm2fb_options.flags |= OPTF_YPAN;
else if (!strcmp(options, "oldmem"))
pm2fb_options.flags |= OPTF_OLD_MEM;
+ else if (!strcmp(options, "virtual"))
+ pm2fb_options.flags |= OPTF_VIRTUAL;
options=next;
}
}
diff --git a/drivers/video/pm2fb.h b/drivers/video/pm2fb.h
index 94f346427..f10ab7e93 100644
--- a/drivers/video/pm2fb.h
+++ b/drivers/video/pm2fb.h
@@ -2,7 +2,7 @@
* Permedia2 framebuffer driver definitions.
* Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
* --------------------------------------------------------------------------
- * $Id: pm2fb.h,v 1.1.2.1 1999/01/12 19:53:02 geert Exp $
+ * $Id: pm2fb.h,v 1.21 1999/01/28 13:18:07 illo Exp $
* --------------------------------------------------------------------------
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file README.legal in the main directory of this archive
@@ -16,7 +16,7 @@
#define PM2_MAX_PIXCLOCK 230000 /* in KHz */
#define PM2_REGS_SIZE 0x10000
-#define PM2TAG(r) (unsigned long )(((r)-0x8000)>>3)
+#define PM2TAG(r) (u32 )(((r)-0x8000)>>3)
/*****************************************************************************
* Permedia2 registers used in the framebuffer
@@ -128,16 +128,16 @@
#define PM2I_RD_BLUE_KEY 0x44
/* Fields and flags */
-#define PM2F_RENDER_AREASTIPPLE (1<<0)
-#define PM2F_RENDER_FASTFILL (1<<3)
-#define PM2F_RENDER_PRIMITIVE_MASK (0x3<<6)
+#define PM2F_RENDER_AREASTIPPLE (1L<<0)
+#define PM2F_RENDER_FASTFILL (1L<<3)
+#define PM2F_RENDER_PRIMITIVE_MASK (3L<<6)
#define PM2F_RENDER_LINE 0
-#define PM2F_RENDER_TRAPEZOID (1<<6)
-#define PM2F_RENDER_POINT (2<<6)
-#define PM2F_RENDER_RECTANGLE (3<<6)
-#define PM2F_SYNCHRONIZATION (1<<10)
+#define PM2F_RENDER_TRAPEZOID (1L<<6)
+#define PM2F_RENDER_POINT (2L<<6)
+#define PM2F_RENDER_RECTANGLE (3L<<6)
+#define PM2F_SYNCHRONIZATION (1L<<10)
#define PM2F_PLL_LOCKED 0x10
-#define PM2F_BEING_RESET (1<<31)
+#define PM2F_BEING_RESET (1L<<31)
#define PM2F_DATATYPE_COLOR 0x8000
#define PM2F_VGA_ENABLE 0x02
#define PM2F_VGA_FIXED 0x04
@@ -166,13 +166,18 @@
#define PM2F_TEXTEL_SIZE_32 0x00100000
#define PM2F_TEXTEL_SIZE_4 0x00180000
#define PM2F_TEXTEL_SIZE_24 0x00200000
-#define PM2F_INCREASE_X (1<<21)
-#define PM2F_INCREASE_Y (1<<22)
-#define PM2F_CONFIG_FB_WRITE_ENABLE (1<<3)
-#define PM2F_CONFIG_FB_PACKED_DATA (1<<2)
-#define PM2F_CONFIG_FB_READ_DEST_ENABLE (1<<1)
-#define PM2F_CONFIG_FB_READ_SOURCE_ENABLE (1<<0)
-#define PM2F_COLOR_KEY_TEST_OFF (1<<4)
+#define PM2F_INCREASE_X (1L<<21)
+#define PM2F_INCREASE_Y (1L<<22)
+#define PM2F_CONFIG_FB_WRITE_ENABLE (1L<<3)
+#define PM2F_CONFIG_FB_PACKED_DATA (1L<<2)
+#define PM2F_CONFIG_FB_READ_DEST_ENABLE (1L<<1)
+#define PM2F_CONFIG_FB_READ_SOURCE_ENABLE (1L<<0)
+#define PM2F_COLOR_KEY_TEST_OFF (1L<<4)
+#define PM2F_MEM_CONFIG_RAM_MASK (3L<<29)
+#define PM2F_MEM_BANKS_1 0L
+#define PM2F_MEM_BANKS_2 (1L<<29)
+#define PM2F_MEM_BANKS_3 (2L<<29)
+#define PM2F_MEM_BANKS_4 (3L<<29)
#endif /* PM2FB_H */
diff --git a/drivers/video/promcon.c b/drivers/video/promcon.c
index 9148f609e..984edab98 100644
--- a/drivers/video/promcon.c
+++ b/drivers/video/promcon.c
@@ -1,10 +1,11 @@
-/* $Id: promcon.c,v 1.12 1998/08/23 20:19:01 mj Exp $
+/* $Id: promcon.c,v 1.15 1999/04/22 06:35:32 davem Exp $
* Console driver utilizing PROM sun terminal emulation
*
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
* Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -230,7 +231,7 @@ promcon_putcs(struct vc_data *conp, const unsigned short *s,
int count, int y, int x)
{
unsigned char buf[256], *b = buf;
- unsigned short attr = *s;
+ unsigned short attr = scr_readw(s);
unsigned char save;
int i, last = 0;
@@ -256,9 +257,9 @@ promcon_putcs(struct vc_data *conp, const unsigned short *s,
}
if (inverted(attr))
- b += sprintf(b, "\033[7m%c\033[m", *s++);
+ b += sprintf(b, "\033[7m%c\033[m", scr_readw(s++));
else
- b += sprintf(b, "%c", *s++);
+ b += sprintf(b, "%c", scr_readw(s++));
strcpy(b, "\b\033[@");
b += 4;
@@ -295,14 +296,14 @@ promcon_putcs(struct vc_data *conp, const unsigned short *s,
promcon_puts(buf, b - buf);
b = buf;
}
- *b++ = *s++;
+ *b++ = scr_readw(s++);
}
px += count;
if (last) {
- save = *s++;
- b += sprintf(b, "%c\b\033[@%c", *s++, save);
+ save = scr_readw(s++);
+ b += sprintf(b, "%c\b\033[@%c", scr_readw(s++), save);
px++;
}
@@ -318,11 +319,12 @@ promcon_putcs(struct vc_data *conp, const unsigned short *s,
static void
promcon_putc(struct vc_data *conp, int c, int y, int x)
{
- unsigned short s = c;
+ unsigned short s;
if (console_blanked)
return;
+ scr_writew(c, &s);
promcon_putcs(conp, &s, 1, y, x);
}
@@ -591,8 +593,11 @@ struct consw prom_con = {
__initfunc(void prom_con_init(void))
{
+#ifdef CONFIG_DUMMY_CONSOLE
if (conswitchp == &dummy_con)
take_over_console(&prom_con, 0, MAX_NR_CONSOLES-1, 1);
- else if (conswitchp == &prom_con)
+ else
+#endif
+ if (conswitchp == &prom_con)
promcon_init_unimap(vc_cons[fg_console].d);
}
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
new file mode 100644
index 000000000..8cacf5966
--- /dev/null
+++ b/drivers/video/q40fb.c
@@ -0,0 +1,362 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.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-cfb16.h>
+
+
+#define Q40_PHYS_SCREEN_ADDR 0xFE800000
+static unsigned long q40_screen_addr;
+
+static u16 fbcon_cmap_cfb16[16];
+
+/* frame buffer operations */
+
+static int q40fb_open(struct fb_info *info, int user);
+static int q40fb_release(struct fb_info *info, int user);
+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_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int q40fb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg, int con,
+ 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 q40con_blank(int blank, 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 = {
+ q40fb_open,q40fb_release, q40fb_get_fix, q40fb_get_var, q40fb_set_var,
+ q40fb_get_cmap, q40fb_set_cmap, q40fb_pan_display, q40fb_ioctl
+};
+
+static int currcon=0;
+
+static char q40fb_name[]="Q40";
+
+static int q40fb_open(struct fb_info *info, int user)
+{
+ /*
+ * Nothing, only a usage count for the moment
+ */
+
+ MOD_INC_USE_COUNT;
+ return(0);
+}
+
+static int q40fb_release(struct fb_info *info, int user)
+{
+ MOD_DEC_USE_COUNT;
+ return(0);
+}
+
+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=(char*)q40_screen_addr;
+ 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 q40_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.
+ */
+
+ red>>=11;
+ green>>=11;
+ blue>>=10;
+
+ if (regno < 16) {
+ fbcon_cmap_cfb16[regno] = ((red & 31) <<5) |
+ ((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 == 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("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 == currcon) /* current console? */
+ return fb_set_cmap(cmap, kspc, q40_setcolreg, info);
+ else
+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+ return 0;
+#else
+ printk("set cmap not supported\n");
+
+ return -EINVAL;
+#endif
+}
+
+static int q40fb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ printk("panning not supported\n");
+
+ return -EINVAL;
+
+}
+
+static int q40fb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg, int con,
+ struct fb_info *info)
+{
+ return -EINVAL;
+}
+
+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->screen_base = fix.smem_start;
+ display->visual = fix.visual;
+ display->type = fix.type;
+ display->type_aux = fix.type_aux;
+ display->ypanstep = fix.ypanstep;
+ display->ywrapstep = fix.ywrapstep;
+ display->can_soft_blank = 0;
+ display->inverse = 0;
+ display->line_length = fix.line_length;
+
+#ifdef FBCON_HAS_CFB16
+ display->dispsw = &fbcon_cfb16;
+ disp->dispsw_data = fbcon_cmap_cfb16;
+#else
+ display->dispsw = &fbcon_dummy;
+#endif
+}
+
+void q40fb_init(void)
+{
+#if 0
+ q40_screen_addr = kernel_map(Q40_PHYS_SCREEN_ADDR, 1024*1024,
+ KERNELMAP_NO_COPYBACK, NULL);
+#else
+ q40_screen_addr = 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.switch_con=&q40con_switch;
+ fb_info.updatevar=&q40con_updatevar;
+ fb_info.blank=&q40con_blank;
+ fb_info.node = -1;
+ fb_info.fbops = &q40fb_ops;
+ fb_info.flags = FBINFO_FLAG_DEFAULT; /* not as module for now */
+
+ master_outb(3,DISPLAY_CONTROL_REG);
+
+ q40fb_get_var(&disp[0].var, 0, &fb_info);
+ q40fb_set_disp(-1, &fb_info);
+
+ if (register_framebuffer(&fb_info) < 0)
+ panic("unable to register Q40 frame buffer\n");
+
+
+ printk("fb%d: Q40 frame buffer alive and kicking !\n",
+ GET_FB_IDX(fb_info.node));
+}
+
+
+static int q40con_switch(int con, struct fb_info *info)
+{
+ currcon=con;
+
+ return 0;
+
+}
+
+static int q40con_updatevar(int con, struct fb_info *info)
+{
+ return 0;
+}
+
+static void q40con_blank(int blank, struct fb_info *info)
+{
+}
diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c
index 995e86506..1ee42692f 100644
--- a/drivers/video/retz3fb.c
+++ b/drivers/video/retz3fb.c
@@ -101,8 +101,8 @@ struct display_data {
struct retz3_fb_info {
struct fb_info info;
- unsigned long base;
- unsigned long fbmem;
+ unsigned char *base;
+ unsigned char *fbmem;
unsigned long fbsize;
volatile unsigned char *regs;
unsigned long physfbmem;
@@ -1209,7 +1209,7 @@ static void retz3fb_set_disp(int con, struct fb_info *info)
if (con == -1)
con = 0;
- display->screen_base = (char *)zinfo->fbmem;
+ display->screen_base = zinfo->fbmem;
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
@@ -1282,7 +1282,7 @@ static int retz3fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_fix_screeninfo fix;
retz3fb_get_fix(&fix, con, info);
- display->screen_base = (char *)zinfo->fbmem;
+ display->screen_base = zinfo->fbmem;
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
@@ -1456,7 +1456,7 @@ __initfunc(void retz3fb_init(void))
board_size = (unsigned long)cd->cd_BoardSize;
zinfo->base = ioremap(board_addr, board_size);
- zinfo->regs = (unsigned char *)(zinfo->base);
+ zinfo->regs = zinfo->base;
zinfo->fbmem = zinfo->base + VIDEO_MEM_OFFSET;
/* Get memory size - for now we asume its a 4MB board */
zinfo->fbsize = 0x00400000; /* 4 MB */
diff --git a/drivers/video/sbusfb.c b/drivers/video/sbusfb.c
index 88ecf5743..ce2c89eb7 100644
--- a/drivers/video/sbusfb.c
+++ b/drivers/video/sbusfb.c
@@ -229,7 +229,12 @@ static int sbusfb_mmap(struct fb_info *info, struct file *file,
for (i = 0; fb->mmap_map[i].size; i++)
if (fb->mmap_map[i].voff == vma->vm_offset+page) {
map_size = sbusfb_mmapsize(fb,fb->mmap_map[i].size);
- map_offset = (fb->physbase + fb->mmap_map[i].poff) & PAGE_MASK;
+#ifdef __sparc_v9__
+#define POFF_MASK (PAGE_MASK|0x1UL)
+#else
+#define POFF_MASK (PAGE_MASK)
+#endif
+ map_offset = (fb->physbase + fb->mmap_map[i].poff) & POFF_MASK;
break;
}
if (!map_size){
@@ -244,8 +249,6 @@ static int sbusfb_mmap(struct fb_info *info, struct file *file,
page += map_size;
}
- vma->vm_file = file;
- file->f_count++;
vma->vm_flags |= VM_IO;
if (!fb->mmaped) {
int lastconsole = 0;
@@ -517,7 +520,7 @@ static void sbusfb_cursor(struct display *p, int mode, int x, int y)
static int sbusfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
- if (con == currcon) /* current console? */
+ if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */
return fb_get_cmap(cmap, kspc, sbusfb_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
@@ -534,9 +537,14 @@ static int sbusfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
int err;
+ struct display *disp;
- if (!fb_display[con].cmap.len) { /* no colormap allocated? */
- if ((err = fb_alloc_cmap(&fb_display[con].cmap, 1<<fb_display[con].var.bits_per_pixel, 0)))
+ if (con >= 0)
+ disp = &fb_display[con];
+ else
+ disp = info->disp;
+ if (!disp->cmap.len) { /* no colormap allocated? */
+ if ((err = fb_alloc_cmap(&disp->cmap, 1<<disp->var.bits_per_pixel, 0)))
return err;
}
if (con == currcon) { /* current console? */
@@ -549,7 +557,7 @@ static int sbusfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
}
return err;
} else
- fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+ fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
return 0;
}
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
new file mode 100644
index 000000000..71aafc340
--- /dev/null
+++ b/drivers/video/sgivwfb.c
@@ -0,0 +1,1037 @@
+/*
+ * linux/drivers/video/sgivwfb.c -- SGI DBE frame buffer device
+ *
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Jeffrey Newquist, newquist@engr.sgi.som
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <asm/uaccess.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <asm/mtrr.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb32.h>
+
+#define INCLUDE_TIMING_TABLE_DATA
+#define DBE_REG_BASE regs
+#include "sgivwfb.h"
+
+struct sgivwfb_par {
+ struct fb_var_screeninfo var;
+ u_long timing_num;
+ int valid;
+};
+
+/*
+ * RAM we reserve for the frame buffer. This defines the maximum screen
+ * size
+ *
+ * The default can be overridden if the driver is compiled as a module
+ */
+
+/* set by arch/i386/kernel/setup.c */
+u_long sgivwfb_mem_phys;
+u_long sgivwfb_mem_size;
+
+static volatile char *fbmem;
+static asregs *regs;
+static struct fb_info fb_info;
+static struct { u_char red, green, blue, pad; } palette[256];
+static char sgivwfb_name[16] = "SGI Vis WS FB";
+static u32 cmap_fifo;
+static int ypan = 0;
+static int ywrap = 0;
+
+/* console related variables */
+static int currcon = 0;
+static struct display disp;
+
+static union {
+#ifdef FBCON_HAS_CFB16
+ u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u32 cfb32[16];
+#endif
+} fbcon_cmap;
+
+static struct sgivwfb_par par_current = {
+ { /* var (screeninfo) */
+ /* 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
+ },
+ 0, /* timing_num */
+ 0 /* par not activated */
+};
+
+/*
+ * Interface used by the world
+ */
+void sgivwfb_setup(char *options, int *ints);
+
+static int sgivwfb_open(struct fb_info *info, int user);
+static int sgivwfb_release(struct fb_info *info, int user);
+static int sgivwfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info);
+static int sgivwfb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int sgivwfb_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int sgivwfb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int sgivwfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info);
+static int sgivwfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info);
+static int sgivwfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+ u_long arg, int con, struct fb_info *info);
+static int sgivwfb_mmap(struct fb_info *info, struct file *file,
+ struct vm_area_struct *vma);
+
+static struct fb_ops sgivwfb_ops = {
+ sgivwfb_open,
+ sgivwfb_release,
+ sgivwfb_get_fix,
+ sgivwfb_get_var,
+ sgivwfb_set_var,
+ sgivwfb_get_cmap,
+ sgivwfb_set_cmap,
+ sgivwfb_pan_display,
+ sgivwfb_ioctl,
+ sgivwfb_mmap
+};
+
+/*
+ * Interface to the low level console driver
+ */
+void sgivwfb_init(void);
+static int sgivwfbcon_switch(int con, struct fb_info *info);
+static int sgivwfbcon_updatevar(int con, struct fb_info *info);
+static void sgivwfbcon_blank(int blank, struct fb_info *info);
+
+/*
+ * Internal routines
+ */
+static u_long get_line_length(int xres_virtual, int bpp);
+static unsigned long bytes_per_pixel(int bpp);
+static void activate_par(struct sgivwfb_par *par);
+static void sgivwfb_encode_fix(struct fb_fix_screeninfo *fix,
+ struct fb_var_screeninfo *var);
+static int sgivwfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+ u_int *transp, struct fb_info *info);
+static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info);
+static void do_install_cmap(int con, struct fb_info *info);
+
+static unsigned long get_line_length(int xres_virtual, int bpp)
+{
+ return(xres_virtual * bytes_per_pixel(bpp));
+}
+
+static unsigned long bytes_per_pixel(int bpp)
+{
+ unsigned long length;
+
+ switch (bpp) {
+ case 8:
+ length = 1;
+ break;
+ case 16:
+ length = 2;
+ break;
+ case 32:
+ length = 4;
+ break;
+ default:
+ printk("sgivwfb: unsupported bpp=%d\n", bpp);
+ length = 0;
+ break;
+ }
+ return(length);
+}
+
+/*
+ * Function: dbe_TurnOffDma
+ * Parameters: (None)
+ * Description: This should turn off the monitor and dbe. This is used
+ * when switching between the serial console and the graphics
+ * console.
+ */
+
+static void dbe_TurnOffDma(void)
+{
+ int i;
+ unsigned int readVal;
+
+ // Check to see if things are already turned off:
+ // 1) Check to see if dbe is not using the internal dotclock.
+ // 2) Check to see if the xy counter in dbe is already off.
+
+ DBE_GETREG(ctrlstat, readVal);
+ if (GET_DBE_FIELD(CTRLSTAT, PCLKSEL, readVal) < 2)
+ return;
+
+ DBE_GETREG(vt_xy, readVal);
+ if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1)
+ return;
+
+ // Otherwise, turn off dbe
+
+ DBE_GETREG(ovr_control, readVal);
+ SET_DBE_FIELD(OVR_CONTROL, OVR_DMA_ENABLE, readVal, 0);
+ DBE_SETREG(ovr_control, readVal);
+ udelay(1000);
+ DBE_GETREG(frm_control, readVal);
+ SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, readVal, 0);
+ DBE_SETREG(frm_control, readVal);
+ udelay(1000);
+ DBE_GETREG(did_control, readVal);
+ SET_DBE_FIELD(DID_CONTROL, DID_DMA_ENABLE, readVal, 0);
+ DBE_SETREG(did_control, readVal);
+ udelay(1000);
+
+ // XXX HACK:
+ //
+ // This was necessary for GBE--we had to wait through two
+ // vertical retrace periods before the pixel DMA was
+ // turned off for sure. I've left this in for now, in
+ // case dbe needs it.
+
+ for (i = 0; i < 10000; i++)
+ {
+ DBE_GETREG(frm_inhwctrl, readVal);
+ if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) == 0)
+ udelay(10);
+ else
+ {
+ DBE_GETREG(ovr_inhwctrl, readVal);
+ if (GET_DBE_FIELD(OVR_INHWCTRL, OVR_DMA_ENABLE, readVal) == 0)
+ udelay(10);
+ else
+ {
+ DBE_GETREG(did_inhwctrl, readVal);
+ if (GET_DBE_FIELD(DID_INHWCTRL, DID_DMA_ENABLE, readVal) == 0)
+ udelay(10);
+ else
+ break;
+ }
+ }
+ }
+}
+
+/*
+ * Set the hardware according to 'par'.
+ */
+static void activate_par(struct sgivwfb_par *par)
+{
+ int i,j, htmp, temp;
+ u32 readVal, outputVal;
+ int wholeTilesX, maxPixelsPerTileX;
+ int frmWrite1, frmWrite2, frmWrite3b;
+ dbe_timing_info_t *currentTiming; /* Current Video Timing */
+ int xpmax, ypmax; // Monitor resolution
+ int bytesPerPixel; // Bytes per pixel
+
+ currentTiming = &dbeVTimings[par->timing_num];
+ bytesPerPixel = bytes_per_pixel(par->var.bits_per_pixel);
+ xpmax = currentTiming->width;
+ ypmax = currentTiming->height;
+
+ /* dbe_InitGraphicsBase(); */
+ /* Turn on dotclock PLL */
+ DBE_SETREG(ctrlstat, 0x20000000);
+
+ dbe_TurnOffDma();
+
+ /* dbe_CalculateScreenParams(); */
+ maxPixelsPerTileX = 512/bytesPerPixel;
+ wholeTilesX = xpmax/maxPixelsPerTileX;
+ if (wholeTilesX*maxPixelsPerTileX < xpmax)
+ wholeTilesX++;
+
+ printk("sgivwfb: pixPerTile=%d wholeTilesX=%d\n",
+ maxPixelsPerTileX, wholeTilesX);
+
+ /* dbe_InitGammaMap(); */
+ udelay(10);
+
+ for (i = 0; i < 256; i++)
+ {
+ DBE_ISETREG(gmap, i, (i << 24) | (i << 16) | (i << 8));
+ }
+
+ /* dbe_TurnOn(); */
+ DBE_GETREG(vt_xy, readVal);
+ if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1)
+ {
+ DBE_SETREG(vt_xy, 0x00000000);
+ udelay(1);
+ }
+ else
+ dbe_TurnOffDma();
+
+ /* dbe_Initdbe(); */
+ for (i = 0; i < 256; i++)
+ {
+ for (j = 0; j < 100; j++)
+ {
+ DBE_GETREG(cm_fifo, readVal);
+ if (readVal != 0x00000000)
+ break;
+ else
+ udelay(10);
+ }
+
+ // DBE_ISETREG(cmap, i, 0x00000000);
+ DBE_ISETREG(cmap, i, (i<<8)|(i<<16)|(i<<24));
+ }
+
+ /* dbe_InitFramebuffer(); */
+ frmWrite1 = 0;
+ SET_DBE_FIELD(FRM_SIZE_TILE, FRM_WIDTH_TILE, frmWrite1, wholeTilesX);
+ SET_DBE_FIELD(FRM_SIZE_TILE, FRM_RHS, frmWrite1, 0);
+
+ switch(bytesPerPixel)
+ {
+ case 1:
+ SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1, DBE_FRM_DEPTH_8);
+ break;
+ case 2:
+ SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1, DBE_FRM_DEPTH_16);
+ break;
+ case 4:
+ SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1, DBE_FRM_DEPTH_32);
+ break;
+ }
+
+ frmWrite2 = 0;
+ SET_DBE_FIELD(FRM_SIZE_PIXEL, FB_HEIGHT_PIX, frmWrite2, ypmax);
+
+ // Tell dbe about the framebuffer location and type
+ // XXX What format is the FRM_TILE_PTR?? 64K aligned address?
+ frmWrite3b = 0;
+ SET_DBE_FIELD(FRM_CONTROL, FRM_TILE_PTR, frmWrite3b, sgivwfb_mem_phys>>9);
+ SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, frmWrite3b, 1);
+ SET_DBE_FIELD(FRM_CONTROL, FRM_LINEAR, frmWrite3b, 1);
+
+ /* Initialize DIDs */
+
+ outputVal = 0;
+ switch(bytesPerPixel)
+ {
+ case 1:
+ SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_I8);
+ break;
+ case 2:
+ SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGBA5);
+ break;
+ case 4:
+ SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGB8);
+ break;
+ }
+ SET_DBE_FIELD(WID, BUF, outputVal, DBE_BMODE_BOTH);
+
+ for (i = 0; i < 32; i++)
+ {
+ DBE_ISETREG(mode_regs, i, outputVal);
+ }
+
+ /* dbe_InitTiming(); */
+ DBE_SETREG(vt_intr01, 0xffffffff);
+ DBE_SETREG(vt_intr23, 0xffffffff);
+
+ DBE_GETREG(dotclock, readVal);
+ DBE_SETREG(dotclock, readVal & 0xffff);
+
+ DBE_SETREG(vt_xymax, 0x00000000);
+ outputVal = 0;
+ SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_ON, outputVal, currentTiming->vsync_start);
+ SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_OFF, outputVal, currentTiming->vsync_end);
+ DBE_SETREG(vt_vsync, outputVal);
+ outputVal = 0;
+ SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_ON, outputVal, currentTiming->hsync_start);
+ SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_OFF, outputVal, currentTiming->hsync_end);
+ DBE_SETREG(vt_hsync, outputVal);
+ outputVal = 0;
+ SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_ON, outputVal, currentTiming->vblank_start);
+ SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_OFF, outputVal, currentTiming->vblank_end);
+ DBE_SETREG(vt_vblank, outputVal);
+ outputVal = 0;
+ SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_ON, outputVal, currentTiming->hblank_start);
+ SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_OFF, outputVal, currentTiming->hblank_end-3);
+ DBE_SETREG(vt_hblank, outputVal);
+ outputVal = 0;
+ SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_ON, outputVal, currentTiming->vblank_start);
+ SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_OFF, outputVal, currentTiming->vblank_end);
+ DBE_SETREG(vt_vcmap, outputVal);
+ outputVal = 0;
+ SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_ON, outputVal, currentTiming->hblank_start);
+ SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_OFF, outputVal, currentTiming->hblank_end-3);
+ DBE_SETREG(vt_hcmap, outputVal);
+
+ outputVal = 0;
+ temp = currentTiming->vblank_start - currentTiming->vblank_end - 1;
+ if (temp > 0)
+ temp = -temp;
+
+ SET_DBE_FIELD(DID_START_XY, DID_STARTY, outputVal, (u32)temp);
+ if (currentTiming->hblank_end >= 20)
+ SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal,
+ currentTiming->hblank_end - 20);
+ else
+ SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal,
+ currentTiming->htotal - (20 - currentTiming->hblank_end));
+ DBE_SETREG(did_start_xy, outputVal);
+
+ outputVal = 0;
+ SET_DBE_FIELD(CRS_START_XY, CRS_STARTY, outputVal, (u32)(temp+1));
+ if (currentTiming->hblank_end >= DBE_CRS_MAGIC)
+ SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal,
+ currentTiming->hblank_end - DBE_CRS_MAGIC);
+ else
+ SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal,
+ currentTiming->htotal - (DBE_CRS_MAGIC - currentTiming->hblank_end));
+ DBE_SETREG(crs_start_xy, outputVal);
+
+ outputVal = 0;
+ SET_DBE_FIELD(VC_START_XY, VC_STARTY, outputVal, (u32)temp);
+ SET_DBE_FIELD(VC_START_XY, VC_STARTX, outputVal,
+ currentTiming->hblank_end - 4);
+ DBE_SETREG(vc_start_xy, outputVal);
+
+ DBE_SETREG(frm_size_tile, frmWrite1);
+ DBE_SETREG(frm_size_pixel, frmWrite2);
+
+ outputVal = 0;
+ SET_DBE_FIELD(DOTCLK, M, outputVal, currentTiming->pll_m-1);
+ SET_DBE_FIELD(DOTCLK, N, outputVal, currentTiming->pll_n-1);
+ SET_DBE_FIELD(DOTCLK, P, outputVal, currentTiming->pll_p);
+ SET_DBE_FIELD(DOTCLK, RUN, outputVal, 1);
+ DBE_SETREG(dotclock, outputVal);
+
+ udelay(11*1000);
+
+ DBE_SETREG(vt_vpixen, 0xffffff);
+ DBE_SETREG(vt_hpixen, 0xffffff);
+
+ outputVal = 0;
+ SET_DBE_FIELD(VT_XYMAX, VT_MAXX, outputVal, currentTiming->htotal);
+ SET_DBE_FIELD(VT_XYMAX, VT_MAXY, outputVal, currentTiming->vtotal);
+ DBE_SETREG(vt_xymax, outputVal);
+
+ outputVal = frmWrite1;
+ SET_DBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, outputVal, 1);
+ DBE_SETREG(frm_size_tile, outputVal);
+ DBE_SETREG(frm_size_tile, frmWrite1);
+
+ outputVal = 0;
+ SET_DBE_FIELD(OVR_WIDTH_TILE, OVR_FIFO_RESET, outputVal, 1);
+ DBE_SETREG(ovr_width_tile, outputVal);
+ DBE_SETREG(ovr_width_tile, 0);
+
+ DBE_SETREG(frm_control, frmWrite3b);
+ DBE_SETREG(did_control, 0);
+
+ // Wait for dbe to take frame settings
+ for (i=0; i<100000; i++)
+ {
+ DBE_GETREG(frm_inhwctrl, readVal);
+ if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) != 0)
+ break;
+ else
+ udelay(1);
+ }
+
+ if (i==100000)
+ printk("sgivwfb: timeout waiting for frame DMA enable.\n");
+
+ outputVal = 0;
+ htmp = currentTiming->hblank_end - 19;
+ if (htmp < 0)
+ htmp += currentTiming->htotal; /* allow blank to wrap around */
+ SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_ON, outputVal, htmp);
+ SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_OFF, outputVal,
+ ((htmp + currentTiming->width - 2) % currentTiming->htotal));
+ DBE_SETREG(vt_hpixen, outputVal);
+
+ outputVal = 0;
+ SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_OFF, outputVal,
+ currentTiming->vblank_start);
+ SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_ON, outputVal,
+ currentTiming->vblank_end);
+ DBE_SETREG(vt_vpixen, outputVal);
+
+ // Turn off mouse cursor
+ regs->crs_ctl = 0;
+
+ // XXX What's this section for??
+ DBE_GETREG(ctrlstat, readVal);
+ readVal &= 0x02000000;
+
+ if (readVal != 0)
+ {
+ DBE_SETREG(ctrlstat, 0x30000000);
+ }
+}
+
+static void sgivwfb_encode_fix(struct fb_fix_screeninfo *fix,
+ struct fb_var_screeninfo *var)
+{
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+ strcpy(fix->id, sgivwfb_name);
+ fix->smem_start = (char *) sgivwfb_mem_phys;
+ fix->smem_len = sgivwfb_mem_size;
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->type_aux = 0;
+ switch (var->bits_per_pixel) {
+ case 8:
+ fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
+ default:
+ fix->visual = FB_VISUAL_TRUECOLOR;
+ break;
+ }
+ fix->ywrapstep = ywrap;
+ fix->xpanstep = 0;
+ fix->ypanstep = ypan;
+ fix->line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
+ fix->mmio_start = (char *) DBE_REG_PHYS;
+ fix->mmio_len = DBE_REG_SIZE;
+}
+
+/*
+ * Read a single color register and split it into
+ * colors/transparent. Return != 0 for invalid regno.
+ */
+static int sgivwfb_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;
+ *green = palette[regno].green << 8;
+ *blue = palette[regno].blue << 8;
+ *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 sgivwfb_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;
+
+ /* wait for the color map FIFO to have a free entry */
+ while (cmap_fifo == 0)
+ cmap_fifo = regs->cm_fifo;
+
+ regs->cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
+ cmap_fifo--; /* assume FIFO is filling up */
+ return 0;
+}
+
+static void do_install_cmap(int con, struct fb_info *info)
+{
+ if (con != currcon)
+ return;
+ if (fb_display[con].cmap.len)
+ fb_set_cmap(&fb_display[con].cmap, 1, sgivwfb_setcolreg, info);
+ else
+ fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), 1,
+ sgivwfb_setcolreg, info);
+}
+
+/* ---------------------------------------------------- */
+
+/*
+ * Open/Release the frame buffer device
+ */
+static int sgivwfb_open(struct fb_info *info, int user)
+{
+ /*
+ * Nothing, only a usage count for the moment
+ */
+ MOD_INC_USE_COUNT;
+ return(0);
+}
+
+static int sgivwfb_release(struct fb_info *info, int user)
+{
+ MOD_DEC_USE_COUNT;
+ return(0);
+}
+
+/*
+ * Get the Fixed Part of the Display
+ */
+static int sgivwfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info)
+{
+ struct fb_var_screeninfo *var;
+
+ if (con == -1)
+ var = &par_current.var;
+ else
+ var = &fb_display[con].var;
+ sgivwfb_encode_fix(fix, var);
+ return 0;
+}
+
+/*
+ * Get the User Defined Part of the Display. If a real par get it form there
+ */
+static int sgivwfb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ if (con == -1)
+ *var = par_current.var;
+ else
+ *var = fb_display[con].var;
+ return 0;
+}
+
+/*
+ * Set the User Defined Part of the Display. Again if par use it to get
+ * real video mode.
+ */
+static int sgivwfb_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;
+ u_long min_mode;
+ int req_dot;
+ int test_mode;
+
+ struct dbe_timing_info *timing;
+
+ struct display *display;
+
+ if (con >= 0)
+ display = &fb_display[con];
+ else
+ display = &disp; /* used during initialization */
+
+ /*
+ * FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
+ * as FB_VMODE_SMOOTH_XPAN is only used internally
+ */
+
+ if (var->vmode & FB_VMODE_CONUPDATE) {
+ var->vmode |= FB_VMODE_YWRAP;
+ var->xoffset = display->var.xoffset;
+ var->yoffset = display->var.yoffset;
+ }
+
+ /* XXX FIXME - forcing var's */
+ var->xoffset = 0;
+ var->yoffset = 0;
+
+ /* Limit bpp to 8, 16, and 32 */
+ 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 <= 32)
+ var->bits_per_pixel = 32;
+ else
+ return -EINVAL;
+
+ var->grayscale = 0; /* No grayscale for now */
+
+ /* determine valid resolution and timing */
+ for (min_mode=0; min_mode<DBE_VT_SIZE; min_mode++) {
+ if (dbeVTimings[min_mode].width >= var->xres &&
+ dbeVTimings[min_mode].height >= var->yres)
+ break;
+ }
+
+ if (min_mode == DBE_VT_SIZE)
+ return -EINVAL; /* Resolution to high */
+
+ /* XXX FIXME - should try to pick best refresh rate */
+ /* for now, pick closest dot-clock within 3MHz*/
+ req_dot = (int)((1.0e3/1.0e6) / (1.0e-12 * (float)var->pixclock));
+ printk("sgivwfb: requested pixclock=%d ps (%d KHz)\n", var->pixclock,
+ req_dot);
+ test_mode=min_mode;
+ while (dbeVTimings[min_mode].width == dbeVTimings[test_mode].width) {
+ if (dbeVTimings[test_mode].cfreq+3000 > req_dot)
+ break;
+ test_mode++;
+ }
+ if (dbeVTimings[min_mode].width != dbeVTimings[test_mode].width)
+ test_mode--;
+ min_mode = test_mode;
+ timing = &dbeVTimings[min_mode];
+ printk("sgivwfb: granted dot-clock=%d KHz\n", timing->cfreq);
+
+ /* Adjust virtual resolution, if necessary */
+ if (var->xres > var->xres_virtual || (!ywrap && !ypan))
+ var->xres_virtual = var->xres;
+ if (var->yres > var->yres_virtual || (!ywrap && !ypan))
+ var->yres_virtual = var->yres;
+
+ /*
+ * Memory limit
+ */
+ line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
+ if (line_length*var->yres_virtual > sgivwfb_mem_size)
+ return -ENOMEM; /* Virtual resolution to high */
+
+ 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: /* RGBA 5551 */
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 6;
+ var->green.length = 5;
+ var->blue.offset = 1;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ case 32: /* RGB 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;
+
+ /* set video timing information */
+ var->pixclock = (__u32)(1.0e+9/(float)timing->cfreq);
+ var->left_margin = timing->htotal - timing->hsync_end;
+ var->right_margin = timing->hsync_start - timing->width;
+ var->upper_margin = timing->vtotal - timing->vsync_end;
+ var->lower_margin = timing->vsync_start - timing->height;
+ var->hsync_len = timing->hsync_end - timing->hsync_start;
+ var->vsync_len = timing->vsync_end - timing->vsync_start;
+
+ 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;
+ par_current.var = *var;
+ par_current.timing_num = min_mode;
+ if (oldxres != var->xres || oldyres != var->yres ||
+ oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
+ oldbpp != var->bits_per_pixel || !par_current.valid) {
+ struct fb_fix_screeninfo fix;
+ printk("sgivwfb: new video mode xres=%d yres=%d bpp=%d\n",
+ var->xres, var->yres, var->bits_per_pixel);
+ printk(" vxres=%d vyres=%d\n",
+ var->xres_virtual, var->yres_virtual);
+ activate_par(&par_current);
+ sgivwfb_encode_fix(&fix, var);
+ display->screen_base = (char *)fbmem;
+ 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;
+ if (oldbpp != var->bits_per_pixel || !par_current.valid) {
+ if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
+ return err;
+ do_install_cmap(con, info);
+ }
+ switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ display->dispsw = &fbcon_cfb8;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ display->dispsw = &fbcon_cfb16;
+ display->dispsw_data = fbcon_cmap.cfb16;
+ 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;
+ }
+ par_current.valid = 1;
+ if (fb_info.changevar)
+ (*fb_info.changevar)(con);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Pan or Wrap the Display
+ *
+ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+
+static int sgivwfb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+#if 0
+ 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;
+#endif
+ return -EINVAL;
+}
+
+/*
+ * Get the Colormap
+ */
+static int sgivwfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ if (con == currcon) /* current console? */
+ return fb_get_cmap(cmap, kspc, sgivwfb_getcolreg, info);
+ else if (fb_display[con].cmap.len) /* non default colormap? */
+ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+ else
+ fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
+ cmap, kspc ? 0 : 2);
+ return 0;
+}
+
+/*
+ * Set the Colormap
+ */
+static int sgivwfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ int err;
+
+ if (!fb_display[con].cmap.len) { /* no colormap allocated? */
+ if ((err = fb_alloc_cmap(&fb_display[con].cmap,
+ 1<<fb_display[con].var.bits_per_pixel, 0)))
+ return err;
+ }
+ if (con == currcon) /* current console? */
+ return fb_set_cmap(cmap, kspc, sgivwfb_setcolreg, info);
+ else
+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+ return 0;
+}
+
+/*
+ * Virtual Frame Buffer Specific ioctls
+ */
+static int sgivwfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+ u_long arg, int con, struct fb_info *info)
+{
+ return -EINVAL;
+}
+
+static int sgivwfb_mmap(struct fb_info *info, struct file *file,
+ struct vm_area_struct *vma)
+{
+ unsigned long size = vma->vm_end - vma->vm_start;
+ unsigned long offset = sgivwfb_mem_phys + vma->vm_offset;
+ if (vma->vm_offset+size > sgivwfb_mem_size)
+ return -EINVAL;
+ pgprot_val(vma->vm_page_prot) = pgprot_val(vma->vm_page_prot) | _PAGE_PCD;
+ vma->vm_flags |= VM_IO;
+ if (remap_page_range(vma->vm_start, offset, size, vma->vm_page_prot))
+ return -EAGAIN;
+ vma->vm_file = file;
+ printk("sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n", offset, vma->vm_start);
+ return 0;
+}
+
+__initfunc(void sgivwfb_setup(char *options, int *ints))
+{
+ char *this_opt;
+
+ fb_info.fontname[0] = '\0';
+
+ if (!options || !*options)
+ return;
+
+ for (this_opt = strtok(options, ","); this_opt;
+ this_opt = strtok(NULL, ",")) {
+ if (!strncmp(this_opt, "font:", 5))
+ strcpy(fb_info.fontname, this_opt+5);
+ }
+}
+
+/*
+ * Initialisation
+ */
+__initfunc(void sgivwfb_init(void))
+{
+ printk("sgivwfb: framebuffer at 0x%lx, size %ldk\n",
+ sgivwfb_mem_phys, sgivwfb_mem_size/1024);
+
+ regs = (asregs*)ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
+ if (!regs) {
+ printk("sgivwfb: couldn't ioremap registers\n");
+ goto fail_ioremap_regs;
+ }
+
+#ifdef CONFIG_MTRR
+ mtrr_add((unsigned long)sgivwfb_mem_phys, sgivwfb_mem_size, MTRR_TYPE_WRCOMB, 1);
+#endif
+
+ strcpy(fb_info.modename, sgivwfb_name);
+ fb_info.changevar = NULL;
+ fb_info.node = -1;
+ fb_info.fbops = &sgivwfb_ops;
+ fb_info.disp = &disp;
+ fb_info.switch_con = &sgivwfbcon_switch;
+ fb_info.updatevar = &sgivwfbcon_updatevar;
+ fb_info.blank = &sgivwfbcon_blank;
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+ fbmem = ioremap_nocache((unsigned long)sgivwfb_mem_phys, sgivwfb_mem_size);
+ if (!fbmem) {
+ printk("sgivwfb: couldn't ioremap fbmem\n");
+ goto fail_ioremap_fbmem;
+ }
+
+ /* turn on default video mode */
+ sgivwfb_set_var(&par_current.var, -1, &fb_info);
+
+ if (register_framebuffer(&fb_info) < 0) {
+ printk("sgivwfb: couldn't register framebuffer\n");
+ goto fail_register_framebuffer;
+ }
+
+ printk("fb%d: Virtual frame buffer device, using %ldK of video memory\n",
+ GET_FB_IDX(fb_info.node), sgivwfb_mem_size>>10);
+
+ return;
+
+ fail_register_framebuffer:
+ iounmap((char*)fbmem);
+ fail_ioremap_fbmem:
+ iounmap(regs);
+ fail_ioremap_regs:
+ return;
+}
+
+static int sgivwfbcon_switch(int con, struct fb_info *info)
+{
+ /* Do we have to save the colormap? */
+ if (fb_display[currcon].cmap.len)
+ fb_get_cmap(&fb_display[currcon].cmap, 1, sgivwfb_getcolreg, info);
+
+ currcon = con;
+ /* Install new colormap */
+ do_install_cmap(con, info);
+ return 0;
+}
+
+/*
+ * Update the `var' structure (called by fbcon.c)
+ */
+static int sgivwfbcon_updatevar(int con, struct fb_info *info)
+{
+ /* Nothing */
+ return 0;
+}
+
+/*
+ * Blank the display.
+ */
+static void sgivwfbcon_blank(int blank, struct fb_info *info)
+{
+ /* Nothing */
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+ sgivwfb_init();
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ unregister_framebuffer(&fb_info);
+ dbe_TurnOffDma();
+ iounmap(regs);
+ iounmap(fbmem);
+}
+
+#endif /* MODULE */
diff --git a/drivers/video/sgivwfb.h b/drivers/video/sgivwfb.h
new file mode 100644
index 000000000..8ff8a77f4
--- /dev/null
+++ b/drivers/video/sgivwfb.h
@@ -0,0 +1,660 @@
+/*
+ * linux/drivers/video/sgivwfb.h -- SGI DBE frame buffer device header
+ *
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Jeffrey Newquist, newquist@engr.sgi.som
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#ifndef __SGIVWFB_H__
+#define __SGIVWFB_H__
+
+#define DBE_GETREG(reg, dest) ((dest) = DBE_REG_BASE->##reg)
+#define DBE_SETREG(reg, src) DBE_REG_BASE->##reg = (src)
+#define DBE_IGETREG(reg, idx, dest) ((dest) = DBE_REG_BASE->##reg##[idx])
+#define DBE_ISETREG(reg, idx, src) (DBE_REG_BASE->##reg##[idx] = (src))
+
+#define MASK(msb, lsb) ( (((u32)1<<((msb)-(lsb)+1))-1) << (lsb) )
+#define GET(v, msb, lsb) ( ((u32)(v) & MASK(msb,lsb)) >> (lsb) )
+#define SET(v, f, msb, lsb) ( (v) = ((v)&~MASK(msb,lsb)) | (( (u32)(f)<<(lsb) ) & MASK(msb,lsb)) )
+
+#define GET_DBE_FIELD(reg, field, v) GET((v), DBE_##reg##_##field##_MSB, DBE_##reg##_##field##_LSB)
+#define SET_DBE_FIELD(reg, field, v, f) SET((v), (f), DBE_##reg##_##field##_MSB, DBE_##reg##_##field##_LSB)
+
+/* NOTE: All loads/stores must be 32 bits and uncached */
+
+#define DBE_REG_PHYS 0xd0000000
+#define DBE_REG_SIZE 0x01000000
+
+typedef struct {
+ volatile u32 ctrlstat; /* 0x000000 general control */
+ volatile u32 dotclock; /* 0x000004 dot clock PLL control */
+ volatile u32 i2c; /* 0x000008 crt I2C control */
+ volatile u32 sysclk; /* 0x00000c system clock PLL control */
+ volatile u32 i2cfp; /* 0x000010 flat panel I2C control */
+ volatile u32 id; /* 0x000014 device id/chip revision */
+ volatile u32 config; /* 0x000018 power on configuration */
+ volatile u32 bist; /* 0x00001c internal bist status */
+
+ char _pad0[ 0x010000 - 0x000020 ];
+
+ volatile u32 vt_xy; /* 0x010000 current dot coords */
+ volatile u32 vt_xymax; /* 0x010004 maximum dot coords */
+ volatile u32 vt_vsync; /* 0x010008 vsync on/off */
+ volatile u32 vt_hsync; /* 0x01000c hsync on/off */
+ volatile u32 vt_vblank; /* 0x010010 vblank on/off */
+ volatile u32 vt_hblank; /* 0x010014 hblank on/off */
+ volatile u32 vt_flags; /* 0x010018 polarity of vt signals */
+ volatile u32 vt_f2rf_lock; /* 0x01001c f2rf & framelck y coord */
+ volatile u32 vt_intr01; /* 0x010020 intr 0,1 y coords */
+ volatile u32 vt_intr23; /* 0x010024 intr 2,3 y coords */
+ volatile u32 fp_hdrv; /* 0x010028 flat panel hdrv on/off */
+ volatile u32 fp_vdrv; /* 0x01002c flat panel vdrv on/off */
+ volatile u32 fp_de; /* 0x010030 flat panel de on/off */
+ volatile u32 vt_hpixen; /* 0x010034 intrnl horiz pixel on/off*/
+ volatile u32 vt_vpixen; /* 0x010038 intrnl vert pixel on/off */
+ volatile u32 vt_hcmap; /* 0x01003c cmap write (horiz) */
+ volatile u32 vt_vcmap; /* 0x010040 cmap write (vert) */
+ volatile u32 did_start_xy; /* 0x010044 eol/f did/xy reset val */
+ volatile u32 crs_start_xy; /* 0x010048 eol/f crs/xy reset val */
+ volatile u32 vc_start_xy; /* 0x01004c eol/f vc/xy reset val */
+
+ char _pad1[ 0x020000 - 0x010050 ];
+
+ volatile u32 ovr_width_tile; /* 0x020000 overlay plane ctrl 0 */
+ volatile u32 ovr_inhwctrl; /* 0x020004 overlay plane ctrl 1 */
+ volatile u32 ovr_control; /* 0x020008 overlay plane ctrl 1 */
+
+ char _pad2[ 0x030000 - 0x02000C ];
+
+ volatile u32 frm_size_tile; /* 0x030000 normal plane ctrl 0 */
+ volatile u32 frm_size_pixel; /* 0x030004 normal plane ctrl 1 */
+ volatile u32 frm_inhwctrl; /* 0x030008 normal plane ctrl 2 */
+ volatile u32 frm_control; /* 0x03000C normal plane ctrl 3 */
+
+ char _pad3[ 0x040000 - 0x030010 ];
+
+ volatile u32 did_inhwctrl; /* 0x040000 DID control */
+ volatile u32 did_control; /* 0x040004 DID shadow */
+
+ char _pad4[ 0x048000 - 0x040008 ];
+
+ volatile u32 mode_regs[32]; /* 0x048000 - 0x04807c WID table */
+
+ char _pad5[ 0x050000 - 0x048080 ];
+
+ volatile u32 cmap[6144]; /* 0x050000 - 0x055ffc color map */
+
+ char _pad6[ 0x058000 - 0x056000 ];
+
+ volatile u32 cm_fifo; /* 0x058000 color map fifo status */
+
+ char _pad7[ 0x060000 - 0x058004 ];
+
+ volatile u32 gmap[256]; /* 0x060000 - 0x0603fc gamma map */
+
+ char _pad8[ 0x068000 - 0x060400 ];
+
+ volatile u32 gmap10[1024]; /* 0x068000 - 0x068ffc gamma map */
+
+ char _pad9[ 0x070000 - 0x069000 ];
+
+ volatile u32 crs_pos; /* 0x070000 cusror control 0 */
+ volatile u32 crs_ctl; /* 0x070004 cusror control 1 */
+ volatile u32 crs_cmap[3]; /* 0x070008 - 0x070010 crs cmap */
+
+ char _pad10[ 0x078000 - 0x070014 ];
+
+ volatile u32 crs_glyph[64]; /* 0x078000 - 0x0780fc crs glyph */
+
+ char _pad11[ 0x080000 - 0x078100 ];
+
+ volatile u32 vc_0; /* 0x080000 video capture crtl 0 */
+ volatile u32 vc_1; /* 0x080004 video capture crtl 1 */
+ volatile u32 vc_2; /* 0x080008 video capture crtl 2 */
+ volatile u32 vc_3; /* 0x08000c video capture crtl 3 */
+ volatile u32 vc_4; /* 0x080010 video capture crtl 3 */
+ volatile u32 vc_5; /* 0x080014 video capture crtl 3 */
+ volatile u32 vc_6; /* 0x080018 video capture crtl 3 */
+ volatile u32 vc_7; /* 0x08001c video capture crtl 3 */
+ volatile u32 vc_8; /* 0x08000c video capture crtl 3 */
+} asregs;
+
+/* Bit mask information */
+
+#define DBE_CTRLSTAT_CHIPID_MSB 3
+#define DBE_CTRLSTAT_CHIPID_LSB 0
+#define DBE_CTRLSTAT_SENSE_N_MSB 4
+#define DBE_CTRLSTAT_SENSE_N_LSB 4
+#define DBE_CTRLSTAT_PCLKSEL_MSB 29
+#define DBE_CTRLSTAT_PCLKSEL_LSB 28
+
+#define DBE_DOTCLK_M_MSB 7
+#define DBE_DOTCLK_M_LSB 0
+#define DBE_DOTCLK_N_MSB 13
+#define DBE_DOTCLK_N_LSB 8
+#define DBE_DOTCLK_P_MSB 15
+#define DBE_DOTCLK_P_LSB 14
+#define DBE_DOTCLK_RUN_MSB 20
+#define DBE_DOTCLK_RUN_LSB 20
+
+#define DBE_VT_XY_VT_FREEZE_MSB 31
+#define DBE_VT_XY_VT_FREEZE_LSB 31
+
+#define DBE_VT_VSYNC_VT_VSYNC_ON_MSB 23
+#define DBE_VT_VSYNC_VT_VSYNC_ON_LSB 12
+#define DBE_VT_VSYNC_VT_VSYNC_OFF_MSB 11
+#define DBE_VT_VSYNC_VT_VSYNC_OFF_LSB 0
+
+#define DBE_VT_HSYNC_VT_HSYNC_ON_MSB 23
+#define DBE_VT_HSYNC_VT_HSYNC_ON_LSB 12
+#define DBE_VT_HSYNC_VT_HSYNC_OFF_MSB 11
+#define DBE_VT_HSYNC_VT_HSYNC_OFF_LSB 0
+
+#define DBE_VT_VBLANK_VT_VBLANK_ON_MSB 23
+#define DBE_VT_VBLANK_VT_VBLANK_ON_LSB 12
+#define DBE_VT_VBLANK_VT_VBLANK_OFF_MSB 11
+#define DBE_VT_VBLANK_VT_VBLANK_OFF_LSB 0
+
+#define DBE_VT_HBLANK_VT_HBLANK_ON_MSB 23
+#define DBE_VT_HBLANK_VT_HBLANK_ON_LSB 12
+#define DBE_VT_HBLANK_VT_HBLANK_OFF_MSB 11
+#define DBE_VT_HBLANK_VT_HBLANK_OFF_LSB 0
+
+#define DBE_VT_VCMAP_VT_VCMAP_ON_MSB 23
+#define DBE_VT_VCMAP_VT_VCMAP_ON_LSB 12
+#define DBE_VT_VCMAP_VT_VCMAP_OFF_MSB 11
+#define DBE_VT_VCMAP_VT_VCMAP_OFF_LSB 0
+
+#define DBE_VT_HCMAP_VT_HCMAP_ON_MSB 23
+#define DBE_VT_HCMAP_VT_HCMAP_ON_LSB 12
+#define DBE_VT_HCMAP_VT_HCMAP_OFF_MSB 11
+#define DBE_VT_HCMAP_VT_HCMAP_OFF_LSB 0
+
+#define DBE_VT_XYMAX_VT_MAXX_MSB 11
+#define DBE_VT_XYMAX_VT_MAXX_LSB 0
+#define DBE_VT_XYMAX_VT_MAXY_MSB 23
+#define DBE_VT_XYMAX_VT_MAXY_LSB 12
+
+#define DBE_VT_HPIXEN_VT_HPIXEN_ON_MSB 23
+#define DBE_VT_HPIXEN_VT_HPIXEN_ON_LSB 12
+#define DBE_VT_HPIXEN_VT_HPIXEN_OFF_MSB 11
+#define DBE_VT_HPIXEN_VT_HPIXEN_OFF_LSB 0
+
+#define DBE_VT_VPIXEN_VT_VPIXEN_ON_MSB 23
+#define DBE_VT_VPIXEN_VT_VPIXEN_ON_LSB 12
+#define DBE_VT_VPIXEN_VT_VPIXEN_OFF_MSB 11
+#define DBE_VT_VPIXEN_VT_VPIXEN_OFF_LSB 0
+
+#define DBE_OVR_CONTROL_OVR_DMA_ENABLE_MSB 0
+#define DBE_OVR_CONTROL_OVR_DMA_ENABLE_LSB 0
+
+#define DBE_OVR_INHWCTRL_OVR_DMA_ENABLE_MSB 0
+#define DBE_OVR_INHWCTRL_OVR_DMA_ENABLE_LSB 0
+
+#define DBE_OVR_WIDTH_TILE_OVR_FIFO_RESET_MSB 13
+#define DBE_OVR_WIDTH_TILE_OVR_FIFO_RESET_LSB 13
+
+#define DBE_FRM_CONTROL_FRM_DMA_ENABLE_MSB 0
+#define DBE_FRM_CONTROL_FRM_DMA_ENABLE_LSB 0
+#define DBE_FRM_CONTROL_FRM_TILE_PTR_MSB 31
+#define DBE_FRM_CONTROL_FRM_TILE_PTR_LSB 9
+#define DBE_FRM_CONTROL_FRM_LINEAR_MSB 1
+#define DBE_FRM_CONTROL_FRM_LINEAR_LSB 1
+
+#define DBE_FRM_INHWCTRL_FRM_DMA_ENABLE_MSB 0
+#define DBE_FRM_INHWCTRL_FRM_DMA_ENABLE_LSB 0
+
+#define DBE_FRM_SIZE_TILE_FRM_WIDTH_TILE_MSB 12
+#define DBE_FRM_SIZE_TILE_FRM_WIDTH_TILE_LSB 5
+#define DBE_FRM_SIZE_TILE_FRM_RHS_MSB 4
+#define DBE_FRM_SIZE_TILE_FRM_RHS_LSB 0
+#define DBE_FRM_SIZE_TILE_FRM_DEPTH_MSB 14
+#define DBE_FRM_SIZE_TILE_FRM_DEPTH_LSB 13
+#define DBE_FRM_SIZE_TILE_FRM_FIFO_RESET_MSB 15
+#define DBE_FRM_SIZE_TILE_FRM_FIFO_RESET_LSB 15
+
+#define DBE_FRM_SIZE_PIXEL_FB_HEIGHT_PIX_MSB 31
+#define DBE_FRM_SIZE_PIXEL_FB_HEIGHT_PIX_LSB 16
+
+#define DBE_DID_CONTROL_DID_DMA_ENABLE_MSB 0
+#define DBE_DID_CONTROL_DID_DMA_ENABLE_LSB 0
+#define DBE_DID_INHWCTRL_DID_DMA_ENABLE_MSB 0
+#define DBE_DID_INHWCTRL_DID_DMA_ENABLE_LSB 0
+
+#define DBE_DID_START_XY_DID_STARTY_MSB 23
+#define DBE_DID_START_XY_DID_STARTY_LSB 12
+#define DBE_DID_START_XY_DID_STARTX_MSB 11
+#define DBE_DID_START_XY_DID_STARTX_LSB 0
+
+#define DBE_CRS_START_XY_CRS_STARTY_MSB 23
+#define DBE_CRS_START_XY_CRS_STARTY_LSB 12
+#define DBE_CRS_START_XY_CRS_STARTX_MSB 11
+#define DBE_CRS_START_XY_CRS_STARTX_LSB 0
+
+#define DBE_WID_TYP_MSB 4
+#define DBE_WID_TYP_LSB 2
+#define DBE_WID_BUF_MSB 1
+#define DBE_WID_BUF_LSB 0
+
+#define DBE_VC_START_XY_VC_STARTY_MSB 23
+#define DBE_VC_START_XY_VC_STARTY_LSB 12
+#define DBE_VC_START_XY_VC_STARTX_MSB 11
+#define DBE_VC_START_XY_VC_STARTX_LSB 0
+
+/* Constants */
+
+#define DBE_FRM_DEPTH_8 0
+#define DBE_FRM_DEPTH_16 1
+#define DBE_FRM_DEPTH_32 2
+
+#define DBE_CMODE_I8 0
+#define DBE_CMODE_I12 1
+#define DBE_CMODE_RG3B2 2
+#define DBE_CMODE_RGB4 3
+#define DBE_CMODE_ARGB5 4
+#define DBE_CMODE_RGB8 5
+#define DBE_CMODE_RGBA5 6
+#define DBE_CMODE_RGB10 7
+
+#define DBE_BMODE_BOTH 3
+
+#define DBE_CRS_MAGIC 54
+
+/* Config Register (DBE Only) Definitions */
+
+#define DBE_CONFIG_VDAC_ENABLE 0x00000001
+#define DBE_CONFIG_VDAC_GSYNC 0x00000002
+#define DBE_CONFIG_VDAC_PBLANK 0x00000004
+#define DBE_CONFIG_FPENABLE 0x00000008
+#define DBE_CONFIG_LENDIAN 0x00000020
+#define DBE_CONFIG_TILEHIST 0x00000040
+#define DBE_CONFIG_EXT_ADDR 0x00000080
+
+#define DBE_CONFIG_FBDEV ( DBE_CONFIG_VDAC_ENABLE | \
+ DBE_CONFIG_VDAC_GSYNC | \
+ DBE_CONFIG_VDAC_PBLANK | \
+ DBE_CONFIG_LENDIAN | \
+ DBE_CONFIG_EXT_ADDR )
+
+/*
+ * Available Video Timings and Corresponding Indices
+ */
+
+typedef enum {
+ DBE_VT_640_480_60,
+
+ DBE_VT_800_600_60,
+ DBE_VT_800_600_75,
+ DBE_VT_800_600_120,
+
+ DBE_VT_1024_768_50,
+ DBE_VT_1024_768_60,
+ DBE_VT_1024_768_75,
+ DBE_VT_1024_768_85,
+ DBE_VT_1024_768_120,
+
+ DBE_VT_1280_1024_50,
+ DBE_VT_1280_1024_60,
+ DBE_VT_1280_1024_75,
+ DBE_VT_1280_1024_85,
+
+ DBE_VT_1600_1024_53,
+ DBE_VT_1600_1024_60,
+
+ DBE_VT_1600_1200_50,
+ DBE_VT_1600_1200_60,
+ DBE_VT_1600_1200_75,
+
+ DBE_VT_1920_1080_50,
+ DBE_VT_1920_1080_60,
+ DBE_VT_1920_1080_72,
+
+ DBE_VT_1920_1200_50,
+ DBE_VT_1920_1200_60,
+ DBE_VT_1920_1200_66,
+
+ DBE_VT_UNKNOWN
+} dbe_timing_t;
+
+
+
+/*
+ * Crime Video Timing Data Structure
+ */
+
+typedef struct dbe_timing_info
+{
+ dbe_timing_t type;
+ int flags;
+ short width; /* Monitor resolution */
+ short height;
+ int fields_sec; /* fields/sec (Hz -3 dec. places */
+ int cfreq; /* pixel clock frequency (MHz -3 dec. places) */
+ short htotal; /* Horizontal total pixels */
+ short hblank_start; /* Horizontal blank start */
+ short hblank_end; /* Horizontal blank end */
+ short hsync_start; /* Horizontal sync start */
+ short hsync_end; /* Horizontal sync end */
+ short vtotal; /* Vertical total lines */
+ short vblank_start; /* Vertical blank start */
+ short vblank_end; /* Vertical blank end */
+ short vsync_start; /* Vertical sync start */
+ short vsync_end; /* Vertical sync end */
+ short pll_m; /* PLL M parameter */
+ short pll_n; /* PLL P parameter */
+ short pll_p; /* PLL N parameter */
+} dbe_timing_info_t;
+
+/* Defines for dbe_vof_info_t flags */
+
+#define DBE_VOF_UNKNOWNMON 1
+#define DBE_VOF_STEREO 2
+#define DBE_VOF_DO_GENSYNC 4 /* enable incoming sync */
+#define DBE_VOF_SYNC_ON_GREEN 8 /* sync on green */
+#define DBE_VOF_FLATPANEL 0x1000 /* FLATPANEL Timing */
+#define DBE_VOF_MAGICKEY 0x2000 /* Backdoor key */
+
+/*
+ * DBE Timing Tables
+ */
+
+#ifdef INCLUDE_TIMING_TABLE_DATA
+struct dbe_timing_info dbeVTimings[] = {
+ {
+ DBE_VT_640_480_60,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 640, 480, 59940, 25175,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 800, 640, 800, 656, 752,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 525, 480, 525, 490, 492,
+ /* pll_m, pll_n, pll_p */
+ 15, 2, 3
+ },
+
+ {
+ DBE_VT_800_600_60,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 800, 600, 60317, 40000,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 1056, 800, 1056, 840, 968,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 628, 600, 628, 601, 605,
+ /* pll_m, pll_n, pll_p */
+ 3, 1, 1
+ },
+
+ {
+ DBE_VT_800_600_75,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 800, 600, 75000, 49500,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 1056, 800, 1056, 816, 896,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 625, 600, 625, 601, 604,
+ /* pll_m, pll_n, pll_p */
+ 11, 3, 1
+ },
+
+ {
+ DBE_VT_800_600_120,
+ /* flags, width, height, fields_sec, cfreq */
+ DBE_VOF_STEREO, 800, 600, 119800, 82978,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 1040, 800, 1040, 856, 976,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 666, 600, 666, 637, 643,
+ /* pll_m, pll_n, pll_p */
+ 31, 5, 1
+ },
+
+ {
+ DBE_VT_1024_768_50,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1024, 768, 50000, 54163,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 1344, 1024, 1344, 1048, 1184,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 806, 768, 806, 771, 777,
+ /* pll_m, pll_n, pll_p */
+ 4, 1, 1
+ },
+
+ {
+ DBE_VT_1024_768_60,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1024, 768, 60004, 65000,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 1344, 1024, 1344, 1048, 1184,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 806, 768, 806, 771, 777,
+ /* pll_m, pll_n, pll_p */
+ 12, 5, 0
+ },
+
+ {
+ DBE_VT_1024_768_75,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1024, 768, 75029, 78750,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 1312, 1024, 1312, 1040, 1136,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 800, 768, 800, 769, 772,
+ /* pll_m, pll_n, pll_p */
+ 29, 5, 1
+ },
+
+ {
+ DBE_VT_1024_768_85,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1024, 768, 84997, 94500,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 1376, 1024, 1376, 1072, 1168,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 808, 768, 808, 769, 772,
+ /* pll_m, pll_n, pll_p */
+ 7, 2, 0
+ },
+
+ {
+ DBE_VT_1024_768_120,
+ /* flags, width, height, fields_sec, cfreq */
+ DBE_VOF_STEREO, 1024, 768, 119800, 133195,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 1376, 1024, 1376, 1072, 1168,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 808, 768, 808, 769, 772,
+ /* pll_m, pll_n, pll_p */
+ 5, 1, 0
+ },
+
+ {
+ DBE_VT_1280_1024_50,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1280, 1024, 50000, 89460,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 1680, 1280, 1680, 1360, 1480,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 1065, 1024, 1065, 1027, 1030,
+ /* pll_m, pll_n, pll_p */
+ 10, 3, 0
+ },
+
+ {
+ DBE_VT_1280_1024_60,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1280, 1024, 60020, 108000,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 1688, 1280, 1688, 1328, 1440,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 1066, 1024, 1066, 1025, 1028,
+ /* pll_m, pll_n, pll_p */
+ 4, 1, 0
+ },
+
+ {
+ DBE_VT_1280_1024_75,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1280, 1024, 75025, 135000,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 1688, 1280, 1688, 1296, 1440,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 1066, 1024, 1066, 1025, 1028,
+ /* pll_m, pll_n, pll_p */
+ 5, 1, 0
+ },
+
+ {
+ DBE_VT_1280_1024_85,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1280, 1024, 85024, 157500,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 1728, 1280, 1728, 1344, 1504,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 1072, 1024, 1072, 1025, 1028,
+ /* pll_m, pll_n, pll_p */
+ 29, 5, 0
+ },
+
+ {
+ DBE_VT_1600_1024_53,
+ /* flags, width, height, fields_sec, cfreq */
+ DBE_VOF_FLATPANEL | DBE_VOF_MAGICKEY,
+ 1600, 1024, 53000, 107447,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 1900, 1600, 1900, 1630, 1730,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 1067, 1024, 1067, 1027, 1030,
+ /* pll_m, pll_n, pll_p */
+ 4, 1, 0
+ },
+
+ {
+ DBE_VT_1600_1024_60,
+ /* flags, width, height, fields_sec, cfreq */
+ DBE_VOF_FLATPANEL, 1600, 1024, 60000, 106913,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 1670, 1600, 1670, 1630, 1650,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 1067, 1024, 1067, 1027, 1030,
+ /* pll_m, pll_n, pll_p */
+ 4, 1, 0
+ },
+
+ {
+ DBE_VT_1600_1200_50,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1600, 1200, 50000, 130500,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 2088, 1600, 2088, 1644, 1764,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 1250, 1200, 1250, 1205, 1211,
+ /* pll_m, pll_n, pll_p */
+ 24, 5, 0
+ },
+
+ {
+ DBE_VT_1600_1200_60,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1600, 1200, 59940, 162000,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 2160, 1600, 2160, 1644, 1856,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 1250, 1200, 1250, 1201, 1204,
+ /* pll_m, pll_n, pll_p */
+ 6, 1, 0
+ },
+
+ {
+ DBE_VT_1600_1200_75,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1600, 1200, 75000, 202500,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 2160, 1600, 2160, 1644, 1856,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 1250, 1200, 1250, 1201, 1204,
+ /* pll_m, pll_n, pll_p */
+ 15, 2, 0
+ },
+
+ {
+ DBE_VT_1920_1080_50,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1920, 1080, 50000, 133200,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 2368, 1920, 2368, 1952, 2096,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 1125, 1080, 1125, 1083, 1086,
+ /* pll_m, pll_n, pll_p */
+ 5, 1, 0
+ },
+
+ {
+ DBE_VT_1920_1080_60,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1920, 1080, 59940, 159840,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 2368, 1920, 2368, 1952, 2096,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 1125, 1080, 1125, 1083, 1086,
+ /* pll_m, pll_n, pll_p */
+ 6, 1, 0
+ },
+
+ {
+ DBE_VT_1920_1080_72,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1920, 1080, 72000, 216023,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 2560, 1920, 2560, 1968, 2184,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 1172, 1080, 1172, 1083, 1086,
+ /* pll_m, pll_n, pll_p */
+ 8, 1, 0
+ },
+
+ {
+ DBE_VT_1920_1200_50,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1920, 1200, 50000, 161500,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 2584, 1920, 2584, 1984, 2240,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 1250, 1200, 1250, 1203, 1206,
+ /* pll_m, pll_n, pll_p */
+ 6, 1, 0
+ },
+
+ {
+ DBE_VT_1920_1200_60,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1920, 1200, 59940, 193800,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 2584, 1920, 2584, 1984, 2240,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 1250, 1200, 1250, 1203, 1206,
+ /* pll_m, pll_n, pll_p */
+ 29, 4, 0
+ },
+
+ {
+ DBE_VT_1920_1200_66,
+ /* flags, width, height, fields_sec, cfreq */
+ 0, 1920, 1200, 66000, 213180,
+ /* htotal, hblank_start, hblank_end, hsync_start, hsync_end */
+ 2584, 1920, 2584, 1984, 2240,
+ /* vtotal, vblank_start, vblank_end, vsync_start, vsync_end */
+ 1250, 1200, 1250, 1203, 1206,
+ /* pll_m, pll_n, pll_p */
+ 8, 1, 0
+ }
+};
+
+#define DBE_VT_SIZE (sizeof(dbeVTimings)/sizeof(dbeVTimings[0]))
+#endif // INCLUDE_TIMING_TABLE_DATA
+
+#endif // ! __SGIVWFB_H__
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index a99a3a0cd..59a2da716 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -240,12 +240,11 @@ static int xxx_blank(int blank_mode, const struct fb_info *info)
return 0;
}
-static void xxx_set_dispsw(const void *par, struct display *disp,
- struct fb_info_gen *info)
+static void xxx_set_disp(const void *par, struct display *disp,
+ struct fb_info_gen *info)
{
- unsigned long flags;
-
/*
+ * 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
@@ -253,7 +252,7 @@ static void xxx_set_dispsw(const void *par, struct display *disp,
* If you don't have any appropriate operations, you must fill in a
* pointer to dummy operations, and there will be no text output.
*/
- save_flags(flags); cli();
+ disp->screen_base = virtual_frame_buffer_address;
#ifdef FBCON_HAS_CFB8
if (is_cfb8) {
disp->dispsw = fbcon_cfb8;
@@ -278,7 +277,6 @@ static void xxx_set_dispsw(const void *par, struct display *disp,
} else
#endif
disp->dispsw = &fbcon_dummy;
- restore_flags(flags);
}
diff --git a/drivers/video/tcxfb.c b/drivers/video/tcxfb.c
index 90d6152fa..8e9d2fc41 100644
--- a/drivers/video/tcxfb.c
+++ b/drivers/video/tcxfb.c
@@ -1,4 +1,4 @@
-/* $Id: tcxfb.c,v 1.6 1998/09/04 15:43:46 jj Exp $
+/* $Id: tcxfb.c,v 1.7 1999/01/26 10:55:03 jj Exp $
* tcxfb.c: TCX 24/8bit frame buffer driver
*
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -228,6 +228,7 @@ __initfunc(char *tcxfb_init(struct fb_info_sbusfb *fb))
strcpy(fix->id, "TCX24");
}
fix->line_length = fb->var.xres_virtual;
+ fix->accel = FB_ACCEL_SUN_TCX;
disp->scrollmode = SCROLL_YREDRAW;
if (!disp->screen_base)
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index cbad38a82..78af83ef0 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -21,7 +21,6 @@
#include <linux/selection.h>
#include <linux/ioport.h>
#include <linux/init.h>
-#include <linux/config.h>
#include <asm/io.h>
#include <asm/mtrr.h>
@@ -93,6 +92,7 @@ static union {
} fbcon_cmap;
static int inverse = 0;
+static int mtrr = 0;
static int currcon = 0;
static int pmi_setpal = 0; /* pmi for palette changes ??? */
@@ -254,6 +254,7 @@ static void vesafb_set_disp(int con)
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 ||
@@ -262,8 +263,13 @@ static int vesafb_set_var(struct fb_var_screeninfo *var, int con,
var->yres_virtual < video_height ||
var->xoffset ||
var->bits_per_pixel != vesafb_defined.bits_per_pixel ||
- var->nonstd)
+ var->nonstd) {
+ if (first) {
+ printk("Vesafb does not support changing the video mode\n");
+ first = 0;
+ }
return -EINVAL;
+ }
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
return 0;
@@ -489,6 +495,8 @@ void vesafb_setup(char *options, int *ints)
pmi_setpal=0;
else if (! strcmp(this_opt, "pmipal"))
pmi_setpal=1;
+ else if (! strcmp(this_opt, "mtrr"))
+ mtrr=1;
else if (!strncmp(this_opt, "font:", 5))
strcpy(fb_info.fontname, this_opt+5);
}
@@ -626,9 +634,8 @@ __initfunc(void vesafb_init(void))
video_cmap_len = 256;
}
request_region(0x3c0, 32, "vga+");
-#ifdef CONFIG_MTRR
- mtrr_add((unsigned long)video_base, video_size, MTRR_TYPE_WRCOMB, 1);
-#endif
+ if (mtrr)
+ mtrr_add((unsigned long)video_base, video_size, MTRR_TYPE_WRCOMB, 1);
strcpy(fb_info.modename, "VESA VGA");
fb_info.changevar = NULL;
diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c
index ba4bf5ea0..a19c1c9e5 100644
--- a/drivers/video/virgefb.c
+++ b/drivers/video/virgefb.c
@@ -89,11 +89,6 @@
#define rl_3d(reg) \
(*((unsigned long volatile *)(CyberRegs + reg)))
-
-
-
-
-
struct virgefb_par {
int xres;
int yres;
@@ -109,6 +104,11 @@ static int currcon = 0;
static struct display disp;
static struct fb_info fb_info;
+static union {
+#ifdef FBCON_HAS_CFB16
+ u16 cfb16[16];
+#endif
+} fbcon_cmap;
/*
* Switch for Chipset Independency
@@ -132,6 +132,7 @@ static struct fb_hwswitch {
void (*blank)(int blank);
} *fbhw;
+static int blit_maybe_busy = 0;
/*
* Frame Buffer Name
@@ -148,7 +149,7 @@ static char virgefb_name[16] = "Cybervision/3D";
#define VIRGE8_HEIGHT 886
#define VIRGE8_PIXCLOCK 12500 /* ++Geert: Just a guess */
-#if 0
+#if 1
#define VIRGE16_WIDTH 800
#define VIRGE16_HEIGHT 600
#endif
@@ -167,6 +168,8 @@ static unsigned long Cyber_register_base;
static unsigned long Cyber_vcode_switch_base;
static unsigned char cv3d_on_zorro2;
+#define CYBMEM_OFFSET_8 0x800000 /* offsets from start of video - */
+#define CYBMEM_OFFSET_16 0x400000 /* ram to appropriate aperture */
/*
* Predefined Video Modes
@@ -216,10 +219,17 @@ static struct fb_videomode virgefb_predefined[] __initdata = {
FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
}
}, {
+ "640x480-16", { /* Cybervision 16 bpp */
+ 640, 480, 640, 480, 0, 0, 16, 0,
+ {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+ FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ }
+ }, {
"800x600-16", { /* Cybervision 16 bpp */
800, 600, 800, 600, 0, 0, 16, 0,
{11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+ 0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
}
}, {
@@ -229,6 +239,27 @@ static struct fb_videomode virgefb_predefined[] __initdata = {
0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
}
+ }, {
+ "1152x886-16", { /* Cybervision 16 bpp */
+ 1152, 886, 1152, 886, 0, 0, 16, 0,
+ {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
+ 0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+ FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ }
+ }, {
+ "1280x1024-16", { /* Cybervision 16 bpp */
+ 1280, 1024, 1280, 1024, 0, 0, 16, 0,
+ {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
+ 0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+ FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ }
+ }, {
+ "1600x1200-16", { /* Cybervision 16 bpp */
+ 1600, 1200, 1600, 1200, 0, 0, 16, 0,
+ {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
+ 0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+ FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ }
}
};
@@ -246,8 +277,8 @@ static int Cyberfb_Cyber16 = 0; /* Use Cybervision board */
* Some default modes
*/
-#define VIRGE8_DEFMODE (0)
-#define VIRGE16_DEFMODE (6)
+#define VIRGE8_DEFMODE (1)
+#define VIRGE16_DEFMODE (7)
static struct fb_var_screeninfo virgefb_default;
@@ -294,6 +325,9 @@ static void Cyberfb_blank(int blank, struct fb_info *info);
static struct display_switch fbcon_virge8;
#endif
+#ifdef FBCON_HAS_CFB16
+static struct display_switch fbcon_virge16;
+#endif
/*
* Hardware Specific Routines
@@ -353,15 +387,14 @@ static int Cyber_init(void)
* (the 3D penguin might need texture memory :-) )
*/
- memset ((char*)CyberMem, 0, 1600 * 1200);
-
- /* Disable hardware cursor */
if (cv3d_on_zorro2) {
CyberSize = 0x00380000; /* 3.5 MB , we need some space for the registers? */
} else {
CyberSize = 0x00400000; /* 4 MB */
}
+ memset ((char*)CyberMem, 0, CyberSize);
+ /* Disable hardware cursor */
vgawb_3d(0x3c8, 255);
vgawb_3d(0x3c9, 56);
vgawb_3d(0x3c9, 100);
@@ -396,7 +429,18 @@ static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, virgefb_name);
- fix->smem_start = (char*) CyberMem_phys;
+ if (cv3d_on_zorro2) {
+ fix->smem_start = (char*) CyberMem_phys;
+ } else {
+ switch (par->bpp) {
+ case 8:
+ fix->smem_start = (char*) (CyberMem_phys + CYBMEM_OFFSET_8);
+ break;
+ case 16:
+ fix->smem_start = (char*) (CyberMem_phys + CYBMEM_OFFSET_16);
+ break;
+ }
+ }
fix->smem_len = CyberSize;
fix->mmio_start = (char*) CyberRegs_phys;
fix->mmio_len = 0x10000; /* TODO: verify this for the CV64/3D */
@@ -467,24 +511,27 @@ static int Cyber_encode_var(struct fb_var_screeninfo *var,
var->bits_per_pixel = par->bpp;
var->grayscale = 0;
- if (par->bpp == 8) {
- var->red.offset = 0;
- var->red.length = 6;
- var->red.msb_right = 0;
- var->blue = var->green = var->red;
- } else {
- var->red.offset = 11;
- var->red.length = 5;
- var->red.msb_right = 0;
- var->green.offset = 5;
- var->green.length = 6;
- var->green.msb_right = 0;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->blue.msb_right = 0;
+ switch (var->bits_per_pixel) {
+ case 8: /* CLUT */
+ var->red.offset = 0;
+ var->red.length = 6;
+ var->red.msb_right = 0;
+ var->blue = var->green = var->red;
+ 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->transp.offset = 0;
- var->transp.length = 0;
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
var->transp.msb_right = 0;
var->nonstd = 0;
@@ -493,8 +540,10 @@ static int Cyber_encode_var(struct fb_var_screeninfo *var,
var->height = -1;
var->width = -1;
- var->accel_flags = (par->accel && par->bpp == 8) ? FB_ACCELF_TEXT : 0;
- DPRINTK("accel CV64/3D\n");
+ var->accel_flags = (par->accel &&
+ ((par->bpp == 8) || (par->bpp == 16))) ? FB_ACCELF_TEXT : 0;
+
+/* printk("CV64/3D : %s\n",(var->accel_flags ? "accel" : "no accel")); */
var->vmode = FB_VMODE_NONINTERLACED;
@@ -525,28 +574,34 @@ static int Cyber_encode_var(struct fb_var_screeninfo *var,
static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
- if (regno > 255)
- {
- return (1);
+ if (((current_par.bpp==8) && (regno>255)) ||
+ ((current_par.bpp!=8) && (regno>15)))
+ return (1);
+
+ if (((current_par.bpp==8) && (regno<256)) || ((current_par.bpp==16) &&(regno<16))) {
+ Cyber_colour_table [regno][0] = red >> 10;
+ Cyber_colour_table [regno][1] = green >> 10;
+ Cyber_colour_table [regno][2] = blue >> 10;
}
- /*
- * No colors on the CV3D yet.
- */
-
- vgawb_3d(0x3c8, (unsigned char) regno);
- red >>= 10;
- green >>= 10;
- blue >>= 10;
-
- Cyber_colour_table [regno][0] = red;
- Cyber_colour_table [regno][1] = green;
- Cyber_colour_table [regno][2] = blue;
-
- vgawb_3d(0x3c9, red);
- vgawb_3d(0x3c9, green);
- vgawb_3d(0x3c9, blue);
-
+ switch (current_par.bpp) {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ vgawb_3d(0x3c8, (unsigned char) regno);
+ vgawb_3d(0x3c9, ((unsigned char) (red >> 10)));
+ vgawb_3d(0x3c9, ((unsigned char) (green >> 10)));
+ vgawb_3d(0x3c9, ((unsigned char) (blue >> 10)));
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ fbcon_cmap.cfb16[regno] =
+ ((red & 0xf800) |
+ ((green & 0xfc00) >> 5) |
+ ((blue & 0xf800) >> 11));
+ break;
+#endif
+ }
return (0);
}
@@ -561,14 +616,18 @@ static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
{
int t;
- if (regno >= 256)
+ if (regno > 255)
return (1);
- t = Cyber_colour_table [regno][0];
- *red = (t<<10) | (t<<4) | (t>>2);
- t = Cyber_colour_table [regno][1];
- *green = (t<<10) | (t<<4) | (t>>2);
- t = Cyber_colour_table [regno][2];
- *blue = (t<<10) | (t<<4) | (t>>2);
+
+ if (((current_par.bpp==8) && (regno<256)) || ((current_par.bpp==16) && (regno<16))) {
+
+ t = Cyber_colour_table [regno][0];
+ *red = (t<<10) | (t<<4) | (t>>2);
+ t = Cyber_colour_table [regno][1];
+ *green = (t<<10) | (t<<4) | (t>>2);
+ t = Cyber_colour_table [regno][2];
+ *blue = (t<<10) | (t<<4) | (t>>2);
+ }
*transp = 0;
return (0);
}
@@ -615,8 +674,10 @@ static inline void Cyber3D_WaitBusy(void)
unsigned long status;
do {
+ mb();
status = rl_3d(0x8504);
} while (!(status & (1 << 13)));
+ blit_maybe_busy = 0;
}
#define S3V_BITBLT (0x0 << 27)
@@ -666,6 +727,10 @@ static void Cyber3D_BitBLT(u_short curx, u_short cury, u_short destx,
desty += (height - 1);
}
+ if (blit_maybe_busy)
+ Cyber3D_WaitBusy();
+ blit_maybe_busy = 1;
+
wl_3d(0xa4f4, 1); /* pattern fb color */
wl_3d(0xa4e8, ~0); /* mono pat 0 */
@@ -676,8 +741,6 @@ static void Cyber3D_BitBLT(u_short curx, u_short cury, u_short destx,
wl_3d(0xa50c, ((destx << 16) | desty)); /* rdest_xy */
wl_3d(0xa500, blitcmd); /* GO! */
-
- Cyber3D_WaitBusy();
}
/*
@@ -691,6 +754,10 @@ static void Cyber3D_RectFill(u_short x, u_short y, u_short width,
unsigned int blitcmd = S3V_RECTFILL | S3V_DRAW | S3V_DST_8BPP |
S3V_BLT_CLEAR | S3V_MONO_PAT | (1 << 26) | (1 << 25);
+ if (blit_maybe_busy)
+ Cyber3D_WaitBusy();
+ blit_maybe_busy = 1;
+
tmp = color & 0xff;
wl_3d(0xa4f4, tmp);
@@ -698,19 +765,20 @@ static void Cyber3D_RectFill(u_short x, u_short y, u_short width,
wl_3d(0xa50c, ((x << 16) | y)); /* rdest_xy */
wl_3d(0xa500, blitcmd); /* GO! */
- Cyber3D_WaitBusy();
}
/**************************************************************
* Move cursor to x, y
*/
+
+#if 0
static void Cyber_MoveCursor (u_short x, u_short y)
{
printk("Yuck .... MoveCursor on a 3D\n");
return;
}
-
+#endif
/* -------------------- Interfaces to hardware functions -------------------- */
@@ -868,7 +936,18 @@ static void virgefb_set_disp(int con, struct fb_info *info)
virgefb_get_fix(&fix, con, info);
if (con == -1)
con = 0;
- display->screen_base = (char*) CyberMem;
+ if (cv3d_on_zorro2) {
+ display->screen_base = (char*) CyberMem;
+ } else {
+ switch (display->var.bits_per_pixel) {
+ case 8:
+ display->screen_base = (char*) (CyberMem + CYBMEM_OFFSET_8);
+ break;
+ case 16:
+ display->screen_base = (char*) (CyberMem + CYBMEM_OFFSET_16);
+ break;
+ }
+ }
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
@@ -878,22 +957,26 @@ static void virgefb_set_disp(int con, struct fb_info *info)
display->inverse = Cyberfb_inverse;
switch (display->var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
- case 8:
- if (display->var.accel_flags & FB_ACCELF_TEXT) {
- display->dispsw = &fbcon_virge8;
+ case 8:
+ if (display->var.accel_flags & FB_ACCELF_TEXT) {
+ display->dispsw = &fbcon_virge8;
#warning FIXME: We should reinit the graphics engine here
- } else
- display->dispsw = &fbcon_virge8;
- break;
+ } else
+ display->dispsw = &fbcon_cfb8;
+ break;
#endif
#ifdef FBCON_HAS_CFB16
- case 16:
- display->dispsw = &fbcon_cfb16;
- break;
+ case 16:
+ if (display->var.accel_flags & FB_ACCELF_TEXT) {
+ display->dispsw = &fbcon_virge16;
+ } else
+ display->dispsw = &fbcon_cfb16;
+ display->dispsw_data = &fbcon_cmap.cfb16;
+ break;
#endif
- default:
- display->dispsw = &fbcon_dummy;
- break;
+ default:
+ display->dispsw = &fbcon_dummy;
+ break;
}
}
@@ -962,7 +1045,7 @@ static int virgefb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
if (!fb_display[con].cmap.len) { /* no colormap allocated? */
if ((err = fb_alloc_cmap(&fb_display[con].cmap,
- 1<<fb_display[con].var.bits_per_pixel, 0)))
+ 1<<fb_display[con].var.bits_per_pixel, 0)))
return(err);
}
if (con == currcon) /* current console? */
@@ -987,8 +1070,8 @@ static int virgefb_pan_display(struct fb_var_screeninfo *var, int con,
/*
- * Cybervision Frame Buffer Specific ioctls
- */
+ * Cybervision Frame Buffer Specific ioctls
+ */
static int virgefb_ioctl(struct inode *inode, struct file *file,
u_int cmd, u_long arg, int con, struct fb_info *info)
@@ -1073,12 +1156,12 @@ __initfunc(void virgefb_init(void))
}
else
{
- CyberVGARegs = ioremap(board_addr +0x0c000000, 0x00010000);
+ CyberVGARegs = (unsigned long)ioremap(board_addr +0x0c000000, 0x00010000);
CyberRegs_phys = board_addr + 0x05000000;
- CyberMem_phys = board_addr + 0x04800000;
+ CyberMem_phys = board_addr + 0x04000000; /* was 0x04800000 */
CyberRegs = ioremap(CyberRegs_phys, 0x00010000);
- CyberMem = ioremap(CyberMem_phys, 0x00400000);
+ CyberMem = (unsigned long)ioremap(CyberMem_phys, 0x01000000); /* was 0x00400000 */
cv3d_on_zorro2 = 0;
printk("CV3D detected running in Z3 mode\n");
}
@@ -1146,8 +1229,8 @@ static int Cyberfb_updatevar(int con, struct fb_info *info)
/*
- * Blank the display.
- */
+ * Blank the display.
+ */
static void Cyberfb_blank(int blank, struct fb_info *info)
{
@@ -1201,13 +1284,103 @@ static void fbcon_virge8_clear(struct vc_data *conp, struct display *p, int sy,
(u_short)bg);
}
+static void fbcon_virge8_putc(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx)
+{
+ if (blit_maybe_busy)
+ Cyber3D_WaitBusy();
+ fbcon_cfb8_putc(conp, p, c, yy, xx);
+}
+
+static void fbcon_virge8_putcs(struct vc_data *conp, struct display *p,
+ const unsigned short *s, int count, int yy, int xx)
+{
+ if (blit_maybe_busy)
+ Cyber3D_WaitBusy();
+ fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
+}
+
+static void fbcon_virge8_revc(struct display *p, int xx, int yy)
+{
+ if (blit_maybe_busy)
+ Cyber3D_WaitBusy();
+ fbcon_cfb8_revc(p, xx, yy);
+}
+
+static void fbcon_virge8_clear_margins(struct vc_data *conp, struct display *p,
+ int bottom_only)
+{
+ if (blit_maybe_busy)
+ Cyber3D_WaitBusy();
+ fbcon_cfb8_clear_margins(conp, p, bottom_only);
+}
+
static struct display_switch fbcon_virge8 = {
- fbcon_cfb8_setup, fbcon_virge8_bmove, fbcon_virge8_clear, fbcon_cfb8_putc,
- fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins,
- FONTWIDTH(8)
+ fbcon_cfb8_setup, fbcon_virge8_bmove, fbcon_virge8_clear, fbcon_virge8_putc,
+ fbcon_virge8_putcs, fbcon_virge8_revc, NULL, NULL, fbcon_virge8_clear_margins,
+ FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
#endif
+#ifdef FBCON_HAS_CFB16
+static void fbcon_virge16_bmove(struct display *p, int sy, int sx, int dy,
+ int dx, int height, int width)
+{
+ sx *= 16; dx *= 16; width *= 16;
+ Cyber3D_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
+ (u_short)(dy*fontheight(p)), (u_short)width,
+ (u_short)(height*fontheight(p)));
+}
+
+static void fbcon_virge16_clear(struct vc_data *conp, struct display *p, int sy,
+ int sx, int height, int width)
+{
+ unsigned char bg;
+
+ sx *= 16; width *= 16;
+ bg = attr_bgcol_ec(p,conp);
+ Cyber3D_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
+ (u_short)width, (u_short)(height*fontheight(p)),
+ (u_short)bg);
+}
+
+static void fbcon_virge16_putc(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx)
+{
+ if (blit_maybe_busy)
+ Cyber3D_WaitBusy();
+ fbcon_cfb16_putc(conp, p, c, yy, xx);
+}
+
+static void fbcon_virge16_putcs(struct vc_data *conp, struct display *p,
+ const unsigned short *s, int count, int yy, int xx)
+{
+ if (blit_maybe_busy)
+ Cyber3D_WaitBusy();
+ fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
+}
+
+static void fbcon_virge16_revc(struct display *p, int xx, int yy)
+{
+ if (blit_maybe_busy)
+ Cyber3D_WaitBusy();
+ fbcon_cfb16_revc(p, xx, yy);
+}
+
+static void fbcon_virge16_clear_margins(struct vc_data *conp, struct display *p,
+ int bottom_only)
+{
+ if (blit_maybe_busy)
+ Cyber3D_WaitBusy();
+ fbcon_cfb16_clear_margins(conp, p, bottom_only);
+}
+
+static struct display_switch fbcon_virge16 = {
+ fbcon_cfb16_setup, fbcon_virge16_bmove, fbcon_virge16_clear, fbcon_virge16_putc,
+ fbcon_virge16_putcs, fbcon_virge16_revc, NULL, NULL, fbcon_virge16_clear_margins,
+ FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
#ifdef MODULE
int init_module(void)