Commit 4737042c authored by James Simmons's avatar James Simmons

VGA text mode handling cleanup. Rusty's janitoral cleanups.

parent b4e5e606
......@@ -26,7 +26,6 @@
* for more details.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
......@@ -41,81 +40,28 @@
#include <asm/irq.h>
#include <asm/pgtable.h>
#include <linux/fb.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
#define arraysize(x) (sizeof(x)/sizeof(*(x)))
struct mc68328_fb_par {
int xres;
int yres;
int bpp;
};
static struct mc68328_fb_par current_par;
static int current_par_valid = 0;
static int currcon = 0;
static struct display disp[MAX_NR_CONSOLES];
static struct fb_info fb_info;
static int node; /* node of the /dev/fb?current file */
/*
* Switch for Chipset Independency
*/
static struct fb_hwswitch {
/* Initialisation */
int (*init)(void);
/* Display Control */
int (*encode_fix)(struct fb_fix_screeninfo *fix, struct mc68328_fb_par *par);
int (*decode_var)(struct fb_var_screeninfo *var, struct mc68328_fb_par *par);
int (*encode_var)(struct fb_var_screeninfo *var, struct mc68328_fb_par *par);
int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp);
int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue,
u_int transp);
void (*blank)(int blank);
} *fbhw;
/*
* Frame Buffer Name
*/
static char mc68328_fb_name[16] = "mc68328";
/*
* mc68328vision Graphics Board
*/
#define CYBER8_WIDTH 1152
#define CYBER8_HEIGHT 886
#define CYBER8_PIXCLOCK 12500 /* ++Geert: Just a guess */
#define CYBER8_PIXCLOCK 12500 /* ++Geert: Just a guess */
#define CYBER16_WIDTH 800
#define CYBER16_HEIGHT 600
#define CYBER16_PIXCLOCK 25000 /* ++Geert: Just a guess */
#define CYBER16_PIXCLOCK 25000 /* ++Geert: Just a guess */
#define PALM_WIDTH 160
#define PALM_HEIGHT 160
/*static int mc68328Key = 0;
static u_char mc68328_colour_table [256][4];*/
static unsigned long mc68328Mem;
static unsigned long mc68328Size;
/*
* Predefined Video Mode Names
......@@ -123,34 +69,37 @@ static unsigned long mc68328Size;
static char *mc68328_fb_modenames[] = {
/*
* Autodetect (Default) Video Mode
*/
/*
* Autodetect (Default) Video Mode
*/
"default",
"default",
/*
* Predefined Video Modes
*/
"Palm", /* Palm Pilot devices, 1.0 and higher */
"Palm Grey", /* Palm Pilot devices, 1.0 and higher */
/*
* Predefined Video Modes
*/
/*
* Dummy Video Modes
*/
"Palm", /* Palm Pilot devices, 1.0 and higher */
"Palm Grey", /* Palm Pilot devices, 1.0 and higher */
"dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
"dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
"dummy", "dummy", "dummy", "dummy",
/*
* Dummy Video Modes
*/
/*
* User Defined Video Modes
*
* This doesn't work yet!!
*/
"dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
"dummy",
"dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
"dummy",
"dummy", "dummy", "dummy", "dummy",
"user0", "user1", "user2", "user3", "user4", "user5", "user6", "user7"
/*
* User Defined Video Modes
*
* This doesn't work yet!!
*/
"user0", "user1", "user2", "user3", "user4", "user5", "user6",
"user7"
};
......@@ -160,68 +109,70 @@ static char *mc68328_fb_modenames[] = {
static struct fb_var_screeninfo mc68328_fb_predefined[] = {
/*
* Autodetect (Default) Video Mode
*/
{ 0, },
/*
* Predefined Video Modes
*/
{
/* Palm */
PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT,
0, 0,
1, -1,
{0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 0, 0},
0, 0,
-1, -1, /* phys height, width */
FB_ACCEL_NONE,
0, 0, 0, 0, 0, 0, 0, /* timing */
0, /* sync */
FB_VMODE_NONINTERLACED
},
{
/* Palm Grey */
PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT,
0, 0,
2, -1,
{0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0},
0, 0,
-1, -1, /* phys height, width */
FB_ACCEL_NONE,
0, 0, 0, 0, 0, 0, 0, /* timing */
0, /* sync */
FB_VMODE_NONINTERLACED
},
/*
* Dummy Video Modes
*/
{ 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
{ 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
{ 0, }, { 0, },
/*
* User Defined Video Modes
*/
{ 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }
/*
* Autodetect (Default) Video Mode
*/
{0,},
/*
* Predefined Video Modes
*/
{
/* Palm */
PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT,
0, 0,
1, -1,
{0, 1, 0}, {0, 1, 0}, {0, 1, 0}, {0, 0, 0},
0, 0,
-1, -1, /* phys height, width */
FB_ACCEL_NONE,
0, 0, 0, 0, 0, 0, 0, /* timing */
0, /* sync */
FB_VMODE_NONINTERLACED},
{
/* Palm Grey */
PALM_WIDTH, PALM_HEIGHT, PALM_WIDTH, PALM_HEIGHT,
0, 0,
2, -1,
{0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0},
0, 0,
-1, -1, /* phys height, width */
FB_ACCEL_NONE,
0, 0, 0, 0, 0, 0, 0, /* timing */
0, /* sync */
FB_VMODE_NONINTERLACED},
/*
* Dummy Video Modes
*/
{0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,},
{0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,},
{0,}, {0,},
/*
* User Defined Video Modes
*/
{0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}, {0,}
};
static struct fb_fix_screeninfo mc68328_fix __initdata = {
.id = "mc68328";
.smem_len = 160 * 160 /8;
.type = FB_TYPE_PACKED_PIXELS;
.accel = FB_ACCEL_NONE;
};
#define NUM_TOTAL_MODES arraysize(mc68328_fb_predefined)
#define NUM_PREDEF_MODES (3)
static int mc68328fb_inverse = 0;
static int mc68328fb_mode = 0;
static int mc68328fbCursorMode = 0;
/*
* Some default modes
*/
......@@ -229,34 +180,14 @@ static int mc68328fbCursorMode = 0;
#define PALM_DEFMODE (1)
#define CYBER16_DEFMODE (2)
/*
* Interface used by the world
*/
static int mc68328_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
static int mc68328_fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int mc68328_fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int mc68328_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info);
static int mc68328_fb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int mc68328_fb_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
*/
int mc68328_fb_init(void);
static int mc68328fb_switch(int con, struct fb_info *info);
static int mc68328fb_updatevar(int con);
static void mc68328fb_blank(int blank);
static int mc68328fb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp);
static void mc68328fb_blank(int blank, struct fb_info *info);
/*
* Accelerated Functions used by the low level console driver
......@@ -264,239 +195,57 @@ static void mc68328fb_blank(int blank);
void mc68328_WaitQueue(u_short fifo);
void mc68328_WaitBlit(void);
void mc68328_BitBLT(u_short curx, u_short cury, u_short destx, u_short desty,
u_short width, u_short height, u_short mode);
void mc68328_BitBLT(u_short curx, u_short cury, u_short destx,
u_short desty, u_short width, u_short height,
u_short mode);
void mc68328_RectFill(u_short x, u_short y, u_short width, u_short height,
u_short mode, u_short color);
u_short mode, u_short color);
void mc68328_MoveCursor(u_short x, u_short y);
/*
* Hardware Specific Routines
*/
static int mc68328_init(void);
static int mc68328_encode_fix(struct fb_fix_screeninfo *fix,
struct mc68328_fb_par *par);
static int mc68328_decode_var(struct fb_var_screeninfo *var,
struct mc68328_fb_par *par);
static int mc68328_encode_var(struct fb_var_screeninfo *var,
struct mc68328_fb_par *par);
static int mc68328_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp);
static int mc68328_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp);
static void mc68328_blank(int blank);
/*
* Internal routines
*/
static void mc68328_fb_get_par(struct mc68328_fb_par *par);
static void mc68328_fb_set_par(struct mc68328_fb_par *par);
static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
static struct fb_cmap *get_default_colormap(int bpp);
static void memcpy_fs(int fsfromto, void *to, void *from, int len);
static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);
static int alloc_cmap(struct fb_cmap *cmap, int len, int transp);
static void mc68328_fb_set_disp(int con, struct fb_info *info);
static int get_video_mode(const char *name);
/* -------------------- Hardware specific routines -------------------------- */
/*
* Initialization
*
* Set the default video mode for this chipset. If a video mode was
* specified on the command line, it will override the default mode.
*/
static int mc68328_init(void)
{
/*int i;
char size;
volatile u_long *CursorBase;
unsigned long board_addr;
struct ConfigDev *cd;*/
if (mc68328fb_mode == -1)
mc68328fb_mode = PALM_DEFMODE;
mc68328Mem = (*(volatile unsigned long*)0xFFFFFA00);
/*kernel_map (board_addr + 0x01400000, 0x00400000,*/
mc68328Size = 160*160/8;
return (0);
}
/*
* This function should fill in the `fix' structure based on the
* values in the `par' structure.
*/
static int mc68328_encode_fix(struct fb_fix_screeninfo *fix,
struct mc68328_fb_par *par)
{
int i;
strcpy(fix->id, mc68328_fb_name);
fix->smem_start = mc68328Mem;
fix->smem_len = mc68328Size;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
if (par->bpp == 1)
fix->visual = FB_VISUAL_MONO01;
else
fix->visual = FB_VISUAL_DIRECTCOLOR;
fix->xpanstep = 0;
fix->ypanstep = 0;
fix->ywrapstep = 0;
for (i = 0; i < arraysize(fix->reserved); i++)
fix->reserved[i] = 0;
fix->accel = FB_ACCEL_NONE;
return(0);
}
/*
* Get the video params out of `var'. If a value doesn't fit, round
* it up, if it's too big, return -EINVAL.
*/
static int mc68328_decode_var(struct fb_var_screeninfo *var,
struct mc68328_fb_par *par)
{
par->xres = PALM_WIDTH;
par->yres = PALM_HEIGHT;
par->bpp = 1;
return(0);
}
/*
* Fill the `var' structure based on the values in `par' and maybe
* other values read out of the hardware.
*/
static int mc68328_encode_var(struct fb_var_screeninfo *var,
struct mc68328_fb_par *par)
{
int i;
var->xres = par->xres;
var->yres = par->yres;
var->xres_virtual = par->xres;
var->yres_virtual = par->yres;
var->xoffset = 0;
var->yoffset = 0;
var->bits_per_pixel = par->bpp;
var->grayscale = -1;
var->red.offset = 0;
var->red.length = par->bpp;
var->red.msb_right = 0;
var->blue = var->green = var->red;
var->transp.offset = 0;
var->transp.length = 0;
var->transp.msb_right = 0;
var->nonstd = 0;
var->activate = 0;
var->height = -1;
var->width = -1;
var->vmode = FB_VMODE_NONINTERLACED;
/* Dummy values */
var->pixclock = 0;
var->sync = 0;
var->left_margin = 0;
var->right_margin = 0;
var->upper_margin = 0;
var->lower_margin = 0;
var->hsync_len = 0;
var->vsync_len = 0;
for (i = 0; i < arraysize(var->reserved); i++)
var->reserved[i] = 0;
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 mc68328_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp)
static int mc68328fb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp)
{
return 1;
#if 0
if (regno > 255)
return (1);
if (regno > 255)
return (1);
*(mc68328Regs + 0x3c8) = (char)regno;
mc68328_colour_table [regno][0] = red & 0xff;
mc68328_colour_table [regno][1] = green & 0xff;
mc68328_colour_table [regno][2] = blue & 0xff;
mc68328_colour_table [regno][3] = transp;
*(mc68328Regs + 0x3c8) = (char) regno;
mc68328_colour_table[regno][0] = red & 0xff;
mc68328_colour_table[regno][1] = green & 0xff;
mc68328_colour_table[regno][2] = blue & 0xff;
mc68328_colour_table[regno][3] = transp;
*(mc68328Regs + 0x3c9) = (red & 0xff) >> 2;
*(mc68328Regs + 0x3c9) = (green & 0xff) >> 2;
*(mc68328Regs + 0x3c9) = (blue & 0xff) >> 2;
*(mc68328Regs + 0x3c9) = (red & 0xff) >> 2;
*(mc68328Regs + 0x3c9) = (green & 0xff) >> 2;
*(mc68328Regs + 0x3c9) = (blue & 0xff) >> 2;
return (0);
#endif
}
/*
* Read a single color register and split it into
* colors/transparent. Return != 0 for invalid regno.
*/
static int mc68328_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp)
{
return 1;
#if 0
if (regno >= 256)
return (1);
*red = mc68328_colour_table [regno][0];
*green = mc68328_colour_table [regno][1];
*blue = mc68328_colour_table [regno][2];
*transp = mc68328_colour_table [regno][3];
return (0);
return (0);
#endif
}
/*
* (Un)Blank the screen
*/
void mc68328_blank(int blank)
static void mc68328fb_blank(int blank, struct fb_info *info)
{
#if 0
if (blank)
(*(volatile unsigned char*)0xFFFFFA27) &= ~128;
(*(volatile unsigned char *) 0xFFFFFA27) &= ~128;
else
(*(volatile unsigned char*)0xFFFFFA27) |= 128;
(*(volatile unsigned char *) 0xFFFFFA27) |= 128;
#endif
}
......@@ -504,86 +253,91 @@ void mc68328_blank(int blank)
/**************************************************************
* We are waiting for "fifo" FIFO-slots empty
*/
void mc68328_WaitQueue (u_short fifo)
void mc68328_WaitQueue(u_short fifo)
{
}
/**************************************************************
* We are waiting for Hardware (Graphics Engine) not busy
*/
void mc68328_WaitBlit (void)
void mc68328_WaitBlit(void)
{
}
/**************************************************************
* BitBLT - Through the Plane
*/
void mc68328_BitBLT (u_short curx, u_short cury, u_short destx, u_short desty,
u_short width, u_short height, u_short mode)
void mc68328_BitBLT(u_short curx, u_short cury, u_short destx,
u_short desty, u_short width, u_short height,
u_short mode)
{
#if 0
u_short blitcmd = S3_BITBLT;
u_short blitcmd = S3_BITBLT;
/* Set drawing direction */
/* -Y, X maj, -X (default) */
if (curx > destx)
blitcmd |= 0x0020; /* Drawing direction +X */
else
{
curx += (width - 1);
destx += (width - 1);
}
if (cury > desty)
blitcmd |= 0x0080; /* Drawing direction +Y */
else
{
cury += (height - 1);
desty += (height - 1);
}
mc68328_WaitQueue (0x8000);
*((u_short volatile *)(mc68328Regs + S3_PIXEL_CNTL)) = 0xa000;
*((u_short volatile *)(mc68328Regs + S3_FRGD_MIX)) = (0x0060 | mode);
*((u_short volatile *)(mc68328Regs + S3_CUR_X)) = curx;
*((u_short volatile *)(mc68328Regs + S3_CUR_Y)) = cury;
*((u_short volatile *)(mc68328Regs + S3_DESTX_DIASTP)) = destx;
*((u_short volatile *)(mc68328Regs + S3_DESTY_AXSTP)) = desty;
*((u_short volatile *)(mc68328Regs + S3_MIN_AXIS_PCNT)) = height - 1;
*((u_short volatile *)(mc68328Regs + S3_MAJ_AXIS_PCNT)) = width - 1;
*((u_short volatile *)(mc68328Regs + S3_CMD)) = blitcmd;
if (curx > destx)
blitcmd |= 0x0020; /* Drawing direction +X */
else {
curx += (width - 1);
destx += (width - 1);
}
if (cury > desty)
blitcmd |= 0x0080; /* Drawing direction +Y */
else {
cury += (height - 1);
desty += (height - 1);
}
mc68328_WaitQueue(0x8000);
*((u_short volatile *) (mc68328Regs + S3_PIXEL_CNTL)) = 0xa000;
*((u_short volatile *) (mc68328Regs + S3_FRGD_MIX)) =
(0x0060 | mode);
*((u_short volatile *) (mc68328Regs + S3_CUR_X)) = curx;
*((u_short volatile *) (mc68328Regs + S3_CUR_Y)) = cury;
*((u_short volatile *) (mc68328Regs + S3_DESTX_DIASTP)) = destx;
*((u_short volatile *) (mc68328Regs + S3_DESTY_AXSTP)) = desty;
*((u_short volatile *) (mc68328Regs + S3_MIN_AXIS_PCNT)) =
height - 1;
*((u_short volatile *) (mc68328Regs + S3_MAJ_AXIS_PCNT)) =
width - 1;
*((u_short volatile *) (mc68328Regs + S3_CMD)) = blitcmd;
#endif
}
/**************************************************************
* Rectangle Fill Solid
*/
void mc68328_RectFill (u_short x, u_short y, u_short width, u_short height,
u_short mode, u_short color)
void mc68328_RectFill(u_short x, u_short y, u_short width, u_short height,
u_short mode, u_short color)
{
#if 0
u_short blitcmd = S3_FILLEDRECT;
u_short blitcmd = S3_FILLEDRECT;
mc68328_WaitQueue (0x8000);
mc68328_WaitQueue(0x8000);
*((u_short volatile *)(mc68328Regs + S3_PIXEL_CNTL)) = 0xa000;
*((u_short volatile *)(mc68328Regs + S3_FRGD_MIX)) = (0x0020 | mode);
*((u_short volatile *) (mc68328Regs + S3_PIXEL_CNTL)) = 0xa000;
*((u_short volatile *) (mc68328Regs + S3_FRGD_MIX)) =
(0x0020 | mode);
*((u_short volatile *)(mc68328Regs + S3_MULT_MISC)) = 0xe000;
*((u_short volatile *)(mc68328Regs + S3_FRGD_COLOR)) = color;
*((u_short volatile *) (mc68328Regs + S3_MULT_MISC)) = 0xe000;
*((u_short volatile *) (mc68328Regs + S3_FRGD_COLOR)) = color;
*((u_short volatile *)(mc68328Regs + S3_CUR_X)) = x;
*((u_short volatile *)(mc68328Regs + S3_CUR_Y)) = y;
*((u_short volatile *) (mc68328Regs + S3_CUR_X)) = x;
*((u_short volatile *) (mc68328Regs + S3_CUR_Y)) = y;
*((u_short volatile *)(mc68328Regs + S3_MIN_AXIS_PCNT)) = height - 1;
*((u_short volatile *)(mc68328Regs + S3_MAJ_AXIS_PCNT)) = width - 1;
*((u_short volatile *) (mc68328Regs + S3_MIN_AXIS_PCNT)) =
height - 1;
*((u_short volatile *) (mc68328Regs + S3_MAJ_AXIS_PCNT)) =
width - 1;
*((u_short volatile *)(mc68328Regs + S3_CMD)) = blitcmd;
*((u_short volatile *) (mc68328Regs + S3_CMD)) = blitcmd;
#endif
}
......@@ -591,97 +345,54 @@ mc68328_WaitQueue (0x8000);
/**************************************************************
* Move cursor to x, y
*/
void mc68328_MoveCursor (u_short x, u_short y)
void mc68328_MoveCursor(u_short x, u_short y)
{
(*(volatile unsigned short*)0xFFFFFA18) = (mc68328fbCursorMode << 14) | x;
(*(volatile unsigned short*)0xFFFFFA1A) = y;
(*(volatile unsigned short *) 0xFFFFFA18) =
(mc68328fbCursorMode << 14) | x;
(*(volatile unsigned short *) 0xFFFFFA1A) = y;
#if 0
*(mc68328Regs + S3_CRTC_ADR) = 0x39;
*(mc68328Regs + S3_CRTC_DATA) = 0xa0;
*(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGX_H;
*(mc68328Regs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
*(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGX_L;
*(mc68328Regs + S3_CRTC_DATA) = (char)(x & 0x00ff);
*(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGY_H;
*(mc68328Regs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
*(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGY_L;
*(mc68328Regs + S3_CRTC_DATA) = (char)(y & 0x00ff);
*(mc68328Regs + S3_CRTC_ADR) = 0x39;
*(mc68328Regs + S3_CRTC_DATA) = 0xa0;
*(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGX_H;
*(mc68328Regs + S3_CRTC_DATA) = (char) ((x & 0x0700) >> 8);
*(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGX_L;
*(mc68328Regs + S3_CRTC_DATA) = (char) (x & 0x00ff);
*(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGY_H;
*(mc68328Regs + S3_CRTC_DATA) = (char) ((y & 0x0700) >> 8);
*(mc68328Regs + S3_CRTC_ADR) = S3_HWGC_ORGY_L;
*(mc68328Regs + S3_CRTC_DATA) = (char) (y & 0x00ff);
#endif
}
/* -------------------- Interfaces to hardware functions -------------------- */
static struct fb_hwswitch mc68328_switch = {
mc68328_init, mc68328_encode_fix, mc68328_decode_var, mc68328_encode_var,
mc68328_getcolreg, mc68328_setcolreg, mc68328_blank
};
/* -------------------- Generic routines ------------------------------------ */
/*
* Fill the hardware's `par' structure.
*/
static void mc68328_fb_get_par(struct mc68328_fb_par *par)
{
if (current_par_valid)
*par = current_par;
else
fbhw->decode_var(&mc68328_fb_predefined[mc68328fb_mode], par);
}
static void mc68328_fb_set_par(struct mc68328_fb_par *par)
{
current_par = *par;
current_par_valid = 1;
}
static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
{
int err, activate;
struct mc68328_fb_par par;
if ((err = fbhw->decode_var(var, &par)))
return(err);
activate = var->activate;
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
mc68328_fb_set_par(&par);
fbhw->encode_var(var, &par);
var->activate = activate;
return(0);
}
/*
* Default Colormaps
*/
static u_short red16[] =
{ 0xc000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0x0000,
0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff};
{ 0xc000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0x0000,
0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff
};
static u_short green16[] =
{ 0xc000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0x0000,
0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff};
{ 0xc000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0x0000,
0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff
};
static u_short blue16[] =
{ 0xc000, 0x0000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0x0000,
0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff};
{ 0xc000, 0x0000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0x0000,
0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff
};
static struct fb_cmap default_16_colors =
{ 0, 16, red16, green16, blue16, NULL };
{ 0, 16, red16, green16, blue16, NULL };
static struct fb_cmap *get_default_colormap(int bpp)
{
return(&default_16_colors);
return (&default_16_colors);
}
......@@ -689,216 +400,13 @@ static struct fb_cmap *get_default_colormap(int bpp)
#define CNVT_FROMHW(val,width) (((width) ? ((((val)<<16)-(val)) / \
((1<<(width))-1)) : 0))
static void memcpy_fs(int fsfromto, void *to, void *from, int len)
{
switch (fsfromto) {
case 0:
memcpy(to, from, len);
return;
case 1:
copy_from_user(to, from, len);
return;
case 2:
copy_to_user(to, from, len);
return;
}
}
static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
{
int size;
int tooff = 0, fromoff = 0;
if (to->start > from->start)
fromoff = to->start-from->start;
else
tooff = from->start-to->start;
size = to->len-tooff;
if (size > from->len-fromoff)
size = from->len-fromoff;
if (size < 0)
return;
size *= sizeof(u_short);
memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
if (from->transp && to->transp)
memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
}
static int alloc_cmap(struct fb_cmap *cmap, int len, int transp)
{
int size = len*sizeof(u_short);
if (cmap->len != len) {
if (cmap->red)
kfree(cmap->red);
if (cmap->green)
kfree(cmap->green);
if (cmap->blue)
kfree(cmap->blue);
if (cmap->transp)
kfree(cmap->transp);
cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
cmap->len = 0;
if (!len)
return(0);
if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
return(-1);
if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
return(-1);
if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
return(-1);
if (transp) {
if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
return(-1);
} else
cmap->transp = NULL;
}
cmap->start = 0;
cmap->len = len;
copy_cmap(get_default_colormap(len), cmap, 0);
return(0);
}
/*
* Get the Fixed Part of the Display
*/
static int mc68328_fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
{
struct mc68328_fb_par par;
int error = 0;
if (con == -1)
mc68328_fb_get_par(&par);
else
error = fbhw->decode_var(&disp[con].var, &par);
return(error ? error : fbhw->encode_fix(fix, &par));
}
/*
* Get the User Defined Part of the Display
*/
static int mc68328_fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
struct mc68328_fb_par par;
int error = 0;
if (con == -1) {
mc68328_fb_get_par(&par);
error = fbhw->encode_var(var, &par);
} else
*var = disp[con].var;
return(error);
}
static void mc68328_fb_set_disp(int con, struct fb_info *info)
{
struct fb_fix_screeninfo fix;
mc68328_fb_get_fix(&fix, con, info);
if (con == -1)
con = 0;
info->screen_base = (u_char *)fix.smem_start;
disp[con].visual = fix.visual;
disp[con].type = fix.type;
disp[con].type_aux = fix.type_aux;
disp[con].ypanstep = fix.ypanstep;
disp[con].ywrapstep = fix.ywrapstep;
disp[con].can_soft_blank = 1;
disp[con].inverse = mc68328fb_inverse;
}
/*
* Set the User Defined Part of the Display
*/
static int mc68328_fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp;
if ((err = do_fb_set_var(var, con == currcon)))
return(err);
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
oldxres = disp[con].var.xres;
oldyres = disp[con].var.yres;
oldvxres = disp[con].var.xres_virtual;
oldvyres = disp[con].var.yres_virtual;
oldbpp = disp[con].var.bits_per_pixel;
disp[con].var = *var;
if (oldxres != var->xres || oldyres != var->yres ||
oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
oldbpp != var->bits_per_pixel) {
mc68328_fb_set_disp(con, info);
(*fb_info.changevar)(con);
alloc_cmap(&disp[con].cmap, 0, 0);
do_install_cmap(con, info);
}
}
var->activate = 0;
return(0);
}
/*
* Get the Colormap
*/
static int mc68328_fb_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, fbhw->getcolreg, info));
else if (disp[con].cmap.len) /* non default colormap? */
copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2);
else
copy_cmap(get_default_colormap(disp[con].var.bits_per_pixel), cmap,
kspc ? 0 : 2);
return(0);
}
/*
* Pan or Wrap the Display
*
* This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
*/
static int mc68328_fb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
return(-EINVAL);
}
/*
* mc68328 Frame Buffer Specific ioctls
*/
static int mc68328_fb_ioctl(struct inode *inode, struct file *file,
u_int cmd, u_long arg, int con, struct fb_info *info)
{
return(-EINVAL);
}
static struct fb_ops mc68328_fb_ops = {
owner: THIS_MODULE,
fb_get_fix: mc68328_fb_get_fix,
fb_get_var: mc68328_fb_get_var,
fb_set_var: mc68328_fb_set_var,
fb_get_cmap: mc68328_fb_get_cmap,
fb_set_cmap: gen_set_cmap,
fb_pan_display: mc68328_fb_pan_display,
fb_ioctl: mc68328_fb_ioctl,
.owner: THIS_MODULE,
.fb_setcolreg: mc68328fb_setcolreg,
.fb_fillrect: cfbfillrect,
.fb_copyarea: cfbcopyarea,
.fb_imageblit: cfbimgblt,
.fb_cursor: softcursor,
};
......@@ -908,79 +416,34 @@ static struct fb_ops mc68328_fb_ops = {
int __init mc68328_fb_init(void)
{
int err;
struct mc68328_fb_par par;
fbhw = &mc68328_switch;
err = register_framebuffer(&fb_info);
if (err < 0)
panic("Cannot register frame buffer\n");
fbhw->init();
fbhw->decode_var(&mc68328_fb_predefined[mc68328fb_mode], &par);
fbhw->encode_var(&mc68328_fb_predefined[0], &par);
strcpy(fb_info.modename, mc68328_fb_name);
fb_info.disp = disp;
fb_info.switch_con = &mc68328fb_switch;
fb_info.updatevar = &mc68328fb_updatevar;
do_fb_set_var(&mc68328_fb_predefined[0], 1);
mc68328_fb_get_var(&disp[0].var, -1, &fb_info);
mc68328_fb_set_disp(-1, &fb_info);
do_install_cmap(0, &fb_info);
return(0);
}
static int mc68328fb_switch(int con, struct fb_info *info)
{
/* Do we have to save the colormap? */
if (disp[currcon].cmap.len)
fb_get_cmap(&disp[currcon].cmap, 1, &disp[currcon].var, info);
do_fb_set_var(&disp[con].var, 1);
currcon = con;
/* Install new colormap */
do_install_cmap(con, info);
return(0);
}
/*
* Update the `var' structure (called by fbcon.c)
*
* This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
* Since it's called by a kernel driver, no range checking is done.
*/
static int mc68328fb_updatevar(int con)
{
return(0);
}
/*
* Blank the display.
*/
static void mc68328fb_blank(int blank)
{
fbhw->blank(blank);
if (mc68328fb_mode == -1)
mc68328fb_mode = PALM_DEFMODE;
mc68328_fix.smem_start = (*(volatile unsigned long *) 0xFFFFFA00);
/*kernel_map (board_addr + 0x01400000, 0x00400000, */
info->var = mc68328_fb_predefined[mc68328fb_mode];
if (info->var.bits_per_pixel == 1)
fix->visual = FB_VISUAL_MONO01;
else
fix->visual = FB_VISUAL_DIRECTCOLOR;
info->screen_base = (u_char *) mc68328_fix.smem_start;
if (register_framebuffer(&fb_info) < 0)
panic("Cannot register frame buffer\n");
return 0;
}
/*
* Get a Video Mode
*/
static int get_video_mode(const char *name)
{
int i;
int i;
for (i = 1; i < NUM_PREDEF_MODES; i++)
if (!strcmp(name, mc68328_fb_modenames[i]))
return(i);
return(0);
for (i = 1; i < NUM_PREDEF_MODES; i++)
if (!strcmp(name, mc68328_fb_modenames[i]))
return (i);
return (0);
}
......@@ -1967,8 +1967,7 @@ static void pm2fb_set_disp(const void* par, struct display* disp,
struct pm2fb_par* p=(struct pm2fb_par* )par;
unsigned long flags;
save_flags(flags);
cli();
local_irq_save(flags);
#ifdef __alpha__
disp->screen_base=i->regions.v_fb + dense_mem(i->regions.v_fb);
#else
......@@ -2014,7 +2013,7 @@ static void pm2fb_set_disp(const void* par, struct display* disp,
disp->dispsw=&fbcon_dummy;
break;
}
restore_flags(flags);
local_irq_restore(flags);
}
#ifdef PM2FB_HW_CURSOR
......
......@@ -3297,8 +3297,7 @@ static void pm3fb_set_disp(const void *par, struct display *disp,
DTRACE;
save_flags(flags);
cli();
local_irq_save(flags);
info->info.screen_base = l_fb_info->v_fb;
switch (p->depth) {
#ifdef FBCON_HAS_CFB8
......@@ -3356,7 +3355,7 @@ static void pm3fb_set_disp(const void *par, struct display *disp,
DPRINTK(1, "Invalid depth, using fbcon_dummy\n");
break;
}
restore_flags(flags);
local_irq_restore(flags);
}
/* */
......
......@@ -38,7 +38,6 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/console.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
......@@ -50,13 +49,9 @@
#error This driver requires PCI support.
#endif
/* version number of this driver */
#define RIVAFB_VERSION "0.9.3"
/* ------------------------------------------------------------------------- *
*
* various helpful macros and constants
......@@ -1166,12 +1161,12 @@ static int rivafb_open(struct fb_info *info, int user)
int cnt = atomic_read(&par->ref_count);
if (!cnt) {
memset(&par->state, 0, sizeof(struct fb_vgastate));
memset(&par->state, 0, sizeof(struct vgastate));
par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
/* save the DAC for Riva128 */
if (par->riva.Architecture == NV_ARCH_03)
par->state.flags |= VGA_SAVE_CMAP;
fb_save_vga(&par->state);
save_vga(&par->state);
RivaGetConfig(&par->riva);
riva_save_state(par, &par->initial_state);
......@@ -1192,7 +1187,7 @@ static int rivafb_release(struct fb_info *info, int user)
par->riva.LockUnlock(&par->riva, 0);
par->riva.LoadStateExt(&par->riva, &par->initial_state.ext);
fb_restore_vga(&par->state);
restore_vga(&par->state);
par->riva.LockUnlock(&par->riva, 1);
}
......
......@@ -3,6 +3,7 @@
#include <linux/config.h>
#include <linux/fb.h>
#include <video/vga.h>
#include "riva_hw.h"
/* GGI compatibility macros */
......@@ -34,7 +35,7 @@ struct riva_par {
struct riva_regs initial_state; /* initial startup video mode */
struct riva_regs current_state;
struct fb_vgastate state;
struct vgastate state;
atomic_t ref_count;
riva_cfb8_cmap_t cmap[256]; /* VGA DAC palette cache */
u32 riva_palette[16];
......
......@@ -780,8 +780,7 @@ static int tgafb_blank(int blank, struct fb_info_gen *info)
u32 vhcr, vvcr, vvvr;
unsigned long flags;
save_flags(flags);
cli();
local_irq_save(flags);
vhcr = TGA_READ_REG(TGA_HORIZ_REG);
vvcr = TGA_READ_REG(TGA_VERT_REG);
......@@ -821,7 +820,7 @@ static int tgafb_blank(int blank, struct fb_info_gen *info)
break;
}
restore_flags(flags);
local_irq_restore(flags);
return 0;
}
......
......@@ -23,7 +23,7 @@
#include <linux/init.h>
#include <asm/io.h>
#include "vga.h"
#include <video/vga.h>
#define GRAPHICS_ADDR_REG VGA_GFX_I /* Graphics address register. */
#define GRAPHICS_DATA_REG VGA_GFX_D /* Graphics data register. */
......@@ -70,7 +70,7 @@ static struct vga16fb_par {
unsigned char ModeControl; /* CRT-Controller:17h */
unsigned char ClockingMode; /* Seq-Controller:01h */
} vga_state;
struct fb_vgastate state;
struct vgastate state;
atomic_t ref_count;
int palette_blanked, vesa_blanked, mode, isVGA;
u8 misc, pel_msk, vss, clkdiv;
......@@ -304,9 +304,9 @@ static int vga16fb_open(struct fb_info *info, int user)
int cnt = atomic_read(&par->ref_count);
if (!cnt) {
memset(&par->state, 0, sizeof(struct fb_vgastate));
memset(&par->state, 0, sizeof(struct vgastate));
par->state.flags = 8;
fb_save_vga(&par->state);
save_vga(&par->state);
}
atomic_inc(&par->ref_count);
return 0;
......@@ -320,7 +320,7 @@ static int vga16fb_release(struct fb_info *info, int user)
if (!cnt)
return -EINVAL;
if (cnt == 1)
fb_restore_vga(&par->state);
restore_vga(&par->state);
atomic_dec(&par->ref_count);
return 0;
......
/*
* linux/include/video/vgastate.c -- VGA state save/restore
* linux/drivers/video/vgastate.c -- VGA state save/restore
*
* Copyright 2002 James Simmons
*
......@@ -17,8 +17,19 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/fb.h>
#include "vga.h"
#include <video/vga.h>
struct regstate {
__u8 *vga_font0;
__u8 *vga_font1;
__u8 *vga_text;
__u8 *vga_cmap;
__u8 *attr;
__u8 *crtc;
__u8 *gfx;
__u8 *seq;
__u8 misc;
};
static inline unsigned char vga_rcrtcs(caddr_t regbase, unsigned short iobase,
unsigned char reg)
......@@ -34,8 +45,9 @@ static inline void vga_wcrtcs(caddr_t regbase, unsigned short iobase,
vga_w(regbase, iobase + 0x5, val);
}
static void save_vga_text(struct fb_vgastate *state)
static void save_vga_text(struct vgastate *state, caddr_t fbbase)
{
struct regstate *saved = (struct regstate *) state->vidstate;
int i;
u8 misc, attr10, gr4, gr5, gr6, seq1, seq2, seq4;
......@@ -61,44 +73,45 @@ static void save_vga_text(struct fb_vgastate *state)
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5);
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3);
/* save font 0 */
/* save font at plane 2 */
if (state->flags & VGA_SAVE_FONT0) {
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 8 * 8192; i++)
state->vga_font0[i] = vga_r(state->fbbase, i);
for (i = 0; i < 4 * 8192; i++)
saved->vga_font0[i] = vga_r(fbbase, i);
}
/* save font 1 */
/* save font at plane 3 */
if (state->flags & VGA_SAVE_FONT1) {
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 8 * 8192; i++)
state->vga_font1[i] = vga_r(state->fbbase, i);
for (i = 0; i < state->memsize; i++)
saved->vga_font1[i] = vga_r(fbbase, i);
}
/* save font 2 */
/* save font at plane 0/1 */
if (state->flags & VGA_SAVE_TEXT) {
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 2 * 8192; i++)
state->vga_text[i] = vga_r(state->fbbase, i);
for (i = 0; i < 8192; i++)
saved->vga_text[i] = vga_r(fbbase, i);
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 2 * 8192; i++)
state->vga_text[i] = vga_r(state->fbbase +
2 * 8192, i);
for (i = 0; i < 8192; i++)
saved->vga_text[i] = vga_r(fbbase + 2 * 8192, i);
}
/* restore regs */
......@@ -120,8 +133,9 @@ static void save_vga_text(struct fb_vgastate *state)
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1);
}
static void restore_vga_text(struct fb_vgastate *state)
static void restore_vga_text(struct vgastate *state, caddr_t fbbase)
{
struct regstate *saved = (struct regstate *) state->vidstate;
int i;
u8 misc, gr1, gr3, gr4, gr5, gr6, gr8;
u8 seq1, seq2, seq4;
......@@ -151,45 +165,49 @@ static void restore_vga_text(struct fb_vgastate *state)
vga_wgfx(state->vgabase, VGA_GFX_BIT_MASK, 0xff);
vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, 0x00);
}
/* restore font 0 */
/* restore font at plane 2 */
if (state->flags & VGA_SAVE_FONT0) {
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 8 * 8192; i++)
vga_w(state->fbbase, i, state->vga_font0[i]);
for (i = 0; i < 4 * 8192; i++)
vga_w(fbbase, i, saved->vga_font0[i]);
}
/* restore font 1 */
/* restore font at plane 3 */
if (state->flags & VGA_SAVE_FONT1) {
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 8 * 8192; i++)
vga_w(state->fbbase, i, state->vga_font1[i]);
for (i = 0; i < 4 * 8192; i++)
vga_w(fbbase, i, saved->vga_font1[i]);
}
/* restore font 2 */
/* restore font at plane 0/1 */
if (state->flags & VGA_SAVE_TEXT) {
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 2 * 8192; i++)
vga_w(state->fbbase, i, state->vga_text[i]);
for (i = 0; i < 8192; i++)
vga_w(fbbase, i, saved->vga_text[i]);
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2);
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6);
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1);
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0);
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5);
for (i = 0; i < 2 * 8192; i++)
vga_w(state->fbbase + 2 * 8192, i,
state->vga_text[i]);
for (i = 0; i < 8192; i++)
vga_w(fbbase + 2 * 8192, i,
saved->vga_text[i]);
}
/* unblank screen */
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5));
......@@ -210,81 +228,92 @@ static void restore_vga_text(struct fb_vgastate *state)
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4);
}
static void save_vga_mode(struct fb_vgastate *state)
static void save_vga_mode(struct vgastate *state)
{
struct regstate *saved = (struct regstate *) state->vidstate;
unsigned short iobase;
int i;
state->misc = vga_r(state->vgabase, VGA_MIS_R);
if (state->misc & 1)
saved->misc = vga_r(state->vgabase, VGA_MIS_R);
if (saved->misc & 1)
iobase = 0x3d0;
else
iobase = 0x3b0;
for (i = 0; i < state->num_crtc; i++)
state->crtc[i] = vga_rcrtcs(state->vgabase, iobase, i);
saved->crtc[i] = vga_rcrtcs(state->vgabase, iobase, i);
vga_r(state->vgabase, iobase + 0xa);
vga_w(state->vgabase, VGA_ATT_W, 0x00);
for (i = 0; i < state->num_attr; i++) {
vga_r(state->vgabase, iobase + 0xa);
state->attr[i] = vga_rattr(state->vgabase, i);
saved->attr[i] = vga_rattr(state->vgabase, i);
}
vga_r(state->vgabase, iobase + 0xa);
vga_w(state->vgabase, VGA_ATT_W, 0x20);
for (i = 0; i < state->num_gfx; i++)
state->gfx[i] = vga_rgfx(state->vgabase, i);
saved->gfx[i] = vga_rgfx(state->vgabase, i);
for (i = 0; i < state->num_seq; i++)
state->seq[i] = vga_rseq(state->vgabase, i);
saved->seq[i] = vga_rseq(state->vgabase, i);
}
static void restore_vga_mode(struct fb_vgastate *state)
static void restore_vga_mode(struct vgastate *state)
{
struct regstate *saved = (struct regstate *) state->vidstate;
unsigned short iobase;
int i;
vga_w(state->vgabase, VGA_MIS_W, state->misc);
vga_w(state->vgabase, VGA_MIS_W, saved->misc);
if (state->misc & 1)
if (saved->misc & 1)
iobase = 0x3d0;
else
iobase = 0x3b0;
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
/* turn off display */
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE,
state->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
saved->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
/* disable sequencer */
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01);
/* enable palette addressing */
vga_r(state->vgabase, iobase + 0xa);
vga_w(state->vgabase, VGA_ATT_W, 0x00);
for (i = 2; i < state->num_seq; i++)
vga_wseq(state->vgabase, i, state->seq[i]);
vga_wseq(state->vgabase, i, saved->seq[i]);
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
/* unprotect vga regs */
vga_wcrtcs(state->vgabase, iobase, 17, state->crtc[17] & ~0x80);
vga_wcrtcs(state->vgabase, iobase, 17, saved->crtc[17] & ~0x80);
for (i = 0; i < state->num_crtc; i++)
vga_wcrtcs(state->vgabase, iobase, i, state->crtc[i]);
vga_wcrtcs(state->vgabase, iobase, i, saved->crtc[i]);
for (i = 0; i < state->num_gfx; i++)
vga_wgfx(state->vgabase, i, state->gfx[i]);
vga_wgfx(state->vgabase, i, saved->gfx[i]);
vga_r(state->vgabase, iobase + 0xa);
vga_w(state->vgabase, VGA_ATT_W, 0x00);
for (i = 0; i < state->num_attr; i++) {
vga_r(state->vgabase, iobase + 0xa);
vga_wattr(state->vgabase, i, state->attr[i]);
vga_wattr(state->vgabase, i, saved->attr[i]);
}
/* reenable sequencer */
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03);
/* turn display on */
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE,
state->seq[VGA_SEQ_CLOCK_MODE]);
saved->seq[VGA_SEQ_CLOCK_MODE] & ~(1 << 5));
/* disable video/palette source */
vga_r(state->vgabase, iobase + 0xa);
vga_w(state->vgabase, VGA_ATT_W, 0x20);
}
static void save_vga_cmap(struct fb_vgastate *state)
static void save_vga_cmap(struct vgastate *state)
{
struct regstate *saved = (struct regstate *) state->vidstate;
int i;
vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
......@@ -292,56 +321,55 @@ static void save_vga_cmap(struct fb_vgastate *state)
/* assumes DAC is readable and writable */
vga_w(state->vgabase, VGA_PEL_IR, 0x00);
for (i = 0; i < 768; i++)
state->vga_cmap[i] = vga_r(state->vgabase, VGA_PEL_D);
saved->vga_cmap[i] = vga_r(state->vgabase, VGA_PEL_D);
}
static void restore_vga_cmap(struct fb_vgastate *state)
static void restore_vga_cmap(struct vgastate *state)
{
struct regstate *saved = (struct regstate *) state->vidstate;
int i;
vga_w(state->vgabase, VGA_PEL_MSK, 0xff);
/* assumes DAC is readable and writable */
vga_w(state->vgabase, VGA_PEL_IW, 0x00);
for (i = 0; i < 768; i++)
vga_w(state->vgabase, VGA_PEL_D, state->vga_cmap[i]);
vga_w(state->vgabase, VGA_PEL_D, saved->vga_cmap[i]);
}
static void vga_cleanup(struct fb_vgastate *state)
static void vga_cleanup(struct vgastate *state)
{
if (state->vga_font0)
kfree(state->vga_font0);
if (state->vga_font1)
kfree(state->vga_font1);
if (state->vga_text)
kfree(state->vga_text);
if (state->fbbase)
iounmap(state->fbbase);
if (state->vga_cmap)
kfree(state->vga_cmap);
if (state->attr)
kfree(state->attr);
if (state->crtc)
kfree(state->crtc);
if (state->gfx)
kfree(state->gfx);
if (state->seq)
kfree(state->seq);
if (state->vidstate != NULL) {
struct regstate *saved = (struct regstate *) state->vidstate;
if (saved->vga_font0)
vfree(saved->vga_font0);
if (saved->vga_font1)
vfree(saved->vga_font1);
if (saved->vga_text)
vfree(saved->vga_text);
if (saved->vga_cmap)
vfree(saved->vga_cmap);
if (saved->attr)
vfree(saved->attr);
kfree(saved);
state->vidstate = NULL;
}
}
int fb_save_vga(struct fb_vgastate *state)
int save_vga(struct vgastate *state)
{
state->vga_font0 = NULL;
state->vga_font1 = NULL;
state->vga_text = NULL;
state->vga_cmap = NULL;
state->attr = NULL;
state->crtc = NULL;
state->gfx = NULL;
state->seq = NULL;
struct regstate *saved;
saved = kmalloc(sizeof(struct regstate), GFP_KERNEL);
if (saved == NULL)
return 1;
memset (saved, 0, sizeof(struct regstate));
(struct regstate *) state->vidstate = saved;
if (state->flags & VGA_SAVE_CMAP) {
state->vga_cmap = kmalloc(768, GFP_KERNEL);
if (!state->vga_cmap) {
saved->vga_cmap = vmalloc(768);
if (!saved->vga_cmap) {
vga_cleanup(state);
return 1;
}
......@@ -349,6 +377,8 @@ int fb_save_vga(struct fb_vgastate *state)
}
if (state->flags & VGA_SAVE_MODE) {
int total;
if (state->num_attr < 21)
state->num_attr = 21;
if (state->num_crtc < 25)
......@@ -357,64 +387,99 @@ int fb_save_vga(struct fb_vgastate *state)
state->num_gfx = 9;
if (state->num_seq < 5)
state->num_seq = 5;
state->attr = kmalloc(state->num_attr, GFP_KERNEL);
state->crtc = kmalloc(state->num_crtc, GFP_KERNEL);
state->gfx = kmalloc(state->num_gfx, GFP_KERNEL);
state->seq = kmalloc(state->num_seq, GFP_KERNEL);
if (!state->attr || !state->crtc || !state->gfx ||
!state->seq) {
total = state->num_attr + state->num_crtc +
state->num_gfx + state->num_seq;
saved->attr = vmalloc(total);
if (!saved->attr) {
vga_cleanup(state);
return 1;
}
saved->crtc = saved->attr + state->num_attr;
saved->gfx = saved->crtc + state->num_crtc;
saved->seq = saved->gfx + state->num_gfx;
save_vga_mode(state);
}
if (state->flags & VGA_SAVE_FONT0) {
state->vga_font0 = kmalloc(8192 * 8, GFP_KERNEL);
if (!state->vga_font0) {
if (state->flags & VGA_SAVE_FONTS) {
caddr_t fbbase;
/* exit if window is less than 32K */
if (state->memsize && state->memsize < 4 * 8192) {
vga_cleanup(state);
return 1;
}
if (!state->memsize)
state->memsize = 8 * 8192;
if (!state->membase)
state->membase = 0xA0000;
fbbase = ioremap(state->membase, state->memsize);
if (!fbbase) {
vga_cleanup(state);
iounmap(fbbase);
return 1;
}
if (state->flags & VGA_SAVE_FONT1) {
state->vga_font1 = kmalloc(8192 * 8, GFP_KERNEL);
if (!state->vga_font1) {
/*
* save only first 32K used by vgacon
*/
if (state->flags & VGA_SAVE_FONT0) {
saved->vga_font0 = vmalloc(4 * 8192);
if (!saved->vga_font0) {
vga_cleanup(state);
return 1;
}
}
if (state->flags & VGA_SAVE_TEXT) {
state->vga_text = kmalloc(8192 * 4, GFP_KERNEL);
if (!state->vga_text) {
/*
* largely unused, but if required by the caller
* we'll just save everything.
*/
if (state->flags & VGA_SAVE_FONT1) {
saved->vga_font1 = vmalloc(state->memsize);
if (!saved->vga_font1) {
vga_cleanup(state);
return 1;
}
}
if (state->flags & VGA_SAVE_FONTS) {
state->fbbase = ioremap(0xA0000, 8 * 8192);
if (!state->fbbase) {
/*
* Save 8K at plane0[0], and 8K at plane1[16K]
*/
if (state->flags & VGA_SAVE_TEXT) {
saved->vga_text = vmalloc(8192 * 2);
if (!saved->vga_text) {
vga_cleanup(state);
return 1;
}
save_vga_text(state);
iounmap(state->fbbase);
state->fbbase = NULL;
}
save_vga_text(state, fbbase);
iounmap(fbbase);
}
return 0;
}
int fb_restore_vga (struct fb_vgastate *state)
int restore_vga (struct vgastate *state)
{
if (state->vidstate == NULL)
return 1;
if (state->flags & VGA_SAVE_MODE)
restore_vga_mode(state);
if (state->flags & VGA_SAVE_FONTS) {
state->fbbase = ioremap(0xA0000, 8 * 8192);
if (!state->fbbase) {
caddr_t fbbase = ioremap(state->membase, state->memsize);
if (!fbbase) {
vga_cleanup(state);
iounmap(fbbase);
return 1;
}
restore_vga_text(state);
restore_vga_text(state, fbbase);
iounmap(fbbase);
}
if (state->flags & VGA_SAVE_CMAP)
......@@ -429,8 +494,8 @@ int init_module(void) { return 0; };
void cleanup_module(void) {};
#endif
EXPORT_SYMBOL(fb_save_vga);
EXPORT_SYMBOL(fb_restore_vga);
EXPORT_SYMBOL(save_vga);
EXPORT_SYMBOL(restore_vga);
MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>");
MODULE_DESCRIPTION("VGA State Save/Restore");
......
......@@ -321,37 +321,6 @@ struct fb_cursor {
struct fb_image image; /* Cursor image */
};
/* VGA State Save and Restore */
#define VGA_SAVE_FONT0 1 /* save/restore plane 2 fonts */
#define VGA_SAVE_FONT1 2 /* save/restore plane 3 fonts */
#define VGA_SAVE_TEXT 4 /* save/restore plane 0/1 fonts */
#define VGA_SAVE_FONTS 7 /* save/restore all fonts */
#define VGA_SAVE_MODE 8 /* save/restore video mode */
#define VGA_SAVE_CMAP 16 /* save/restore color map/DAC */
struct fb_vgastate {
caddr_t vgabase; /* mmio base, if supported */
__u32 flags; /* what state/s to save (see VGA_SAVE_*) */
__u32 depth; /* current fb depth, not important */
__u32 num_attr; /* number of att registers, 0 for default */
__u32 num_crtc; /* number of crt registers, 0 for default */
__u32 num_gfx; /* number of gfx registers, 0 for default */
__u32 num_seq; /* number of seq registers, 0 for default */
caddr_t fbbase; /* -- DO NOT ALTER STARTING HERE -- */
__u8 *vga_font0;
__u8 *vga_font1;
__u8 *vga_text;
__u8 *vga_cmap;
__u8 *attr;
__u8 *crtc;
__u8 *gfx;
__u8 *seq;
__u8 misc;
};
extern int fb_save_vga(struct fb_vgastate *state);
extern int fb_restore_vga(struct fb_vgastate *state);
#ifdef __KERNEL__
#include <linux/fs.h>
......
......@@ -187,6 +187,29 @@
#define VGA_OUTW_WRITE
#endif
/* VGA State Save and Restore */
#define VGA_SAVE_FONT0 1 /* save/restore plane 2 fonts */
#define VGA_SAVE_FONT1 2 /* save/restore plane 3 fonts */
#define VGA_SAVE_TEXT 4 /* save/restore plane 0/1 fonts */
#define VGA_SAVE_FONTS 7 /* save/restore all fonts */
#define VGA_SAVE_MODE 8 /* save/restore video mode */
#define VGA_SAVE_CMAP 16 /* save/restore color map/DAC */
struct vgastate {
caddr_t vgabase; /* mmio base, if supported */
__u32 flags; /* what state[s] to save (see VGA_SAVE_*) */
__u32 membase; /* VGA window base, 0 for default - 0xA000 */
__u32 memsize; /* VGA window size, 0 for default 64K */
__u32 depth; /* current fb depth, not important */
__u32 num_attr; /* number of att registers, 0 for default */
__u32 num_crtc; /* number of crt registers, 0 for default */
__u32 num_gfx; /* number of gfx registers, 0 for default */
__u32 num_seq; /* number of seq registers, 0 for default */
void *vidstate;
};
extern int save_vga(struct vgastate *state);
extern int restore_vga(struct vgastate *state);
/*
* generic VGA port read/write
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment