📄 sis_main.c
字号:
sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info){ struct sis_video_info *ivideo = (struct sis_video_info *)info->par; memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, ivideo->myid); fix->smem_start = ivideo->video_base + ivideo->video_offset; fix->smem_len = ivideo->sisfb_mem; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->visual = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; fix->xpanstep = 1; fix->ypanstep = (ivideo->sisfb_ypan) ? 1 : 0; fix->ywrapstep = 0; fix->line_length = ivideo->video_linelength; fix->mmio_start = ivideo->mmio_base; fix->mmio_len = ivideo->mmio_size; if(ivideo->sisvga_engine == SIS_300_VGA) { fix->accel = FB_ACCEL_SIS_GLAMOUR; } else if((ivideo->chip == SIS_330) || (ivideo->chip == SIS_760) || (ivideo->chip == SIS_761)) { fix->accel = FB_ACCEL_SIS_XABRE; } else if(ivideo->chip == XGI_20) { fix->accel = FB_ACCEL_XGI_VOLARI_Z; } else if(ivideo->chip >= XGI_40) { fix->accel = FB_ACCEL_XGI_VOLARI_V; } else { fix->accel = FB_ACCEL_SIS_GLAMOUR_2; } return 0;}/* ---------------- fb_ops structures ----------------- */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)static struct fb_ops sisfb_ops = { .owner = THIS_MODULE, .fb_get_fix = sisfb_get_fix, .fb_get_var = sisfb_get_var, .fb_set_var = sisfb_set_var, .fb_get_cmap = sisfb_get_cmap, .fb_set_cmap = sisfb_set_cmap, .fb_pan_display = sisfb_pan_display, .fb_ioctl = sisfb_ioctl};#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)static struct fb_ops sisfb_ops = { .owner = THIS_MODULE, .fb_open = sisfb_open, .fb_release = sisfb_release, .fb_check_var = sisfb_check_var, .fb_set_par = sisfb_set_par, .fb_setcolreg = sisfb_setcolreg, .fb_pan_display = sisfb_pan_display, .fb_blank = sisfb_blank, .fb_fillrect = fbcon_sis_fillrect, .fb_copyarea = fbcon_sis_copyarea, .fb_imageblit = cfb_imageblit, .fb_cursor = soft_cursor, .fb_sync = fbcon_sis_sync,#ifdef SIS_NEW_CONFIG_COMPAT .fb_compat_ioctl= sisfb_compat_ioctl,#endif .fb_ioctl = sisfb_ioctl};#endif/* ---------------- Chip generation dependent routines ---------------- */static struct pci_dev * __devinitsisfb_get_northbridge(int basechipid){ struct pci_dev *pdev = NULL; int nbridgenum, nbridgeidx, i; static const unsigned short nbridgeids[] = { PCI_DEVICE_ID_SI_540, /* for SiS 540 VGA */ PCI_DEVICE_ID_SI_630, /* for SiS 630/730 VGA */ PCI_DEVICE_ID_SI_730, PCI_DEVICE_ID_SI_550, /* for SiS 550 VGA */ PCI_DEVICE_ID_SI_650, /* for SiS 650/651/740 VGA */ PCI_DEVICE_ID_SI_651, PCI_DEVICE_ID_SI_740, PCI_DEVICE_ID_SI_661, /* for SiS 661/741/660/760/761 VGA */ PCI_DEVICE_ID_SI_741, PCI_DEVICE_ID_SI_660, PCI_DEVICE_ID_SI_760, PCI_DEVICE_ID_SI_761 }; switch(basechipid) {#ifdef CONFIG_FB_SIS_300 case SIS_540: nbridgeidx = 0; nbridgenum = 1; break; case SIS_630: nbridgeidx = 1; nbridgenum = 2; break;#endif#ifdef CONFIG_FB_SIS_315 case SIS_550: nbridgeidx = 3; nbridgenum = 1; break; case SIS_650: nbridgeidx = 4; nbridgenum = 3; break; case SIS_660: nbridgeidx = 7; nbridgenum = 5; break;#endif default: return NULL; } for(i = 0; i < nbridgenum; i++) { if((pdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, nbridgeids[nbridgeidx+i], NULL))) break; } return pdev;}static int __devinitsisfb_get_dram_size(struct sis_video_info *ivideo){#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315) u8 reg;#endif ivideo->video_size = 0; ivideo->UMAsize = ivideo->LFBsize = 0; switch(ivideo->chip) {#ifdef CONFIG_FB_SIS_300 case SIS_300: inSISIDXREG(SISSR, 0x14, reg); ivideo->video_size = ((reg & 0x3F) + 1) << 20; break; case SIS_540: case SIS_630: case SIS_730: if(!ivideo->nbridge) return -1; pci_read_config_byte(ivideo->nbridge, 0x63, ®); ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21); break;#endif#ifdef CONFIG_FB_SIS_315 case SIS_315H: case SIS_315PRO: case SIS_315: inSISIDXREG(SISSR, 0x14, reg); ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; switch((reg >> 2) & 0x03) { case 0x01: case 0x03: ivideo->video_size <<= 1; break; case 0x02: ivideo->video_size += (ivideo->video_size/2); } break; case SIS_330: inSISIDXREG(SISSR, 0x14, reg); ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; if(reg & 0x0c) ivideo->video_size <<= 1; break; case SIS_550: case SIS_650: case SIS_740: inSISIDXREG(SISSR, 0x14, reg); ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20; break; case SIS_661: case SIS_741: inSISIDXREG(SISCR, 0x79, reg); ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; break; case SIS_660: case SIS_760: case SIS_761: inSISIDXREG(SISCR, 0x79, reg); reg = (reg & 0xf0) >> 4; if(reg) { ivideo->video_size = (1 << reg) << 20; ivideo->UMAsize = ivideo->video_size; } inSISIDXREG(SISCR, 0x78, reg); reg &= 0x30; if(reg) { if(reg == 0x10) { ivideo->LFBsize = (32 << 20); } else { ivideo->LFBsize = (64 << 20); } ivideo->video_size += ivideo->LFBsize; } break; case SIS_340: case XGI_20: case XGI_40: inSISIDXREG(SISSR, 0x14, reg); ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20; if(ivideo->chip != XGI_20) { reg = (reg & 0x0c) >> 2; if(ivideo->revision_id == 2) { if(reg & 0x01) reg = 0x02; else reg = 0x00; } if(reg == 0x02) ivideo->video_size <<= 1; else if(reg == 0x03) ivideo->video_size <<= 2; } break;#endif default: return -1; } return 0;}/* -------------- video bridge device detection --------------- */static void __devinitsisfb_detect_VB_connect(struct sis_video_info *ivideo){ u8 cr32, temp; /* No CRT2 on XGI Z7 */ if(ivideo->chip == XGI_20) { ivideo->sisfb_crt1off = 0; return; }#ifdef CONFIG_FB_SIS_300 if(ivideo->sisvga_engine == SIS_300_VGA) { inSISIDXREG(SISSR, 0x17, temp); if((temp & 0x0F) && (ivideo->chip != SIS_300)) { /* PAL/NTSC is stored on SR16 on such machines */ if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) { inSISIDXREG(SISSR, 0x16, temp); if(temp & 0x20) ivideo->vbflags |= TV_PAL; else ivideo->vbflags |= TV_NTSC; } } }#endif inSISIDXREG(SISCR, 0x32, cr32); if(cr32 & SIS_CRT1) { ivideo->sisfb_crt1off = 0; } else { ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0; } ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA); if(cr32 & SIS_VB_TV) ivideo->vbflags |= CRT2_TV; if(cr32 & SIS_VB_LCD) ivideo->vbflags |= CRT2_LCD; if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA; /* Check given parms for hardware compatibility. * (Cannot do this in the search_xx routines since we don't * know what hardware we are running on then) */ if(ivideo->chip != SIS_550) { ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0; } if(ivideo->sisfb_tvplug != -1) { if( (ivideo->sisvga_engine != SIS_315_VGA) || (!(ivideo->vbflags2 & VB2_SISYPBPRBRIDGE)) ) { if(ivideo->sisfb_tvplug & TV_YPBPR) { ivideo->sisfb_tvplug = -1; printk(KERN_ERR "sisfb: YPbPr not supported\n"); } } } if(ivideo->sisfb_tvplug != -1) { if( (ivideo->sisvga_engine != SIS_315_VGA) || (!(ivideo->vbflags2 & VB2_SISHIVISIONBRIDGE)) ) { if(ivideo->sisfb_tvplug & TV_HIVISION) { ivideo->sisfb_tvplug = -1; printk(KERN_ERR "sisfb: HiVision not supported\n"); } } } if(ivideo->sisfb_tvstd != -1) { if( (!(ivideo->vbflags2 & VB2_SISBRIDGE)) && (!((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags2 & VB2_CHRONTEL))) ) { if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) { ivideo->sisfb_tvstd = -1; printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n"); } } } /* Detect/set TV plug & type */ if(ivideo->sisfb_tvplug != -1) { ivideo->vbflags |= ivideo->sisfb_tvplug; } else { if(cr32 & SIS_VB_YPBPR) ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */ else if(cr32 & SIS_VB_HIVISION) ivideo->vbflags |= TV_HIVISION; else if(cr32 & SIS_VB_SCART) ivideo->vbflags |= TV_SCART; else { if(cr32 & SIS_VB_SVIDEO) ivideo->vbflags |= TV_SVIDEO; if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO; } } if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) { if(ivideo->sisfb_tvstd != -1) { ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ); ivideo->vbflags |= ivideo->sisfb_tvstd; } if(ivideo->vbflags & TV_SCART) { ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ); ivideo->vbflags |= TV_PAL; } if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) { if(ivideo->sisvga_engine == SIS_300_VGA) { inSISIDXREG(SISSR, 0x38, temp); if(temp & 0x01) ivideo->vbflags |= TV_PAL; else ivideo->vbflags |= TV_NTSC; } else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) { inSISIDXREG(SISSR, 0x38, temp); if(temp & 0x01) ivideo->vbflags |= TV_PAL; else ivideo->vbflags |= TV_NTSC; } else { inSISIDXREG(SISCR, 0x79, temp); if(temp & 0x20) ivideo->vbflags |= TV_PAL; else ivideo->vbflags |= TV_NTSC; } } } /* Copy forceCRT1 option to CRT1off if option is given */ if(ivideo->sisfb_forcecrt1 != -1) { ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1; }}/* ------------------ Sensing routines ------------------ */static BOOLEAN __devinitsisfb_test_DDC1(struct sis_video_info *ivideo){ unsigned short old; int count = 48; old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr); do { if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break; } while(count--); return (count == -1) ? FALSE : TRUE;}static void __devinitsisfb_sense_crt1(struct sis_video_info *ivideo){ BOOLEAN mustwait = FALSE; u8 sr1F, cr17;#ifdef CONFIG_FB_SIS_315 u8 cr63=0;#endif u16 temp = 0xffff; int i; inSISIDXREG(SISSR,0x1F,sr1F); orSISIDXREG(SISSR,0x1F,0x04); andSISIDXREG(SISSR,0x1F,0x3F); if(sr1F & 0xc0) mustwait = TRUE;#ifdef CONFIG_FB_SIS_315 if(ivideo->sisvga_engine == SIS_315_VGA) { inSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,cr63); cr63 &= 0x40; andSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF); }#endif inSISIDXREG(SISCR,0x17,cr17); cr17 &= 0x80; if(!cr17) { orSISIDXREG(SISCR,0x17,0x80); mustwait = TRUE; outSISIDXREG(SISSR, 0x00, 0x01); outSISIDXREG(SISSR, 0x00, 0x03); } if(mustwait) { for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo); }#ifdef CONFIG_FB_SIS_315 if(ivideo->chip >= SIS_330) { andSISIDXREG(SISCR,0x32,~0x20); if(ivideo->chip >= SIS_340) { outSISIDXREG(SISCR, 0x57, 0x4a); } else { outSISIDXREG(SISCR, 0x57, 0x5f); } orSISIDXREG(SISCR, 0x53, 0x02); while((inSISREG(SISINPSTAT)) & 0x01) break; while(!((inSISREG(SISINPSTAT)) & 0x01)) break; if((inSISREG(SISMISCW)) & 0x10) temp = 1; andSISIDXREG(SISCR, 0x53, 0xfd); andSISIDXREG(SISCR, 0x57, 0x00); }#endif if(temp == 0xffff) { i = 3; do { temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2); } while(((temp == 0) || (temp == 0xffff)) && i--); if((temp == 0) || (temp == 0xffff)) { if(sisfb_test_DDC1(ivideo)) temp = 1; } } if((temp) && (temp != 0xffff)) { orSISIDXREG(SISCR,0x32,0x20); }#ifdef CONFIG_FB_SIS_315 if(ivideo->sisvga_engine == SIS_315_VGA) { setSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF,cr63); }#endif setSISIDXREG(SISCR,0x17,0x7F,cr17); outSISIDXREG(SISSR,0x1F,sr1F);}/* Determine and detect attached devices on SiS30x */static void __devinitSiS_SenseLCD(struct sis_video_info *ivideo){ unsigned char buffer[256]; unsigned short temp, realcrtno, i; u8 reg, cr37 = 0, paneltype = 0; u16 xres, yres; ivideo->SiS_Pr.PanelSelfDetected = FALSE; /* LCD detection only for TMDS bridges */ if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE)) return; if(ivideo->vbflags2 & VB2_30xBDH) return; /* If LCD already set up by BIOS, skip it */ inSISIDXREG(SISCR, 0x32, reg); if(reg & 0x08) return; realcrtno = 1; if(ivideo->SiS_Pr.DDCPortMixup) realcrtno = 0; /* Check DDC capabilities */ temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, realcrtno, 0, &buffer[0], ivideo->vbflags2); if((!temp) || (temp == 0xffff) || (!(temp & 0x02))) return; /* Read DDC data */ i = 3; /* Number of retrys */ do { temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, realcrtno, 1, &buffer[0], ivideo->vbflags2); } while((temp) && i--); if(temp) return; /* No digital device */ if(!(buffer[0x
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -