📄 sis_main.c
字号:
break; default: ivideo->video_cmap_len = 16; printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp); ivideo->accel = 0; break; }}static voidsisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var){ ivideo->video_cmap_len = sisfb_get_cmap_len(var); switch(var->bits_per_pixel) { case 8: var->red.offset = var->green.offset = var->blue.offset = 0; var->red.length = var->green.length = var->blue.length = 6; break; case 16: var->red.offset = 11; var->red.length = 5; var->green.offset = 5; var->green.length = 6; var->blue.offset = 0; var->blue.length = 5; var->transp.offset = 0; var->transp.length = 0; break; case 32: var->red.offset = 16; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 24; var->transp.length = 8; break; }}static intsisfb_do_set_var(struct fb_var_screeninfo *var, int isactive, struct fb_info *info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; unsigned int htotal = 0, vtotal = 0; unsigned int drate = 0, hrate = 0; int found_mode = 0; int old_mode; 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)) { DPRINTK("sisfb: Invalid 'var' information\n"); return -EINVAL; } if(pixclock && htotal && vtotal) { drate = 1000000000 / pixclock; hrate = (drate * 1000) / htotal; ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal); } else { ivideo->refresh_rate = 60; } old_mode = ivideo->sisfb_mode_idx; ivideo->sisfb_mode_idx = 0; while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) && (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) { if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) && (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) && (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) { ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]; found_mode = 1; break; } ivideo->sisfb_mode_idx++; } if(found_mode) { ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo, ivideo->sisfb_mode_idx, ivideo->currentvbflags); } else { ivideo->sisfb_mode_idx = -1; } if(ivideo->sisfb_mode_idx < 0) { printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres, var->yres, var->bits_per_pixel); ivideo->sisfb_mode_idx = old_mode; return -EINVAL; } if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) { ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx; ivideo->refresh_rate = 60; }#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) if(ivideo->sisfb_thismonitor.datavalid) { if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx, ivideo->rate_idx, ivideo->refresh_rate)) { printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n"); } }#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) if(((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {#else if(isactive) {#endif sisfb_pre_setmode(ivideo); if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) { printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no); return -EINVAL; } outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); sisfb_post_setmode(ivideo); ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp; ivideo->video_vwidth = ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres; ivideo->video_vheight = ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres; ivideo->video_linelength = ivideo->video_width * (ivideo->video_bpp >> 3); ivideo->org_x = ivideo->org_y = 0; ivideo->accel = 0; if(ivideo->sisfb_accel) { ivideo->accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0; } sisfb_set_vparms(ivideo); ivideo->current_width = ivideo->video_width; ivideo->current_height = ivideo->video_height; ivideo->current_bpp = ivideo->video_bpp; ivideo->current_htotal = htotal; ivideo->current_vtotal = vtotal; ivideo->current_pixclock = var->pixclock; ivideo->current_refresh_rate = ivideo->refresh_rate;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;#endif } return 0;}static intsisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var){ unsigned int base; if(var->xoffset > (var->xres_virtual - var->xres)) { return -EINVAL; } if(var->yoffset > (var->yres_virtual - var->yres)) { return -EINVAL; } base = var->yoffset * var->xres_virtual + var->xoffset; /* calculate base bpp dep. */ switch(var->bits_per_pixel) { case 32: break; case 16: base >>= 1; break; case 8: default: base >>= 2; break; } outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); outSISIDXREG(SISCR, 0x0D, base & 0xFF); outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF); outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF); if(ivideo->sisvga_engine == SIS_315_VGA) { setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01); } if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) { orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01); outSISIDXREG(SISPART1, 0x06, (base & 0xFF)); outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF)); outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF)); if(ivideo->sisvga_engine == SIS_315_VGA) { setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7); } } return 0;}/* ------------ FBDev related routines for 2.4 series ----------- */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)static voidsisfb_crtc_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var){ u16 VRE, VBE, VRS, VBS, VDE, VT; u16 HRE, HBE, HRS, HBS, HDE, HT; u8 sr_data, cr_data, cr_data2, cr_data3, mr_data; int A, B, C, D, E, F, temp; unsigned int hrate, drate, maxyres; inSISIDXREG(SISSR, IND_SIS_COLOR_MODE, sr_data); if(sr_data & SIS_INTERLACED_MODE) var->vmode = FB_VMODE_INTERLACED; else var->vmode = FB_VMODE_NONINTERLACED; switch((sr_data & 0x1C) >> 2) { case SIS_8BPP_COLOR_MODE: var->bits_per_pixel = 8; break; case SIS_16BPP_COLOR_MODE: var->bits_per_pixel = 16; break; case SIS_32BPP_COLOR_MODE: var->bits_per_pixel = 32; break; } sisfb_bpp_to_var(ivideo, var); inSISIDXREG(SISSR, 0x0A, sr_data); inSISIDXREG(SISCR, 0x06, cr_data); inSISIDXREG(SISCR, 0x07, cr_data2); VT = (cr_data & 0xFF) | ((u16) (cr_data2 & 0x01) << 8) | ((u16) (cr_data2 & 0x20) << 4) | ((u16) (sr_data & 0x01) << 10); A = VT + 2; inSISIDXREG(SISCR, 0x12, cr_data); VDE = (cr_data & 0xff) | ((u16) (cr_data2 & 0x02) << 7) | ((u16) (cr_data2 & 0x40) << 3) | ((u16) (sr_data & 0x02) << 9); E = VDE + 1; inSISIDXREG(SISCR, 0x10, cr_data); VRS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x04) << 6) | ((u16) (cr_data2 & 0x80) << 2) | ((u16) (sr_data & 0x08) << 7); F = VRS + 1 - E; inSISIDXREG(SISCR, 0x15, cr_data); inSISIDXREG(SISCR, 0x09, cr_data3); if(cr_data3 & 0x80) var->vmode = FB_VMODE_DOUBLE; VBS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x08) << 5) | ((u16) (cr_data3 & 0x20) << 4) | ((u16) (sr_data & 0x04) << 8); inSISIDXREG(SISCR, 0x16, cr_data); VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4); temp = VBE - ((E - 1) & 511); B = (temp > 0) ? temp : (temp + 512); inSISIDXREG(SISCR, 0x11, cr_data); VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1); temp = VRE - ((E + F - 1) & 31); C = (temp > 0) ? temp : (temp + 32); D = B - F - C; var->yres = E; var->upper_margin = D; var->lower_margin = F; var->vsync_len = C; if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { var->yres <<= 1; var->upper_margin <<= 1; var->lower_margin <<= 1; var->vsync_len <<= 1; } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) { var->yres >>= 1; var->upper_margin >>= 1; var->lower_margin >>= 1; var->vsync_len >>= 1; } inSISIDXREG(SISSR, 0x0b, sr_data); inSISIDXREG(SISCR, 0x00, cr_data); HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8); A = HT + 5; inSISIDXREG(SISCR, 0x01, cr_data); HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6); E = HDE + 1; inSISIDXREG(SISCR, 0x04, cr_data); HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2); F = HRS - E - 3; inSISIDXREG(SISCR, 0x02, cr_data); HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4); inSISIDXREG(SISSR, 0x0c, sr_data); inSISIDXREG(SISCR, 0x03, cr_data); inSISIDXREG(SISCR, 0x05, cr_data2); HBE = (cr_data & 0x1f) | ((u16) (cr_data2 & 0x80) >> 2) | ((u16) (sr_data & 0x03) << 6); HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3); temp = HBE - ((E - 1) & 255); B = (temp > 0) ? temp : (temp + 256); temp = HRE - ((E + F + 3) & 63); C = (temp > 0) ? temp : (temp + 64); D = B - F - C; var->xres = var->xres_virtual = E * 8; if((var->xres == 320) && (var->yres == 200 || var->yres == 240)) { /* Terrible hack, but the correct CRTC data for * these modes only produces a black screen... */ var->left_margin = (400 - 376); var->right_margin = (328 - 320); var->hsync_len = (376 - 328); } else { var->left_margin = D * 8; var->right_margin = F * 8; var->hsync_len = C * 8; } var->activate = FB_ACTIVATE_NOW; var->sync = 0; mr_data = inSISREG(SISMISCR); if(mr_data & 0x80) var->sync &= ~FB_SYNC_VERT_HIGH_ACT; else var->sync |= FB_SYNC_VERT_HIGH_ACT; if(mr_data & 0x40) var->sync &= ~FB_SYNC_HOR_HIGH_ACT; else var->sync |= FB_SYNC_HOR_HIGH_ACT; VT += 2; VT <<= 1; HT = (HT + 5) * 8; if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { VT <<= 1; } hrate = ivideo->refresh_rate * VT / 2; drate = (hrate * HT) / 1000; var->pixclock = (u32) (1000000000 / drate); if(ivideo->sisfb_ypan) { maxyres = ivideo->heapstart / (var->xres * (var->bits_per_pixel >> 3)); if(maxyres > 32767) maxyres = 32767; if(ivideo->sisfb_max) { var->yres_virtual = maxyres; } else { if(var->yres_virtual > maxyres) { 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 }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -