📄 sis_main.c
字号:
sisfb_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 bool __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);}static void __devinitsisfb_sense_crt1(struct sis_video_info *ivideo){ bool 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[0x14] & 0x80)) return; /* First detailed timing preferred timing? */ if(!(buffer[0x18] & 0x02)) return; xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4); yres = buffer[0x3b] | ((buffer[0x3d] & 0xf0) << 4); switch(xres) { case 1024: if(yres == 768) paneltype = 0x02; break; case 1280: if(yres == 1024) paneltype = 0x03; break; case 1600: if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC)) paneltype = 0x0b; break; } if(!paneltype) return; if(buffer[0x23]) cr37 |= 0x10; if((buffer[0x47] & 0x18) == 0x18) cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20); else cr37 |= 0xc0; outSISIDXREG(SISCR, 0x36, paneltype); cr37 &= 0xf1; setSISIDXREG(SISCR, 0x37, 0x0c, cr37); orSISIDXREG(SISCR, 0x32, 0x08); ivideo->SiS_Pr.PanelSelfDetected = true;}static int __devinitSISDoSense(struct sis_video_info *ivideo, u16 type, u16 test){ int temp, mytest, result, i, j; for(j = 0; j < 10; j++) { result = 0; for(i = 0; i < 3; i++) { mytest = test; outSISIDXREG(SISPART4,0x11,(type & 0x00ff)); temp = (type >> 8) | (mytest & 0x00ff); setSISIDXREG(SISPART4,0x10,0xe0,temp); SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500); mytest >>= 8; mytest &= 0x7f; inSISIDXREG(SISPART4,0x03,temp); temp ^= 0x0e; temp &= mytest; if(temp == mytest) result++;#if 1 outSISIDXREG(SISPART4,0x11,0x00); andSISIDXREG(SISPART4,0x10,0xe0); SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);#endif } if((result == 0) || (result >= 2)) break; } return result;}static void __devinitSiS_Sense30x(struct sis_video_info *ivideo){ u8 backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0; u16 svhs=0, svhs_c=0; u16 cvbs=0, cvbs_c=0; u16 vga2=0, vga2_c=0; int myflag, result; char stdstr[] = "sisfb: Detected"; char tvstr[] = "TV connected to"; if(ivideo->vbflags2 & VB2_301) { svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1; inSISIDXREG(SISPART4,0x01,myflag); if(myflag & 0x04) { svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd; } } else if(ivideo->vbflags2 & (VB2_301B | VB2_302B)) { svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190; } else if(ivideo->vbflags2 & (VB2_301LV | VB2_302LV)) { svhs = 0x0200; cvbs = 0x0100; } else if(ivideo->vbflags2 & (VB2_301C | VB2_302ELV | VB2_307T | VB2_307LV)) { svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190; } else return; vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804; if(ivideo->vbflags & (VB2_301LV|VB2_302LV|VB2_302ELV|VB2_307LV)) { svhs_c = 0x0408; cvbs_c = 0x0808; } biosflag = 2; if(ivideo->haveXGIROM) { biosflag = ivideo->bios_abase[0x58] & 0x03; } else if(ivideo->newrom) { if(ivideo->bios_abase[0x5d] & 0x04) biosflag |= 0x01; } else if(ivideo->sisvga_engine == SIS_300_VGA) { if(ivideo->bios_abase) { biosflag = ivideo->bios_abase[0xfe] & 0x03; } } if(ivideo->chip == SIS_300) { inSISIDXREG(SISSR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -