Commit b30e6e18 authored by James Simmons's avatar James Simmons

More drivers ported over to new API.

parent 1a133193
......@@ -10,9 +10,6 @@ bool 'Support for frame buffer devices (EXPERIMENTAL)' CONFIG_FB
if [ "$CONFIG_FB" = "y" ]; then
define_bool CONFIG_DUMMY_CONSOLE y
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
if [ "$CONFIG_PCI" = "y" ]; then
tristate ' nVidia Riva support (EXPERIMENTAL)' CONFIG_FB_RIVA
fi
if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_PCI" = "y" ]; then
tristate ' Cirrus Logic support (EXPERIMENTAL)' CONFIG_FB_CLGEN
tristate ' Permedia2 support (EXPERIMENTAL)' CONFIG_FB_PM2
......@@ -127,6 +124,7 @@ if [ "$CONFIG_FB" = "y" ]; then
fi
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
if [ "$CONFIG_PCI" != "n" ]; then
tristate ' nVidia Riva support (EXPERIMENTAL)' CONFIG_FB_RIVA
tristate ' Matrox acceleration (EXPERIMENTAL)' CONFIG_FB_MATROX
if [ "$CONFIG_FB_MATROX" != "n" ]; then
bool ' Millennium I/II support' CONFIG_FB_MATROX_MILLENIUM
......@@ -268,10 +266,10 @@ if [ "$CONFIG_FB" = "y" ]; then
if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_ATARI" = "y" -o \
"$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
"$CONFIG_FB_OF" = "y" -o "$CONFIG_FB_TGA" = "y" -o \
"$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
"$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_TCX" = "y" -o "$CONFIG_FB_CGTHREE" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_G364" = "y" -o \
"$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_TRIDENT" = "y" -o \
"$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
"$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
"$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
......@@ -282,17 +280,16 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_3DFX" = "y" -o \
"$CONFIG_FB_PMAG_BA" = "y" -o "$CONFIG_FB_PMAGB_B" = "y" -o \
"$CONFIG_FB_MAXINE" = "y" -o "$CONFIG_FB_TX3912" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_TRIDENT" = "y" ]; then
"$CONFIG_FB_SIS" = "y" ]; then
define_tristate CONFIG_FBCON_CFB8 y
else
if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
"$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_MAC" = "m" -o \
"$CONFIG_FB_OF" = "m" -o "$CONFIG_FB_TGA" = "m" -o \
"$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
"$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_PM3" = "m" -o \
"$CONFIG_FB_TCX" = "m" -o "$CONFIG_FB_CGTHREE" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_G364" = "m" -o \
"$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_TRIDENT" = "m" -o \
"$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
"$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
"$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
......@@ -303,14 +300,13 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_PMAG_BA" = "m" -o "$CONFIG_FB_PMAGB_B" = "m" -o \
"$CONFIG_FB_MAXINE" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
"$CONFIG_FB_TX3912" = "m" -o "$CONFIG_FB_PM3" = "m" -o \
"$CONFIG_FB_TRIDENT" = "m" ]; then
"$CONFIG_FB_TX3912" = "m" ]; then
define_tristate CONFIG_FBCON_CFB8 m
fi
fi
if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \
"$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" -o \
"$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \
"$CONFIG_FB_TRIDENT" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \
"$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
......@@ -320,13 +316,12 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
"$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_3DFX" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \
"$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_TRIDENT" = "y" ]; then
"$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_PM3" = "y" ]; then
define_tristate CONFIG_FBCON_CFB16 y
else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
"$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_NEOMAGIC" = "m" -o \
"$CONFIG_FB_VIRTUAL" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \
"$CONFIG_FB_TRIDENT" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \
"$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_3DFX" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
......@@ -336,8 +331,7 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_PM3" = "m" -o \
"$CONFIG_FB_TRIDENT" = "m" ]; then
"$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_PM3" = "m" ]; then
define_tristate CONFIG_FBCON_CFB16 m
fi
fi
......@@ -359,36 +353,36 @@ if [ "$CONFIG_FB" = "y" ]; then
fi
fi
if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \
"$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
"$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_TRIDENT" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_TGA" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
"$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
"$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \
"$CONFIG_FB_RADEON" = "y" -o "$CONFIG_FB_PVR2" = "y" -o \
"$CONFIG_FB_3DFX" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_TRIDENT" = "y" ]; then
"$CONFIG_FB_3DFX" = "y" -o "$CONFIG_FB_PM3" = "y" ]; then
define_tristate CONFIG_FBCON_CFB32 y
else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
"$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
"$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_TRIDENT" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_TGA" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
"$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
"$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_3DFX" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
"$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_PM3" = "y"-o \
"$CONFIG_FB_TRIDENT" = "m" ]; then
"$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_PM3" = "y" ]; then
define_tristate CONFIG_FBCON_CFB32 m
fi
fi
if [ "$CONFIG_FB_VESA" = "y" -o "$CONFIG_FB_Q40" = "y" -o \
"$CONFIG_FB_FM2" = "y" -o "$CONFIG_FB_HIT" = "y" -o \
"$CONFIG_FB_ANAKIN" = "y" ]; then
"$CONFIG_FB_ANAKIN" = "y" -o "$CONFIG_FB_G364" = "y" -o \
"$CONFIG_FB_VIRTUAL" = "y" ]; then
define_tristate CONFIG_FBCON_ACCEL y
else
if [ "$CONFIG_FB_HIT" = "m" ]; then
if [ "$CONFIG_FB_HIT" = "m" -o "$CONFIG_FB_G364" = "m" -o \
"$CONFIG_FB_VIRTUAL" = "m" ]; then
define_tristate CONFIG_FBCON_ACCEL m
fi
fi
......@@ -414,10 +408,10 @@ if [ "$CONFIG_FB" = "y" ]; then
# define_tristate CONFIG_FBCON_IPLAN2P16 m
fi
fi
if [ "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" ]; then
if [ "$CONFIG_FB_MAC" = "y" ]; then
define_tristate CONFIG_FBCON_MAC y
else
if [ "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then
if [ "$CONFIG_FB_MAC" = "m" ]; then
define_tristate CONFIG_FBCON_MAC m
fi
fi
......
......@@ -28,13 +28,10 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/selection.h>
#include <linux/console.h>
#include <asm/io.h>
#include <asm/jazz.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
/*
* Various defines for the G364
......@@ -79,56 +76,61 @@
static struct display disp;
static struct fb_info fb_info;
static struct { u_char red, green, blue, pad; } palette[256];
static struct fb_fix_screeninfo fb_fix = { { "G364 8plane", } };
static struct fb_var_screeninfo fb_var = { 0, };
static struct fb_fix_screeninfo fb_fix __initdata = {
id: "G364 8plane",
smem_start: 0x40000000, /* physical address */
type: FB_TYPE_PACKED_PIXELS,
visual: FB_VISUAL_PSEUDOCOLOR,
ypanstep: 1,
accel: FB_ACCEL_NONE,
};
static struct fb_var_screeninfo fb_var __initdata = {
bits_per_pixel: 8,
red: { 0, 8, 0 },
green: { 0, 8, 0 },
blue: { 0, 8, 0 },
activate: FB_ACTIVATE_NOW,
height: -1,
width: -1,
pixclock: 39722,
left_margin: 40,
right_margin: 24,
upper_margin: 32,
lower_margin: 11,
hsync_len: 96,
vsync_len: 2,
vmode: FB_VMODE_NONINTERLACED,
};
/*
* Interface used by the world
*/
static int g364fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
static int g364fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int g364fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
int g364fb_init(void);
static int g364fb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int g364fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
static int g364fb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp,
struct fb_info *info);
static int g364fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int g364fb_blank(int blank, struct fb_info *info);
/*
* Interface to the low level console driver
*/
int g364fb_init(void);
static int g364fbcon_switch(int con, struct fb_info *info);
static int g364fbcon_updatevar(int con, struct fb_info *info);
/*
* Internal routines
*/
static int g364fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info);
static struct fb_ops g364fb_ops = {
owner: THIS_MODULE,
fb_get_fix: g364fb_get_fix,
fb_get_var: g364fb_get_var,
fb_set_var: g364fb_set_var,
fb_get_cmap: g364fb_get_cmap,
fb_get_fix: gen_get_fix,
fb_get_var: gen_get_var,
fb_set_var: gen_set_var,
fb_get_cmap: gen_get_cmap,
fb_set_cmap: gen_set_cmap,
fb_setcolreg: g364fb_setcolreg,
fb_pan_display: g364fb_pan_display,
fb_blank: g364fb_blank,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
};
void fbcon_g364fb_cursor(struct display *p, int mode, int x, int y)
{
switch (mode) {
......@@ -139,111 +141,57 @@ void fbcon_g364fb_cursor(struct display *p, int mode, int x, int y)
case CM_MOVE:
case CM_DRAW:
*(unsigned int *) CTLA_REG &= ~CURS_TOGGLE;
*(unsigned int *) CURS_POS_REG = ((x * fontwidth(p)) << 12) | ((y * fontheight(p))-p->var.yoffset);
*(unsigned int *) CURS_POS_REG =
((x * fontwidth(p)) << 12) | ((y * fontheight(p)) -
p->var.yoffset);
break;
}
}
static struct display_switch fbcon_g364cfb8 = {
setup: fbcon_cfb8_setup,
bmove: fbcon_cfb8_bmove,
clear: fbcon_cfb8_clear,
putc: fbcon_cfb8_putc,
putcs: fbcon_cfb8_putcs,
revc: fbcon_cfb8_revc,
cursor: fbcon_g364fb_cursor,
clear_margins: fbcon_cfb8_clear_margins,
fontwidthmask: FONTWIDTH(8)
};
/*
* Get the Fixed Part of the Display
* Pan or Wrap the Display
*
* This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
*/
static int g364fb_get_fix(struct fb_fix_screeninfo *fix, int con,
static int g364fb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
memcpy(fix, &fb_fix, sizeof(fb_fix));
return 0;
}
if (var->xoffset || var->yoffset + var->yres > var->yres_virtual)
return -EINVAL;
/*
* Get the User Defined Part of the Display
*/
static int g364fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
memcpy(var, &fb_var, sizeof(fb_var));
*(unsigned int *) TOP_REG = var->yoffset * var->xres;
return 0;
}
/*
* Set the User Defined Part of the Display
* Blank the display.
*/
static int g364fb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
static int g364fb_blank(int blank, struct fb_info *info)
{
struct display *display;
int oldbpp = -1, err;
if (con >= 0)
display = &fb_display[con];
if (blank)
*(unsigned int *) CTLA_REG |= FORCE_BLANK;
else
display = &disp; /* used during initialization */
if (var->xres > fb_var.xres || var->yres > fb_var.yres ||
var->xres_virtual > fb_var.xres_virtual ||
var->yres_virtual > fb_var.yres_virtual ||
var->bits_per_pixel > fb_var.bits_per_pixel ||
var->nonstd ||
(var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
return -EINVAL;
memcpy(var, &fb_var, sizeof(fb_var));
if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
oldbpp = display->var.bits_per_pixel;
display->var = *var;
*(unsigned int *)TOP_REG = var->yoffset * var->xres;
}
if (oldbpp != var->bits_per_pixel) {
if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
return err;
do_install_cmap(con, info);
}
*(unsigned int *) CTLA_REG &= ~FORCE_BLANK;
return 0;
}
/*
* Pan or Wrap the Display
*
* This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
* Set a single color register. Return != 0 for invalid regno.
*/
static int g364fb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
static int g364fb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp, struct fb_info *info)
{
if (var->xoffset || var->yoffset+var->yres > var->yres_virtual)
return -EINVAL;
volatile unsigned int *ptr = (volatile unsigned int *) CLR_PAL_REG;
*(unsigned int *)TOP_REG = var->yoffset * var->xres;
return 0;
}
if (regno > 255)
return 1;
red >>= 8;
green >>= 8;
blue >>= 8;
ptr[regno << 1] = (red << 16) | (green << 8) | blue;
/*
* Get the Colormap
*/
static int g364fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
if (con == info->currcon) /* current console? */
return fb_get_cmap(cmap, kspc, g364fb_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
cmap, kspc ? 0 : 2);
return 0;
}
......@@ -252,28 +200,21 @@ static int g364fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
*/
int __init g364fb_init(void)
{
int i,j;
volatile unsigned int *pal_ptr = (volatile unsigned int *) CLR_PAL_REG;
volatile unsigned int *curs_pal_ptr = (volatile unsigned int *) CURS_PAL_REG;
unsigned int xres, yres;
int mem;
volatile unsigned int *pal_ptr =
(volatile unsigned int *) CLR_PAL_REG;
volatile unsigned int *curs_pal_ptr =
(volatile unsigned int *) CURS_PAL_REG;
int mem, i, j;
/* TBD: G364 detection */
/* get the resolution set by ARC console */
*(volatile unsigned int *)CTLA_REG &= ~ENABLE_VTG;
xres = (*((volatile unsigned int*)DISPLAY_REG) & 0x00ffffff) * 4;
yres = (*((volatile unsigned int*)VDISPLAY_REG) & 0x00ffffff) / 2;
*(volatile unsigned int *)CTLA_REG |= ENABLE_VTG;
/* initialise color palette */
for (i = 0; i < 16; i++) {
j = color_table[i];
palette[i].red=default_red[j];
palette[i].green=default_grn[j];
palette[i].blue=default_blu[j];
pal_ptr[i << 1] = (palette[i].red << 16) | (palette[i].green << 8) | palette[i].blue;
}
*(volatile unsigned int *) CTLA_REG &= ~ENABLE_VTG;
fb_var.xres =
(*((volatile unsigned int *) DISPLAY_REG) & 0x00ffffff) * 4;
fb_var.yres =
(*((volatile unsigned int *) VDISPLAY_REG) & 0x00ffffff) / 2;
*(volatile unsigned int *) CTLA_REG |= ENABLE_VTG;
/* setup cursor */
curs_pal_ptr[0] |= 0x00ffffff;
......@@ -284,171 +225,45 @@ int __init g364fb_init(void)
* first set the whole cursor to transparent
*/
for (i = 0; i < 512; i++)
*(unsigned short *)(CURS_PAT_REG+i*8) = 0;
*(unsigned short *) (CURS_PAT_REG + i * 8) = 0;
/*
* switch the last two lines to cursor palette 3
* we assume here, that FONTSIZE_X is 8
*/
*(unsigned short *)(CURS_PAT_REG + 14*64) = 0xffff;
*(unsigned short *)(CURS_PAT_REG + 15*64) = 0xffff;
fb_var.bits_per_pixel = 8;
fb_var.xres = fb_var.xres_virtual = xres;
fb_var.yres = yres;
*(unsigned short *) (CURS_PAT_REG + 14 * 64) = 0xffff;
*(unsigned short *) (CURS_PAT_REG + 15 * 64) = 0xffff;
fb_var.xres_virtual = fbvar.xres;
fb_fix.line_length = (xres / 8) * fb_var.bits_per_pixel;
fb_fix.smem_start = 0x40000000; /* physical address */
/* get size of video memory; this is special for the JAZZ hardware */
mem = (r4030_read_reg32(JAZZ_R4030_CONFIG) >> 8) & 3;
fb_fix.smem_len = (1 << (mem*2)) * 512 * 1024;
fb_fix.type = FB_TYPE_PACKED_PIXELS;
fb_fix.type_aux = 0;
fb_fix.visual = FB_VISUAL_PSEUDOCOLOR;
fb_fix.xpanstep = 0;
fb_fix.ypanstep = 1;
fb_fix.ywrapstep = 0;
fb_fix.mmio_start = 0;
fb_fix.mmio_len = 0;
fb_fix.accel = FB_ACCEL_NONE;
fb_var.yres_virtual = fb_fix.smem_len / xres;
fb_var.xoffset = fb_var.yoffset = 0;
fb_var.grayscale = 0;
fb_var.red.offset = 0;
fb_var.green.offset = 0;
fb_var.blue.offset = 0;
fb_var.red.length = fb_var.green.length = fb_var.blue.length = 8;
fb_var.red.msb_right = fb_var.green.msb_right = fb_var.blue.msb_right = 0;
fb_var.transp.offset = fb_var.transp.length = fb_var.transp.msb_right = 0;
fb_var.nonstd = 0;
fb_var.activate = 0;
fb_var.height = fb_var.width = -1;
fb_var.accel_flags = 0;
fb_var.pixclock = 39722;
fb_var.left_margin = 40;
fb_var.right_margin = 24;
fb_var.upper_margin = 32;
fb_var.lower_margin = 11;
fb_var.hsync_len = 96;
fb_var.vsync_len = 2;
fb_var.sync = 0;
fb_var.vmode = FB_VMODE_NONINTERLACED;
disp.var = fb_var;
disp.cmap.start = 0;
disp.cmap.len = 0;
disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL;
disp.visual = fb_fix.visual;
disp.type = fb_fix.type;
disp.type_aux = fb_fix.type_aux;
disp.ypanstep = fb_fix.ypanstep;
disp.ywrapstep = fb_fix.ywrapstep;
disp.line_length = fb_fix.line_length;
disp.can_soft_blank = 1;
disp.inverse = 0;
disp.dispsw = &fbcon_g364cfb8;
fb_fix.smem_len = (1 << (mem * 2)) * 512 * 1024;
fb_var.yres_virtual = fb_fix.smem_len / fb_var.xres;
strcpy(fb_info.modename, fb_fix.id);
fb_info.node = NODEV;
fb_info.fbops = &g364fb_ops;
fb_info.screen_base = (char *)G364_MEM_BASE; /* virtual kernel address */
fb_info.screen_base = (char *) G364_MEM_BASE; /* virtual kernel address */
fb_info.var = fb_var;
fb_info.fix = fb_fix;
fb_info.flags = FBINFO_FLAG_DEFAULT;
fb_info.disp = &disp;
fb_info.currcon = -1;
fb_info.fontname[0] = '\0';
fb_info.changevar = NULL;
fb_info.switch_con = &g364fbcon_switch;
fb_info.updatevar = &g364fbcon_updatevar;
fb_info.flags = FBINFO_FLAG_DEFAULT;
fb_info.switch_con = gen_switch;
fb_info.updatevar = gen_update_var;
g364fb_set_var(&fb_var, -1, &fb_info);
fb_alloc_cmap(&fb_info.cmap, 255, 0);
gen_set_disp(-1, &fb_info);
if (register_framebuffer(&fb_info) < 0)
return -EINVAL;
printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node),
fb_fix.id);
return 0;
}
static int g364fbcon_switch(int con, struct fb_info *info)
{
/* Do we have to save the colormap? */
if (fb_display[info->currcon].cmap.len)
fb_get_cmap(&fb_display[info->currcon].cmap, 1, g364fb_getcolreg, info);
info->currcon = con;
/* Install new colormap */
do_install_cmap(con, info);
g364fbcon_updatevar(con, info);
return 0;
}
/*
* Update the `var' structure (called by fbcon.c)
*/
static int g364fbcon_updatevar(int con, struct fb_info *info)
{
if (con == info->currcon) {
struct fb_var_screeninfo *var = &fb_display[info->currcon].var;
/* hardware scrolling */
*(unsigned int *)TOP_REG = var->yoffset * var->xres;
}
return 0;
}
/*
* Blank the display.
*/
static int g364fb_blank(int blank, struct fb_info *info)
{
if (blank)
*(unsigned int *) CTLA_REG |= FORCE_BLANK;
else
*(unsigned int *) CTLA_REG &= ~FORCE_BLANK;
return 0;
}
/*
* Read a single color register and split it into
* colors/transparent. Return != 0 for invalid regno.
*/
static int g364fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info)
{
if (regno > 255)
return 1;
*red = (palette[regno].red << 8) | palette[regno].red;
*green = (palette[regno].green << 8) | palette[regno].green;
*blue = (palette[regno].blue << 8) | palette[regno].blue;
*transp = 0;
return 0;
}
/*
* Set a single color register. Return != 0 for invalid regno.
*/
static int g364fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
volatile unsigned int *ptr = (volatile unsigned int *) CLR_PAL_REG;
if (regno > 255)
return 1;
red >>= 8;
green >>= 8;
blue >>=8;
palette[regno].red = red;
palette[regno].green = green;
palette[regno].blue = blue;
ptr[regno << 1] = (red << 16) | (green << 8) | blue;
fb_info.fix.id);
return 0;
}
......
/*
* linux/drivers/video/vfb.c -- Virtual frame buffer device
*
* Copyright (C) 2002 James Simmons
*
* Copyright (C) 1997 Geert Uytterhoeven
*
* This file is subject to the terms and conditions of the GNU General Public
......@@ -22,15 +24,7 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <video/fbcon.h>
#include <video/fbcon-mfb.h>
#include <video/fbcon-cfb2.h>
#include <video/fbcon-cfb4.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
#include <video/fbcon-cfb24.h>
#include <video/fbcon-cfb32.h>
#include <linux/fbcon.h>
/*
* RAM we reserve for the frame buffer. This defines the maximum screen
......@@ -41,135 +35,109 @@
#define VIDEOMEMSIZE (1*1024*1024) /* 1 MB */
static u_long videomemory, videomemorysize = VIDEOMEMSIZE;
static void *videomemory;
static u_long videomemorysize = VIDEOMEMSIZE;
MODULE_PARM(videomemorysize, "l");
static struct display disp;
static const char *mode_option __initdata = NULL;
static struct fb_info fb_info;
static struct { u_char red, green, blue, pad; } palette[256];
static union {
#ifdef FBCON_HAS_CFB16
u16 cfb16[16];
#endif
#ifdef FBCON_HAS_CFB24
u32 cfb24[16];
#endif
#ifdef FBCON_HAS_CFB32
u32 cfb32[16];
#endif
} fbcon_cmap;
static char vfb_name[16] = "Virtual FB";
static struct fb_var_screeninfo vfb_default = {
/* 640x480, 8 bpp */
640, 480, 640, 480, 0, 0, 8, 0,
{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
0, 0, -1, -1, 0, 20000, 64, 64, 32, 32, 64, 2,
0, FB_VMODE_NONINTERLACED
static u32 vfb_pseudo_palette[17];
static struct display disp;
static struct fb_var_screeninfo vfb_default __initdata = {
xres: 640,
yres: 480,
xres_virtual: 640,
yres_virtual: 480,
bits_per_pixel: 8,
red: { 0, 8, 0 },
green: { 0, 8, 0 },
blue: { 0, 8, 0 },
activate: FB_ACTIVATE_TEST,
height: -1,
width: -1,
pixclock: 20000,
left_margin: 64,
right_margin: 64,
upper_margin: 32,
lower_margin: 32,
hsync_len: 64,
vsync_len: 2,
vmode: FB_VMODE_NONINTERLACED,
};
static int vfb_enable = 0; /* disabled by default */
static struct fb_fix_screeninfo vfb_fix __initdata = {
id: "Virtual FB",
type: FB_TYPE_PACKED_PIXELS,
visual: FB_VISUAL_PSEUDOCOLOR,
xpanstep: 1,
ypanstep: 1,
ywrapstep: 1,
accel: FB_ACCEL_NONE,
};
static int vfb_enable __initdata = 0; /* disabled by default */
MODULE_PARM(vfb_enable, "i");
/*
* Interface used by the world
*/
int vfb_init(void);
int vfb_setup(char *);
int vfb_setup(char*);
static int vfb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
static int vfb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
static int vfb_set_var(struct fb_var_screeninfo *var, int con,
static int vfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info);
static int vfb_set_par(struct fb_info *info);
static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int vfb_pan_display(struct fb_var_screeninfo *var, int con,
static int vfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info);
static int vfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info);
/*
* Interface to the low level console driver
*/
int vfb_init(void);
static int vfbcon_switch(int con, struct fb_info *info);
static int vfbcon_updatevar(int con, struct fb_info *info);
/*
* Internal routines
*/
static u_long get_line_length(int xres_virtual, int bpp);
static void vfb_encode_fix(struct fb_fix_screeninfo *fix,
struct fb_var_screeninfo *var);
static void set_color_bitfields(struct fb_var_screeninfo *var);
static int vfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info);
static int vfb_mmap(struct fb_info *info, struct file *file,
struct vm_area_struct *vma);
static struct fb_ops vfb_ops = {
owner: THIS_MODULE,
fb_get_fix: vfb_get_fix,
fb_get_var: vfb_get_var,
fb_set_var: vfb_set_var,
fb_get_cmap: vfb_get_cmap,
fb_get_fix: gen_get_fix,
fb_get_var: gen_get_var,
fb_set_var: gen_set_var,
fb_get_cmap: gen_set_cmap,
fb_set_cmap: gen_set_cmap,
fb_check_var: vfb_check_var,
fb_set_par: vfb_set_par,
fb_setcolreg: vfb_setcolreg,
fb_pan_display: vfb_pan_display,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
fb_mmap: vfb_mmap,
};
/*
* Get the Fixed Part of the Display
* Internal routines
*/
static int vfb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
static u_long get_line_length(int xres_virtual, int bpp)
{
struct fb_var_screeninfo *var;
if (con == -1)
var = &vfb_default;
else
var = &fb_display[con].var;
vfb_encode_fix(fix, var);
return 0;
}
/*
* Get the User Defined Part of the Display
*/
u_long length;
static int vfb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
if (con == -1)
*var = vfb_default;
else
*var = fb_display[con].var;
set_color_bitfields(var);
return 0;
length = xres_virtual * bpp;
length = (length + 31) & ~31;
length >>= 3;
return (length);
}
/*
* Set the User Defined Part of the Display
* Setting the video mode has been split into two parts.
* First part, xxxfb_check_var, must not write anything
* to hardware, it should only verify and adjust var.
* This means it doesn't alter par but it does use hardware
* data from it to check this var.
*/
static int vfb_set_var(struct fb_var_screeninfo *var, int con,
static int vfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
int err, activate = var->activate;
int oldxres, oldyres, oldvxres, oldvyres, oldbpp;
u_long line_length;
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
......@@ -177,8 +145,8 @@ static int vfb_set_var(struct fb_var_screeninfo *var, int con,
if (var->vmode & FB_VMODE_CONUPDATE) {
var->vmode |= FB_VMODE_YWRAP;
var->xoffset = display->var.xoffset;
var->yoffset = display->var.yoffset;
var->xoffset = info->var.xoffset;
var->yoffset = info->var.yoffset;
}
/*
......@@ -198,368 +166,316 @@ static int vfb_set_var(struct fb_var_screeninfo *var, int con,
var->bits_per_pixel = 8;
else if (var->bits_per_pixel <= 16)
var->bits_per_pixel = 16;
#if 0
/* fbcon doesn't support this (yet) */
else if (var->bits_per_pixel <= 24)
var->bits_per_pixel = 24;
else if (var->bits_per_pixel <= 32)
var->bits_per_pixel = 32;
#endif
else
return -EINVAL;
if (var->xres_virtual < var->xoffset + var->xres)
var->xres_virtual = var->xoffset + var->xres;
if (var->yres_virtual < var->yoffset + var->yres)
var->yres_virtual = var->yoffset + var->yres;
/*
* Memory limit
*/
line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
if (line_length*var->yres_virtual > videomemorysize)
line_length =
get_line_length(var->xres_virtual, var->bits_per_pixel);
if (line_length * var->yres_virtual > videomemorysize)
return -ENOMEM;
set_color_bitfields(var);
if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
oldxres = display->var.xres;
oldyres = display->var.yres;
oldvxres = display->var.xres_virtual;
oldvyres = display->var.yres_virtual;
oldbpp = display->var.bits_per_pixel;
display->var = *var;
if (oldxres != var->xres || oldyres != var->yres ||
oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
oldbpp != var->bits_per_pixel) {
struct fb_fix_screeninfo fix;
vfb_encode_fix(&fix, var);
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
display->ypanstep = fix.ypanstep;
display->ywrapstep = fix.ywrapstep;
display->line_length = fix.line_length;
display->can_soft_blank = 1;
display->inverse = 0;
/*
* Now that we checked it we alter var. The reason being is that the video
* mode passed in might not work but slight changes to it might make it
* work. This way we let the user know what is acceptable.
*/
switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_MFB
case 1:
display->dispsw = &fbcon_mfb;
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;
#endif
#ifdef FBCON_HAS_CFB2
case 2:
display->dispsw = &fbcon_cfb2;
case 16: /* RGBA 5551 */
if (var->transp.length) {
var->red.offset = 0;
var->red.length = 5;
var->green.offset = 5;
var->green.length = 5;
var->blue.offset = 10;
var->blue.length = 5;
var->transp.offset = 15;
var->transp.length = 1;
} else { /* RGB 565 */
var->red.offset = 0;
var->red.length = 5;
var->green.offset = 5;
var->green.length = 6;
var->blue.offset = 11;
var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
}
break;
#endif
#ifdef FBCON_HAS_CFB4
case 4:
display->dispsw = &fbcon_cfb4;
case 24: /* RGB 888 */
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 8;
var->green.length = 8;
var->blue.offset = 16;
var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break;
case 32: /* RGBA 8888 */
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 8;
var->green.length = 8;
var->blue.offset = 16;
var->blue.length = 8;
var->transp.offset = 24;
var->transp.length = 8;
break;
}
var->red.msb_right = 0;
var->green.msb_right = 0;
var->blue.msb_right = 0;
var->transp.msb_right = 0;
return 0;
}
/* This routine actually sets the video mode. It's in here where we
* the hardware state info->par and fix which can be affected by the
* change in par. For this driver it doesn't do much.
*/
static int vfb_set_par(struct fb_info *info)
{
info->fix.line_length = get_line_length(info->var.xres_virtual,
info->var.bits_per_pixel);
return 0;
}
/*
* 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 vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
if (regno >= 256) /* no. of hw registers */
return 1;
/*
* Program hardware... do anything you want with transp
*/
/* grayscale works only partially under directcolor */
if (info->var.grayscale) {
/* grayscale = 0.30*R + 0.59*G + 0.11*B */
red = green = blue =
(red * 77 + green * 151 + blue * 28) >> 8;
}
/* Directcolor:
* var->{color}.offset contains start of bitfield
* var->{color}.length contains length of bitfield
* {hardwarespecific} contains width of RAMDAC
* cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
* RAMDAC[X] is programmed to (red, green, blue)
*
* Pseudocolor:
* uses offset = 0 && length = RAMDAC register width.
* var->{color}.offset is 0
* var->{color}.length contains widht of DAC
* cmap is not used
* RAMDAC[X] is programmed to (red, green, blue)
* Truecolor:
* does not use DAC. Usually 3 are present.
* var->{color}.offset contains start of bitfield
* var->{color}.length contains length of bitfield
* cmap is programmed to (red << red.offset) | (green << green.offset) |
* (blue << blue.offset) | (transp << transp.offset)
* RAMDAC does not exist
*/
#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
switch (info->fix.visual) {
case FB_VISUAL_TRUECOLOR:
case FB_VISUAL_PSEUDOCOLOR:
red = CNVT_TOHW(red, info->var.red.length);
green = CNVT_TOHW(green, info->var.green.length);
blue = CNVT_TOHW(blue, info->var.blue.length);
transp = CNVT_TOHW(transp, info->var.transp.length);
break;
case FB_VISUAL_DIRECTCOLOR:
red = CNVT_TOHW(red, 8); /* expect 8 bit DAC */
green = CNVT_TOHW(green, 8);
blue = CNVT_TOHW(blue, 8);
/* hey, there is bug in transp handling... */
transp = CNVT_TOHW(transp, 8);
break;
#endif
#ifdef FBCON_HAS_CFB8
}
#undef CNVT_TOHW
/* Truecolor has hardware independent palette */
if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
u32 v;
if (regno >= 16)
return 1;
v = (red << info->var.red.offset) |
(green << info->var.green.offset) |
(blue << info->var.blue.offset) |
(transp << info->var.transp.offset);
switch (info->var.bits_per_pixel) {
case 8:
display->dispsw = &fbcon_cfb8;
break;
#endif
#ifdef FBCON_HAS_CFB16
case 16:
display->dispsw = &fbcon_cfb16;
display->dispsw_data = fbcon_cmap.cfb16;
((u32 *) (info->pseudo_palette))[regno] = v;
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
display->dispsw = &fbcon_cfb24;
display->dispsw_data = fbcon_cmap.cfb24;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
display->dispsw = &fbcon_cfb32;
display->dispsw_data = fbcon_cmap.cfb32;
break;
#endif
default:
display->dispsw = &fbcon_dummy;
((u32 *) (info->pseudo_palette))[regno] = v;
break;
}
if (fb_info.changevar)
(*fb_info.changevar)(con);
}
if (oldbpp != var->bits_per_pixel) {
if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
return err;
do_install_cmap(con, info);
}
return 0;
}
return 0;
}
/*
* Pan or Wrap the Display
*
* This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
*/
static int vfb_pan_display(struct fb_var_screeninfo *var, int con,
static int vfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
if (var->vmode & FB_VMODE_YWRAP) {
if (var->yoffset < 0 ||
var->yoffset >= fb_display[con].var.yres_virtual ||
var->xoffset)
if (var->yoffset < 0
|| var->yoffset >= info->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)
if (var->xoffset + var->xres > info->var.xres_virtual ||
var->yoffset + var->yres > info->var.yres_virtual)
return -EINVAL;
}
fb_display[con].var.xoffset = var->xoffset;
fb_display[con].var.yoffset = var->yoffset;
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
fb_display[con].var.vmode |= FB_VMODE_YWRAP;
info->var.vmode |= FB_VMODE_YWRAP;
else
fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
info->var.vmode &= ~FB_VMODE_YWRAP;
return 0;
}
/*
* Get the Colormap
* Most drivers don't need their own mmap function
*/
static int vfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
static int vfb_mmap(struct fb_info *info, struct file *file,
struct vm_area_struct *vma)
{
if (con == info->currcon) /* current console? */
return fb_get_cmap(cmap, kspc, vfb_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
cmap, kspc ? 0 : 2);
return 0;
return -EINVAL;
}
int __init vfb_setup(char *options)
{
char *this_opt;
fb_info.fontname[0] = '\0';
vfb_enable = 1;
if (!options || !*options)
return 0;
return 1;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!strncmp(this_opt, "font:", 5))
strcpy(fb_info.fontname, this_opt+5);
if (!*this_opt)
continue;
if (!strncmp(this_opt, "disable", 7))
vfb_enable = 0;
}
return 0;
return 1;
}
/*
* Initialisation
*/
int __init vfb_init(void)
{
int retval;
if (!vfb_enable)
return -ENXIO;
if (!(videomemory = (u_long)vmalloc(videomemorysize)))
/*
* For real video cards we use ioremap.
*/
if (!(videomemory = vmalloc(videomemorysize)))
return -ENOMEM;
strcpy(fb_info.modename, vfb_name);
fb_info.changevar = NULL;
fb_info.node = NODEV;
fb_info.fbops = &vfb_ops;
fb_info.screen_base = (char *)videomemory;
fb_info.disp = &disp;
fb_info.currcon = -1;
fb_info.switch_con = &vfbcon_switch;
fb_info.updatevar = &vfbcon_updatevar;
fb_info.flags = FBINFO_FLAG_DEFAULT;
vfb_set_var(&vfb_default, -1, &fb_info);
if (register_framebuffer(&fb_info) < 0) {
vfree((void *)videomemory);
return -EINVAL;
}
printk(KERN_INFO "fb%d: Virtual frame buffer device, using %ldK of video memory\n",
GET_FB_IDX(fb_info.node), videomemorysize>>10);
return 0;
}
static int vfbcon_switch(int con, struct fb_info *info)
{
/* Do we have to save the colormap? */
if (fb_display[info->currcon].cmap.len)
fb_get_cmap(&fb_display[info->currcon].cmap, 1, vfb_getcolreg, info);
info->currcon = con;
/* Install new colormap */
do_install_cmap(con, info);
return 0;
}
/*
* Update the `var' structure (called by fbcon.c)
* VFB must clear memory to prevent kernel info
* leakage into userspace
* VGA-based drivers MUST NOT clear memory if
* they want to be able to take over vgacon
*/
memset(videomemory, 0, videomemorysize);
static int vfbcon_updatevar(int con, struct fb_info *info)
{
/* Nothing */
return 0;
}
static u_long get_line_length(int xres_virtual, int bpp)
{
u_long length;
length = xres_virtual*bpp;
length = (length+31)&-32;
length >>= 3;
return(length);
}
static void vfb_encode_fix(struct fb_fix_screeninfo *fix,
struct fb_var_screeninfo *var)
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, vfb_name);
fix->smem_start = videomemory;
fix->smem_len = videomemorysize;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
switch (var->bits_per_pixel) {
case 1:
fix->visual = FB_VISUAL_MONO01;
break;
case 2:
case 4:
case 8:
fix->visual = FB_VISUAL_PSEUDOCOLOR;
break;
case 16:
case 24:
case 32:
fix->visual = FB_VISUAL_TRUECOLOR;
break;
}
fix->ywrapstep = 1;
fix->xpanstep = 1;
fix->ypanstep = 1;
fix->line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
}
static void set_color_bitfields(struct fb_var_screeninfo *var)
{
switch (var->bits_per_pixel) {
case 1:
case 8:
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 0;
var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break;
case 16: /* RGB 565 */
var->red.offset = 0;
var->red.length = 5;
var->green.offset = 5;
var->green.length = 6;
var->blue.offset = 11;
var->blue.length = 5;
var->transp.offset = 0;
var->transp.length = 0;
break;
case 24: /* RGB 888 */
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 8;
var->green.length = 8;
var->blue.offset = 16;
var->blue.length = 8;
var->transp.offset = 0;
var->transp.length = 0;
break;
case 32: /* RGBA 8888 */
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 8;
var->green.length = 8;
var->blue.offset = 16;
var->blue.length = 8;
var->transp.offset = 24;
var->transp.length = 8;
break;
}
var->red.msb_right = 0;
var->green.msb_right = 0;
var->blue.msb_right = 0;
var->transp.msb_right = 0;
}
fb_info.screen_base = videomemory;
fb_info.node = NODEV;
fb_info.fbops = &vfb_ops;
retval = fb_find_mode(&fb_info.var, &fb_info, mode_option,
NULL, 0, NULL, 8);
/*
* Read a single color register and split it into
* colors/transparent. Return != 0 for invalid regno.
*/
if (!retval || (retval == 4))
fb_info.var = vfb_default;
fb_info.fix = vfb_fix;
fb_info.pseudo_palette = &vfb_pseudo_palette;
fb_info.flags = FBINFO_FLAG_DEFAULT;
static int vfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info)
{
if (regno > 255)
return 1;
*red = (palette[regno].red<<8) | palette[regno].red;
*green = (palette[regno].green<<8) | palette[regno].green;
*blue = (palette[regno].blue<<8) | palette[regno].blue;
*transp = 0;
return 0;
}
strcpy(fb_info.modename, vesafb_fix.id);
fb_info.changevar = NULL;
fb_info.currcon = -1;
fb_info.disp = &disp;
fb_info.switch_con = gen_switch;
fb_info.updatevar = gen_update_var;
fb_alloc_cmap(&fb_info.cmap, 256, 0);
/*
* Set a single color register. The values supplied are already
* rounded down to the hardware's capabilities (according to the
* entries in the var structure). Return != 0 for invalid regno.
*/
if (register_framebuffer(&fb_info) < 0) {
vfree(videomemory);
return -EINVAL;
}
static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
if (regno > 255)
return 1;
red >>= 8;
green >>= 8;
blue >>= 8;
palette[regno].red = red;
palette[regno].green = green;
palette[regno].blue = blue;
printk(KERN_INFO
"fb%d: Virtual frame buffer device, using %ldK of video memory\n",
GET_FB_IDX(fb_info.node), videomemorysize >> 10);
return 0;
}
#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
{
return vfb_init();
}
void cleanup_module(void)
static void __exit vfb_cleanup(void)
{
unregister_framebuffer(&fb_info);
vfree((void *)videomemory);
vfree(videomemory);
}
module_init(vfb_init);
module_exit(vfb_cleanup);
MODULE_LICENSE("GPL");
#endif /* MODULE */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment