📄 sis_main.c
字号:
} if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) { if( (!ivideo->sisfb_thismonitor.datavalid) || ((ivideo->sisfb_thismonitor.datavalid) && (ivideo->sisfb_thismonitor.feature & 0xe0))) { if(ivideo->sisvga_engine == SIS_315_VGA) { setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63); } if(!(sisfb_bridgeisslave(ivideo))) { setSISIDXREG(SISSR, 0x01, ~0x20, sr01); setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f); } } } if(ivideo->currentvbflags & CRT2_LCD) { if(ivideo->vbflags2 & VB2_SISLVDSBRIDGE) { if(backlight) { SiS_SiS30xBLOn(&ivideo->SiS_Pr); } else { SiS_SiS30xBLOff(&ivideo->SiS_Pr); } } else if(ivideo->sisvga_engine == SIS_315_VGA) {#ifdef CONFIG_FB_SIS_315 if(ivideo->vbflags2 & VB2_CHRONTEL) { if(backlight) { SiS_Chrontel701xBLOn(&ivideo->SiS_Pr); } else { SiS_Chrontel701xBLOff(&ivideo->SiS_Pr); } }#endif } if(((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags2 & (VB2_301|VB2_30xBDH|VB2_LVDS))) || ((ivideo->sisvga_engine == SIS_315_VGA) && ((ivideo->vbflags2 & (VB2_LVDS | VB2_CHRONTEL)) == VB2_LVDS))) { setSISIDXREG(SISSR, 0x11, ~0x0c, sr11); } if(ivideo->sisvga_engine == SIS_300_VGA) { if((ivideo->vbflags2 & VB2_30xB) && (!(ivideo->vbflags2 & VB2_30xBDH))) { setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13); } } else if(ivideo->sisvga_engine == SIS_315_VGA) { if((ivideo->vbflags2 & VB2_30xB) && (!(ivideo->vbflags2 & VB2_30xBDH))) { setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); } } } else if(ivideo->currentvbflags & CRT2_VGA) { if(ivideo->vbflags2 & VB2_30xB) { setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0); } } return 0;}/* ------------- Callbacks from init.c/init301.c -------------- */#ifdef CONFIG_FB_SIS_300unsigned intsisfb_read_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg){ struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo; u32 val = 0; pci_read_config_dword(ivideo->nbridge, reg, &val); return (unsigned int)val;}voidsisfb_write_nbridge_pci_dword(struct SiS_Private *SiS_Pr, int reg, unsigned int val){ struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo; pci_write_config_dword(ivideo->nbridge, reg, (u32)val);}unsigned intsisfb_read_lpc_pci_dword(struct SiS_Private *SiS_Pr, int reg){ struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo; u32 val = 0; if(!ivideo->lpcdev) return 0; pci_read_config_dword(ivideo->lpcdev, reg, &val); return (unsigned int)val;}#endif#ifdef CONFIG_FB_SIS_315voidsisfb_write_nbridge_pci_byte(struct SiS_Private *SiS_Pr, int reg, unsigned char val){ struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo; pci_write_config_byte(ivideo->nbridge, reg, (u8)val);}unsigned intsisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg){ struct sis_video_info *ivideo = (struct sis_video_info *)SiS_Pr->ivideo; u16 val = 0; if(!ivideo->lpcdev) return 0; pci_read_config_word(ivideo->lpcdev, reg, &val); return (unsigned int)val;}#endif/* ----------- FBDev related routines for all series ----------- */static intsisfb_get_cmap_len(const struct fb_var_screeninfo *var){ return (var->bits_per_pixel == 8) ? 256 : 16;}static voidsisfb_set_vparms(struct sis_video_info *ivideo){ switch(ivideo->video_bpp) { case 8: ivideo->DstColor = 0x0000; ivideo->SiS310_AccelDepth = 0x00000000; ivideo->video_cmap_len = 256; break; case 16: ivideo->DstColor = 0x8000; ivideo->SiS310_AccelDepth = 0x00010000; ivideo->video_cmap_len = 16; break; case 32: ivideo->DstColor = 0xC000; ivideo->SiS310_AccelDepth = 0x00020000; ivideo->video_cmap_len = 16; break; default: ivideo->video_cmap_len = 16; printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp); ivideo->accel = 0; }}static intsisfb_calc_maxyres(struct sis_video_info *ivideo, struct fb_var_screeninfo *var){ int maxyres = ivideo->sisfb_mem / (var->xres_virtual * (var->bits_per_pixel >> 3)); if(maxyres > 32767) maxyres = 32767; return maxyres;}static voidsisfb_calc_pitch(struct sis_video_info *ivideo, struct fb_var_screeninfo *var){ ivideo->video_linelength = var->xres_virtual * (var->bits_per_pixel >> 3); ivideo->scrnpitchCRT1 = ivideo->video_linelength; if(!(ivideo->currentvbflags & CRT1_LCDA)) { if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { ivideo->scrnpitchCRT1 <<= 1; } }}static voidsisfb_set_pitch(struct sis_video_info *ivideo){ BOOLEAN isslavemode = FALSE; unsigned short HDisplay1 = ivideo->scrnpitchCRT1 >> 3; unsigned short HDisplay2 = ivideo->video_linelength >> 3; if(sisfb_bridgeisslave(ivideo)) isslavemode = TRUE; /* We need to set pitch for CRT1 if bridge is in slave mode, too */ if((ivideo->currentvbflags & VB_DISPTYPE_DISP1) || (isslavemode)) { outSISIDXREG(SISCR,0x13,(HDisplay1 & 0xFF)); setSISIDXREG(SISSR,0x0E,0xF0,(HDisplay1 >> 8)); } /* We must not set the pitch for CRT2 if bridge is in slave mode */ if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!isslavemode)) { orSISIDXREG(SISPART1,ivideo->CRT2_write_enable,0x01); outSISIDXREG(SISPART1,0x07,(HDisplay2 & 0xFF)); setSISIDXREG(SISPART1,0x09,0xF0,(HDisplay2 >> 8)); }}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_set_mode(struct sis_video_info *ivideo, int clrscrn){ unsigned short modeno = ivideo->mode_no; /* >=2.6.12's fbcon clears the screen anyway */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) if(!clrscrn) modeno |= 0x80;#else modeno |= 0x80;#endif outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD); sisfb_pre_setmode(ivideo); if(SiSSetMode(&ivideo->SiS_Pr, modeno) == 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); return 0;}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, ret; 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); ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]; } 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 /* If acceleration to be used? Need to know * before pre/post_set_mode() */ ivideo->accel = 0;#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)#ifdef STUPID_ACCELF_TEXT_SHIT if(var->accel_flags & FB_ACCELF_TEXT) { info->flags &= ~FBINFO_HWACCEL_DISABLED; } else { info->flags |= FBINFO_HWACCEL_DISABLED; }#endif if(!(info->flags & FBINFO_HWACCEL_DISABLED)) ivideo->accel = -1;#else if(var->accel_flags & FB_ACCELF_TEXT) ivideo->accel = -1;#endif if((ret = sisfb_set_mode(ivideo, 1))) { return ret; } ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp; ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres; ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres; sisfb_calc_pitch(ivideo, var); sisfb_set_pitch(ivideo); 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_linelength = ivideo->video_linelength; 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 voidsisfb_set_base_CRT1(struct sis_video_info *ivideo, unsigned int base){ 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); }}static voidsisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base){ 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); } }}static intsisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var){ if(var->xoffset > (var->xres_virtual - var->xres)) { return -EINVAL; } if(var->yoffset > (var->yres_virtual - var->yres)) { return -EINVAL; } ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset; /* calculate base bpp dep. */ switch(var->bits_per_pixel) { case 32: break; case 16: ivideo->current_base >>= 1; break; case 8: default: ivideo->current_base >>= 2; break; } ivideo->current_base += (ivideo->video_offset >> 2); sisfb_set_base_CRT1(ivideo, ivideo->current_base); sisfb_set_base_CRT2(ivideo, ivideo->current_base); return 0;}/* ------------ FBDev related routines for 2.4 series ----------- */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)#include "sisfb_fbdev_2_4.h"#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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -