📄 sis_main.c
字号:
var->yres_virtual = maxyres; } } if(var->yres_virtual <= var->yres) { var->yres_virtual = var->yres; } } else { var->yres_virtual = var->yres; }}static intsis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; if(regno >= ivideo->video_cmap_len) return 1; *red = ivideo->sis_palette[regno].red; *green = ivideo->sis_palette[regno].green; *blue = ivideo->sis_palette[regno].blue; *transp = 0; return 0;}static intsisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; if(regno >= ivideo->video_cmap_len) return 1; ivideo->sis_palette[regno].red = red; ivideo->sis_palette[regno].green = green; ivideo->sis_palette[regno].blue = blue; switch(ivideo->video_bpp) {#ifdef FBCON_HAS_CFB8 case 8: outSISREG(SISDACA, regno); outSISREG(SISDACD, (red >> 10)); outSISREG(SISDACD, (green >> 10)); outSISREG(SISDACD, (blue >> 10)); if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { outSISREG(SISDAC2A, regno); outSISREG(SISDAC2D, (red >> 8)); outSISREG(SISDAC2D, (green >> 8)); outSISREG(SISDAC2D, (blue >> 8)); } break;#endif#ifdef FBCON_HAS_CFB16 case 16: ivideo->sis_fbcon_cmap.cfb16[regno] = ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); break;#endif#ifdef FBCON_HAS_CFB32 case 32: red >>= 8; green >>= 8; blue >>= 8; ivideo->sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue); break;#endif } return 0;}static voidsisfb_set_disp(int con, struct fb_var_screeninfo *var, struct fb_info *info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; struct display *display; struct display_switch *sw; struct fb_fix_screeninfo fix; long flags; display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp; sisfb_get_fix(&fix, con, info); display->var = *var; display->screen_base = (char *)ivideo->video_vbase; 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 = ivideo->sisfb_inverse; display->next_line = fix.line_length; save_flags(flags); switch(ivideo->video_bpp) {#ifdef FBCON_HAS_CFB8 case 8: sw = ivideo->accel ? &fbcon_sis8 : &fbcon_cfb8; break;#endif#ifdef FBCON_HAS_CFB16 case 16:sw = ivideo->accel ? &fbcon_sis16 : &fbcon_cfb16; display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb16; break;#endif#ifdef FBCON_HAS_CFB32 case 32:sw = ivideo->accel ? &fbcon_sis32 : &fbcon_cfb32; display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb32; break;#endif default:sw = &fbcon_dummy; break; } memcpy(&ivideo->sisfb_sw, sw, sizeof(*sw)); display->dispsw = &ivideo->sisfb_sw; restore_flags(flags); if(ivideo->sisfb_ypan) { /* display->scrollmode = 0; */ } else { display->scrollmode = SCROLL_YREDRAW; ivideo->sisfb_sw.bmove = fbcon_redraw_bmove; }}static voidsisfb_do_install_cmap(int con, struct fb_info *info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; if(con != ivideo->currcon) return; if(fb_display[con].cmap.len) { fb_set_cmap(&fb_display[con].cmap, sisfb_setcolreg, info); } else { int size = sisfb_get_cmap_len(&fb_display[con].var); fb_set_cmap(fb_default_cmap(size), sisfb_setcolreg, info); }}static intsisfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; if(con == -1) { memcpy(var, &ivideo->default_var, sizeof(struct fb_var_screeninfo)); } else { *var = fb_display[con].var; } if(ivideo->sisfb_fstn) { if(var->xres == 320 && var->yres == 480) var->yres = 240; } return 0;}static intsisfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; int err; fb_display[con].var.activate = FB_ACTIVATE_NOW; if(sisfb_do_set_var(var, con == ivideo->currcon, info)) { sisfb_crtc_to_var(ivideo, var); return -EINVAL; } sisfb_crtc_to_var(ivideo, var); sisfb_set_disp(con, var, info); if(info->changevar) { (*info->changevar)(con); } if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0))) { return err; } sisfb_do_install_cmap(con, info);#if 0 /* Why was this called here? */ unsigned int cols, rows; cols = sisbios_mode[ivideo->sisfb_mode_idx].cols; rows = sisbios_mode[ivideo->sisfb_mode_idx].rows; vc_resize_con(rows, cols, fb_display[con].conp->vc_num);#endif return 0;}static intsisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; struct display *display; display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp; if(con == ivideo->currcon) { return fb_get_cmap(cmap, kspc, sis_getcolreg, info); } else if(display->cmap.len) { fb_copy_cmap(&display->cmap, cmap, kspc ? 0 : 2); } else { int size = sisfb_get_cmap_len(&display->var); fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2); } return 0;}static intsisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; struct display *display; int err, size; display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp; size = sisfb_get_cmap_len(&display->var); if(display->cmap.len != size) { err = fb_alloc_cmap(&display->cmap, size, 0); if(err) return err; } if(con == ivideo->currcon) { return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info); } else { fb_copy_cmap(cmap, &display->cmap, kspc ? 0 : 1); } return 0;}static intsisfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info* info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; int err; if(var->vmode & FB_VMODE_YWRAP) return -EINVAL; if((var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual) || (var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)) { return -EINVAL; } if(con == ivideo->currcon) { if((err = sisfb_pan_var(ivideo, var)) < 0) return err; } fb_display[con].var.xoffset = var->xoffset; fb_display[con].var.yoffset = var->yoffset; return 0;}static intsisfb_update_var(int con, struct fb_info *info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; return(sisfb_pan_var(ivideo, &fb_display[con].var));}static intsisfb_switch(int con, struct fb_info *info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; int cols, rows; if(fb_display[ivideo->currcon].cmap.len) { fb_get_cmap(&fb_display[ivideo->currcon].cmap, 1, sis_getcolreg, info); } fb_display[con].var.activate = FB_ACTIVATE_NOW; if(!memcmp(&fb_display[con].var, &fb_display[ivideo->currcon].var, sizeof(struct fb_var_screeninfo))) { ivideo->currcon = con; return 1; } ivideo->currcon = con; sisfb_do_set_var(&fb_display[con].var, 1, info); sisfb_set_disp(con, &fb_display[con].var, info); sisfb_do_install_cmap(con, info); cols = sisbios_mode[ivideo->sisfb_mode_idx].cols; rows = sisbios_mode[ivideo->sisfb_mode_idx].rows; vc_resize_con(rows, cols, fb_display[con].conp->vc_num); sisfb_update_var(con, info); return 1;}static voidsisfb_blank(int blank, struct fb_info *info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; sisfb_myblank(ivideo, blank);}#endif/* ------------ FBDev related routines for 2.6 series ----------- */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)static intsisfb_open(struct fb_info *info, int user){ return 0;}static intsisfb_release(struct fb_info *info, int user){ return 0;}static intsisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; if(regno >= sisfb_get_cmap_len(&info->var)) return 1; switch(info->var.bits_per_pixel) { case 8: outSISREG(SISDACA, regno); outSISREG(SISDACD, (red >> 10)); outSISREG(SISDACD, (green >> 10)); outSISREG(SISDACD, (blue >> 10)); if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { outSISREG(SISDAC2A, regno); outSISREG(SISDAC2D, (red >> 8)); outSISREG(SISDAC2D, (green >> 8)); outSISREG(SISDAC2D, (blue >> 8)); } break; case 16: ((u32 *)(info->pseudo_palette))[regno] = ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); break; case 32: red >>= 8; green >>= 8; blue >>= 8; ((u32 *)(info->pseudo_palette))[regno] = (red << 16) | (green << 8) | (blue); break; } return 0;}static intsisfb_set_par(struct fb_info *info){ int err; if((err = sisfb_do_set_var(&info->var, 1, info))) { return err; } sisfb_get_fix(&info->fix, info->currcon, info); return 0;}static intsisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; unsigned int htotal = 0, vtotal = 0, myrateindex = 0; unsigned int drate = 0, hrate = 0, maxyres; int found_mode = 0; int refresh_rate, search_idx; BOOLEAN recalc_clock = FALSE; u32 pixclock; htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len; vtotal = var->upper_margin + var->lower_margin + var->vsync_len; pixclock = var->pixclock; if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) { vtotal += var->yres; vtotal <<= 1; } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { vtotal += var->yres; vtotal <<= 2; } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { vtotal += var->yres; vtotal <<= 1; } else vtotal += var->yres; if(!(htotal) || !(vtotal)) { SISFAIL("sisfb: no valid timing data"); } search_idx = 0; while( (sisbios_mode[search_idx].mode_no[0] != 0) && (sisbios_mode[search_idx].xres <= var->xres) ) { if( (sisbios_mode[search_idx].xres == var->xres) && (sisbios_mode[search_idx].yres == var->yres) && (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) { if(sisfb_validate_mode(ivideo, search_idx, ivideo->currentvbflags) > 0) { found_mode = 1; break; } } search_idx++; } if(!found_mode) { search_idx = 0; while(sisbios_mode[search_idx].mode_no[0] != 0) { if( (var->xres <= sisbios_mode[search_idx].xres) && (var->yres <= sisbios_mode[search_idx].yres) && (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) { if(sisfb_validate_mode(ivideo,search_idx, ivideo->currentvbflags) > 0) { found_mode = 1; break; } } search_idx++; } if(found_mode) { printk(KERN_DEBUG "sisfb: Adapted from %dx%dx%d to %dx%dx%d\n", var->xres, var->yres, var->bits_per_pixel, sisbios_mode[search_idx].xres, sisbios_mode[search_idx].yres, var->bits_per_pixel); var->xres = sisbios_mode[search_idx].xres; var->yres = sisbios_mode[search_idx].yres; } else { printk(KERN_ERR "sisfb: Failed to find supported mode near %dx%dx%d\n", var->xres, var->yres, var->bits_per_pixel); return -EINVAL; } } if( ((ivideo->vbflags & VB_LVDS) || /* Slave modes on LVDS and 301B-DH */ ((ivideo->vbflags & VB_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) && (var->bits_per_pixel == 8) ) { refresh_rate = 60; recalc_clock = TRUE; } else if( (ivideo->current_htotal == htotal) && /* x=x & y=y & c=c -> assume depth change */ (ivideo->current_vtotal == vtotal) && (ivideo->current_pixclock == pixclock) ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -