⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sis_main.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
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, &reg);		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 + -