📄 voyager.c
字号:
{
if (SMI_de_busy)
deWaitForNotBusy();
fbcon_cfb16_revc(p, xx, yy);
}
static void fbcon_SMI16_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only)
{
if (SMI_de_busy)
deWaitForNotBusy();
fbcon_cfb16_clear_margins(conp, p, bottom_only);
}
static struct display_switch fbcon_SMI16 = {
setup: fbcon_cfb16_setup,
bmove: fbcon_SMI16_bmove,
clear: fbcon_SMI16_clear,
putc: fbcon_SMI16_putc,
putcs: fbcon_SMI16_putcs,
revc: fbcon_SMI16_revc,
clear_margins: fbcon_SMI16_clear_margins,
fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
static void fbcon_SMI32_bmove(struct display *p, int sy, int sx, int dy,
int dx, int height, int width)
{
sx *= 8; dx *= 8; width *= 8;
deCopy(0, 0, 32,
dx, dy*fontheight(p), width, height*fontheight(p),
0, 0, sx, sy*fontheight(p), 0, 0xC);
}
static void fbcon_SMI32_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
unsigned char color;
color = attr_bgcol_ec(p,conp);
deFillRect(0, 0, sx*8, sy*fontheight(p), width*8, height*fontheight(p), color);
}
static void fbcon_SMI32_putc(struct vc_data *conp, struct display *p, int c, int yy,
int xx)
{
if (SMI_de_busy)
deWaitForNotBusy();
fbcon_cfb32_putc(conp, p, c, yy, xx);
}
static void fbcon_SMI32_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy, int xx)
{
if (SMI_de_busy)
deWaitForNotBusy();
fbcon_cfb32_putcs(conp, p, s, count, yy, xx);
}
static void fbcon_SMI32_revc(struct display *p, int xx, int yy)
{
if (SMI_de_busy)
deWaitForNotBusy();
fbcon_cfb32_revc(p, xx, yy);
}
static void fbcon_SMI32_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only)
{
if (SMI_de_busy)
deWaitForNotBusy();
fbcon_cfb32_clear_margins(conp, p, bottom_only);
}
static struct display_switch fbcon_SMI32 = {
setup: fbcon_cfb32_setup,
bmove: fbcon_SMI32_bmove,
clear: fbcon_SMI32_clear,
putc: fbcon_SMI32_putc,
putcs: fbcon_SMI32_putcs,
revc: fbcon_SMI32_revc,
clear_margins: fbcon_SMI32_clear_margins,
fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
/*
* Get the VAR structure pointer for the specified console
*/
static inline struct fb_var_screeninfo *get_con_var(struct fb_info *info, int con)
{
struct smifb_info *sfb = (struct smifb_info *)info;
return (con == sfb->currcon) ? &sfb->fb.var : &fb_display[con].var;
}
/*
* Get the DISPLAY structure pointer for the specified console
*/
static inline struct display *get_con_display(struct fb_info *info, int con)
{
struct smifb_info *sfb = (struct smifb_info *)info;
return (con < 0) ? sfb->fb.disp : &fb_display[con];
}
/*
* Get the CMAP pointer for the specified console
*/
static inline struct fb_cmap *get_con_cmap(struct fb_info *info, int con)
{
struct smifb_info *sfb = (struct smifb_info *)info;
return (con == sfb->currcon) ? &sfb->fb.cmap : &fb_display[con].cmap;
}
/*
* Set the color palette
*/
static int
smifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int trans, struct fb_info *info)
{
struct smifb_info *sfb = (struct smifb_info *)info;
u16 *pal;
u32 *pal32;
switch (sfb->fb.var.bits_per_pixel)
{
case 8:
if (regno >= 256)
return 1;
if (hw.chipID==0x501)
sm501_setpalette(regno,red,green,blue);
break;
case 32:
pal32 = sfb->fb.pseudo_palette; // System has 16 default color
if (regno >= 16)
return 1;
red >>= 8;
green >>= 8;
blue >>= 8;
pal32[regno] =
(red << sfb->fb.var.red.offset) |
(green << sfb->fb.var.green.offset) |
(blue << sfb->fb.var.blue.offset);
break;
case 16:
default:
pal = sfb->fb.pseudo_palette; // System has 16 default color
if (regno >= 16)
return 1;
pal[regno] = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
break;
}
return 0;
}
/*
* smifb_decode_var():
* Get the video params out of 'var'. If a value doesn't fit, round it up,
* if it's too big, return -EINVAL.
*
* Suggestion: Round up in the following order: bits_per_pixel, xres,
* yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
* bitfields, horizontal timing, vertical timing.
*/
static int smifb_decode_var(struct fb_var_screeninfo *var, struct smifb_info *sfb, struct par_info *hw)
{
var->xres_virtual =
var->xres_virtual < var->xres ? var->xres : var->xres_virtual;
var->yres_virtual =
var->yres_virtual < var->yres ? var->yres : var->yres_virtual;
hw->width = var->xres;
hw->height = var->yres;
hw->hz = 60;
switch (var->bits_per_pixel) {
case 8:
case 16: /* RGB 565 */
case 32:
break;
default:
return -EINVAL;
}
return 0;
}
static void
smifb_hw_set_var(struct fb_var_screeninfo *var, struct smifb_info *sfb)
{
struct display *display = sfb->fb.disp;
struct fb_cmap *cmap;
sfb->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
if (display->cmap.len)
cmap = &display->cmap;
else
cmap = fb_default_cmap(sfb->palette_size);
fb_set_cmap(cmap, 1, smifb_setcolreg, &sfb->fb);
}
static int
smifb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
struct smifb_info *sfb = (struct smifb_info *)info;
struct fb_var_screeninfo *dvar = get_con_var(&sfb->fb, con);
struct display *display = get_con_display(&sfb->fb, con);
int err, chgvar = 0;
/*
* Decode var contents into a par structure, adjusting any
* out of range values.
*/
err = smifb_decode_var(var, sfb, &hw);
if (err) {
return err;
}
if (var->activate & FB_ACTIVATE_TEST)
return 0;
if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
return -EINVAL;
if (dvar->xres != var->xres)
chgvar = 1;
if (dvar->yres != var->yres)
chgvar = 1;
if (dvar->xres_virtual != var->xres_virtual)
chgvar = 1;
if (dvar->yres_virtual != var->yres_virtual)
chgvar = 1;
if (dvar->bits_per_pixel != var->bits_per_pixel)
chgvar = 1;
if (con < 0)
chgvar = 0;
switch (var->bits_per_pixel) {
case 8:
dvar->red.offset = 5;
dvar->red.length = 3;
dvar->green.offset = 2;
dvar->green.length = 3;
dvar->blue.offset = 0;
dvar->blue.length = 2;
display->visual = FB_VISUAL_PSEUDOCOLOR;
display->line_length= var->xres ;
display->dispsw = &fbcon_SMI8;
display->dispsw_data= sfb->fb.pseudo_palette;
break;
case 16:
dvar->red.offset = 11;
dvar->red.length = 5;
dvar->green.offset = 5;
dvar->green.length = 6;
dvar->blue.offset = 0;
dvar->blue.length = 5;
display->visual = FB_VISUAL_TRUECOLOR;
display->line_length= var->xres * 2;
display->dispsw = &fbcon_SMI16;
display->dispsw_data= sfb->fb.pseudo_palette;
break;
#if isPC
case 32:
dvar->red.offset = 16;
dvar->red.length = 8;
dvar->green.offset = 8;
dvar->green.length = 8;
dvar->blue.offset = 0;
dvar->blue.length = 8;
display->visual = FB_VISUAL_TRUECOLOR;
display->line_length= var->xres * 4;
display->dispsw = &fbcon_SMI32;
display->dispsw_data= sfb->fb.pseudo_palette;
break;
#endif
default:
display->dispsw = &fbcon_dummy;
break;
}
display->screen_base= sfb->fb.screen_base;
display->next_line = display->line_length;
display->type = sfb->fb.fix.type;
display->type_aux = sfb->fb.fix.type_aux;
display->ypanstep = sfb->fb.fix.ypanstep;
display->ywrapstep = sfb->fb.fix.ywrapstep;
display->can_soft_blank = 1;
display->inverse = 0;
*dvar = *var;
dvar->activate &= ~FB_ACTIVATE_ALL;
/*
* Update the old var. The fbcon drivers still use this.
* Once they are using sfb->fb.var, this can be dropped.
*/
display->var = *dvar;
/*
* If we are setting all the virtual consoles, also set the
* defaults used to create new consoles.
*/
if (var->activate & FB_ACTIVATE_ALL)
sfb->fb.disp->var = *dvar;
/*
* If the console has changed and the console has defined
* a changevar function, call that function.
*/
if (chgvar && info && sfb->fb.changevar)
sfb->fb.changevar(con);
/* If the current console is selected, activate the new var. */
if (con != sfb->currcon)
return 0;
smifb_hw_set_var(dvar, sfb);
smi_set_timing(sfb, &hw);
deInit(var->xres, var->yres, var->bits_per_pixel); /* Init SMI drawing engine */
return 0;
}
static int
__do_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
struct smifb_info *sfb = (struct smifb_info *)info;
struct fb_cmap *dcmap = get_con_cmap(info, con);
int err = 0;
/* no colormap allocated? */
if (!dcmap->len)
err = fb_alloc_cmap(dcmap, 256, 0);
if (!err && con == sfb->currcon)
err = fb_set_cmap(cmap, kspc, smifb_setcolreg, info);
if (!err)
fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1);
return err;
}
static int
smifb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
struct display *disp = get_con_display(info, con);
if (disp->visual == FB_VISUAL_TRUECOLOR)
return -EINVAL;
return __do_set_cmap(cmap, kspc, con, info);
}
static int
smifb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
{
struct display *display = get_con_display(info, con);
*fix = info->fix;
fix->line_length = display->line_length;
fix->visual = display->visual;
return 0;
}
static int
smifb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
*var = *get_con_var(info, con);
return 0;
}
static int
smifb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
{
struct fb_cmap *dcmap = get_con_cmap(info, con);
fb_copy_cmap(dcmap, cmap, kspc ? 0 : 2);
return 0;
}
static struct fb_ops smifb_ops = {
owner: THIS_MODULE,
fb_get_fix: smifb_get_fix,
fb_get_var: smifb_get_var,
fb_set_var: smifb_set_var,
fb_get_cmap: smifb_get_cmap,
fb_set_cmap: smifb_set_cmap,
};
/*
* smifb_switch():
* Change to the specified console. Palette and video mode
* are changed to the console's stored parameters.
*/
static int smifb_switch(int con, struct fb_info *info)
{
struct smifb_info *sfb = (struct smifb_info *)info;
struct display *disp;
struct fb_cmap *cmap;
if (con == sfb->currcon) {
return 0;
}
if (sfb->currcon >= 0) {
disp = fb_display + sfb->currcon;
/*
* Save the old colormap and video mode.
*/
disp->var = sfb->fb.var;
if (disp->cmap.len)
fb_copy_cmap(&sfb->fb.cmap, &disp->cmap, 0);
}
sfb->currcon = con;
disp = fb_display + con;
if (disp->cmap.len)
cmap = &disp->cmap;
else
cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
fb_copy_cmap(cmap, &sfb->fb.cmap, 0);
sfb->fb.var = disp->var;
sfb->fb.var.activate = FB_ACTIVATE_NOW;
smifb_set_var(&sfb->fb.var, con, info);
return 0;
}
/*
* Formal definition of the VESA spec:
* On
* This refers to the state of the display when it is in full operation
* Stand-By
* This defines an optional operating state of minimal power reduction with
* the shortest recovery time
* Suspend
* This refers to a level of power management in which substantial power
* reduction is achieved by the display. The display can have a longer
* recovery time from this state than from the Stand-by state
* Off
* This indicates that the display is consuming the lowest level of power
* and is non-operational. Recovery from this state may optionally require
* the user to manually power on the monitor
*
* Now, the fbdev driver adds an additional state, (blank), where they
* turn off the video (maybe by colormap tricks), but don't mess with the
* video itself: think of it semantically between on and Stand-By.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -