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

📄 sis_main.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
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, &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 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 + -