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

📄 sis_main.c

📁 linux下的VIDEO接口驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif	}	return 0;}static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,		      struct fb_info *info){	unsigned int htotal =		var->left_margin + var->xres + var->right_margin +		var->hsync_len;	unsigned int vtotal = 0; /* TW */	/*	var->upper_margin + var->yres + var->lower_margin +		var->vsync_len;     */	double drate = 0, hrate = 0;	int found_mode = 0;	int old_mode;	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {		vtotal = var->upper_margin + var->yres + var->lower_margin +		         var->vsync_len;   /* TW */		vtotal <<= 1;	} else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {		vtotal = var->upper_margin + var->yres + var->lower_margin +		         var->vsync_len;   /* TW */		vtotal <<= 2;	} else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {		vtotal = var->upper_margin + (var->yres/2) + var->lower_margin +		         var->vsync_len;   /* TW */		/* var->yres <<= 1; */ /* TW */	} else 	vtotal = var->upper_margin + var->yres + var->lower_margin +		         var->vsync_len;	if (!(htotal) || !(vtotal)) {		DPRINTK("sisfb: Invalid 'var' information\n");		return -EINVAL;	}	drate = 1E12 / var->pixclock;	hrate = drate / htotal;	ivideo.refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);	DPRINTK("sisfb: Change mode to %dx%dx%d-%dMHz\n",		var->xres,var->yres,var->bits_per_pixel,ivideo.refresh_rate);	old_mode = sisfb_mode_idx;	sisfb_mode_idx = 0;	while ((sisbios_mode[sisfb_mode_idx].mode_no != 0)	       && (sisbios_mode[sisfb_mode_idx].xres <= var->xres)) {		if ((sisbios_mode[sisfb_mode_idx].xres == var->xres)		    && (sisbios_mode[sisfb_mode_idx].yres == var->yres)		    && (sisbios_mode[sisfb_mode_idx].bpp == var->bits_per_pixel)) {			sisfb_mode_no = sisbios_mode[sisfb_mode_idx].mode_no;			found_mode = 1;			break;		}		sisfb_mode_idx++;	}	if (found_mode)		sisfb_validate_mode();	else		sisfb_mode_idx = -1;       	if (sisfb_mode_idx < 0) {		DPRINTK("sisfb: sisfb does not support mode %dx%d-%d\n", var->xres,		       var->yres, var->bits_per_pixel);		sisfb_mode_idx = old_mode;		return -EINVAL;	}	if (sisfb_search_refresh_rate(ivideo.refresh_rate) == 0) {		sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;		ivideo.refresh_rate = 60;	}	if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {		sisfb_pre_setmode();		if (SiSSetMode(&sishw_ext, sisfb_mode_no) == 0) {			DPRINTK("sisfb: Setting mode[0x%x]: failed\n", sisfb_mode_no);			return -1;		}		vgawb(SEQ_ADR, IND_SIS_PASSWORD);		vgawb(SEQ_DATA, SIS_PASSWORD);		sisfb_post_setmode();		DPRINTK("sisfb: Set new mode: %dx%dx%d-%d \n", sisbios_mode[sisfb_mode_idx].xres,			sisbios_mode[sisfb_mode_idx].yres, sisbios_mode[sisfb_mode_idx].bpp,			ivideo.refresh_rate);		ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;		ivideo.video_vwidth = ivideo.video_width = sisbios_mode[sisfb_mode_idx].xres;		ivideo.video_vheight = ivideo.video_height = sisbios_mode[sisfb_mode_idx].yres;		ivideo.org_x = ivideo.org_y = 0;		video_linelength =		    ivideo.video_width * (ivideo.video_bpp >> 3);	}	return 0;}static void sisfb_set_disp(int con, struct fb_var_screeninfo *var){	struct fb_fix_screeninfo fix;	struct display *display;	struct display_switch *sw;	u32 flags;	if (con >= 0)		display = &fb_display[con];	else		display = &disp;		sisfb_get_fix(&fix, con, 0);	display->screen_base = ivideo.video_vbase;	display->visual = fix.visual;	display->type = fix.type;	display->type_aux = fix.type_aux;	display->ypanstep = fix.ypanstep;	display->ywrapstep = fix.ywrapstep;	display->line_length = fix.line_length;	display->next_line = fix.line_length;	display->can_soft_blank = 0;	display->inverse = sisfb_inverse;	display->var = *var;	save_flags(flags);	switch (ivideo.video_bpp) {#ifdef FBCON_HAS_CFB8	   case 8:		sw = &fbcon_cfb8;		break;#endif#ifdef FBCON_HAS_CFB16	   case 15:	   case 16:		sw = &fbcon_cfb16;		display->dispsw_data = fbcon_cmap.cfb16;		break;#endif#ifdef FBCON_HAS_CFB24	   case 24:		sw = &fbcon_cfb24;		display->dispsw_data = fbcon_cmap.cfb24;		break;#endif#ifdef FBCON_HAS_CFB32	   case 32:		sw = &fbcon_cfb32;		display->dispsw_data = fbcon_cmap.cfb32;		break;#endif	   default:		sw = &fbcon_dummy;		return;	}	memcpy(&sisfb_sw, sw, sizeof(*sw));	display->dispsw = &sisfb_sw;	restore_flags(flags);	display->scrollmode = SCROLL_YREDRAW;	sisfb_sw.bmove = fbcon_redraw_bmove;}static void sisfb_do_install_cmap(int con, struct fb_info *info){	if (con != currcon)		return;	if (fb_display[con].cmap.len)		fb_set_cmap(&fb_display[con].cmap, 1, sis_setcolreg, info);	else		fb_set_cmap(fb_default_cmap(video_cmap_len), 1,			    sis_setcolreg, info);}/* --------------- Chip-dependent Routines --------------------------- */#ifdef CONFIG_FB_SIS_300 /* for SiS 300/630/540/730 */static int sisfb_get_dram_size_300(void){	struct pci_dev *pdev = NULL;	int pdev_valid = 0;	u8  pci_data, reg;	u16 nbridge_id;	switch (ivideo.chip) {	   case SIS_540:		nbridge_id = PCI_DEVICE_ID_SI_540;		break;	   case SIS_630:		nbridge_id = PCI_DEVICE_ID_SI_630;		break;	   case SIS_730:		nbridge_id = PCI_DEVICE_ID_SI_730;		break;	   default:		nbridge_id = 0;		break;	}	if (nbridge_id == 0) {  /* 300 */		vgawb(SEQ_ADR, IND_SIS_DRAM_SIZE);		ivideo.video_size =		        ((unsigned int) ((vgarb(SEQ_DATA) & SIS_DRAM_SIZE_MASK) + 1) << 20);	} else {		/* 540, 630, 730 */		pci_for_each_dev(pdev) {			if ((pdev->vendor == PCI_VENDOR_ID_SI) 				&& (pdev->device == nbridge_id)) {				pci_read_config_byte(pdev, IND_BRI_DRAM_STATUS, &pci_data);				pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;				ivideo.video_size = (unsigned int)(1 << (pci_data+21));				pdev_valid = 1;					reg = SIS_DATA_BUS_64 << 6;				vgawb(SEQ_ADR, IND_SIS_DRAM_SIZE);				switch (pci_data) {				   case BRI_DRAM_SIZE_2MB:					reg |= SIS_DRAM_SIZE_2MB;					break;				   case BRI_DRAM_SIZE_4MB:					reg |= SIS_DRAM_SIZE_4MB;					break;				   case BRI_DRAM_SIZE_8MB:					reg |= SIS_DRAM_SIZE_8MB;					break;				   case BRI_DRAM_SIZE_16MB:					reg |= SIS_DRAM_SIZE_16MB;					break;				   case BRI_DRAM_SIZE_32MB:					reg |= SIS_DRAM_SIZE_32MB;					break;				   case BRI_DRAM_SIZE_64MB:					reg |= SIS_DRAM_SIZE_64MB;					break;				}				vgawb(SEQ_DATA, reg);				break;			}  		}   			if (!pdev_valid)			return -1;	}	return 0;}static void sisfb_detect_VB_connect_300(){	u8 sr16, sr17, cr32, temp;	vgawb(SEQ_ADR, IND_SIS_SCRATCH_REG_17);	sr17 = vgarb(SEQ_DATA);	vgawb(CRTC_ADR, IND_SIS_SCRATCH_REG_CR32);	cr32 = vgarb(CRTC_DATA);	ivideo.TV_plug = ivideo.TV_type = 0;	if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) {		if ((sr17 & 0x01) && !sisfb_crt1off)			sisfb_crt1off = 0;		else {			if (sr17 & 0x0E)				sisfb_crt1off = 1;			else				sisfb_crt1off = 0;		}		if (sisfb_crt2type != -1)			/* TW: override detected CRT2 type */			ivideo.disp_state = sisfb_crt2type;		else if (sr17 & 0x08 )			ivideo.disp_state = DISPTYPE_CRT2;		else if (sr17 & 0x02)			ivideo.disp_state = DISPTYPE_LCD;		else if (sr17 & 0x04)			ivideo.disp_state = DISPTYPE_TV;		else			ivideo.disp_state = 0;		if (sr17 & 0x20)			ivideo.TV_plug = TVPLUG_SVIDEO;		else if (sr17 & 0x10)			ivideo.TV_plug = TVPLUG_COMPOSITE;		vgawb(SEQ_ADR, IND_SIS_SCRATCH_REG_16);		sr16 = vgarb(SEQ_DATA);		if (sr16 & 0x20)			ivideo.TV_type = TVMODE_PAL;		else			ivideo.TV_type = TVMODE_NTSC;	} else {		if ((cr32 & SIS_CRT1) && !sisfb_crt1off)			sisfb_crt1off = 0;		else {			if (cr32 & 0x5F)				sisfb_crt1off = 1;			else				sisfb_crt1off = 0;		}		if (sisfb_crt2type != -1)			/* TW: override detected CRT2 type */			ivideo.disp_state = sisfb_crt2type;		else if (cr32 & SIS_VB_CRT2)			ivideo.disp_state = DISPTYPE_CRT2;		else if (cr32 & SIS_VB_LCD)			ivideo.disp_state = DISPTYPE_LCD;		else if (cr32 & SIS_VB_TV)			ivideo.disp_state = DISPTYPE_TV;		else			ivideo.disp_state = 0;		/* TW: Detect TV plug & type anyway */		if (cr32 & SIS_VB_HIVISION) {			ivideo.TV_type = TVMODE_HIVISION;			ivideo.TV_plug = TVPLUG_SVIDEO;		}		else if (cr32 & SIS_VB_SVIDEO)			ivideo.TV_plug = TVPLUG_SVIDEO;		else if (cr32 & SIS_VB_COMPOSITE)			ivideo.TV_plug = TVPLUG_COMPOSITE;		else if (cr32 & SIS_VB_SCART)			ivideo.TV_plug = TVPLUG_SCART;		if (ivideo.TV_type == 0) {			// Eden Chen			//temp = *((u8 *)(sishw_ext.VirtualRomBase+0x52));			//if (temp&0x40) {			//	temp=*((u8 *)(sishw_ext.VirtualRomBase+0x53));				//} else {			vgawb(SEQ_ADR, IND_SIS_POWER_ON_TRAP);			temp = vgarb(SEQ_DATA);			//}			// ~Eden Chen			if (temp & 0x01)				ivideo.TV_type = TVMODE_PAL;			else				ivideo.TV_type = TVMODE_NTSC;		}	}	/* TW: Copy forceCRT1 option to CRT1off if option is given */    	if (sisfb_forcecrt1 != -1) {		vgawb(SEQ_ADR, IND_SIS_SCRATCH_REG_17);    		sr17 = vgarb(SEQ_DATA);    		if (sisfb_forcecrt1) {			sisfb_crt1off=0;			sr17 |= 0x80;		} else {			sisfb_crt1off=1;			sr17 &= ~0x80;		}		vgawb(SEQ_DATA, sr17);    	}}static void sisfb_get_VB_type_300(void){	u8 reg;	if (ivideo.chip != SIS_300) {		if (!sisfb_has_VB_300()) {			vgawb(CRTC_ADR, IND_SIS_SCRATCH_REG_CR37);			reg = vgarb(CRTC_DATA);			switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) {			   case SIS_EXTERNAL_CHIP_SIS301:				ivideo.hasVB = HASVB_301;				break;			   case SIS_EXTERNAL_CHIP_LVDS:				ivideo.hasVB = HASVB_LVDS;				break;			   case SIS_EXTERNAL_CHIP_TRUMPION:				ivideo.hasVB = HASVB_TRUMPION;				break;			   case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:				ivideo.hasVB = HASVB_LVDS_CHRONTEL;				break;			   case SIS_EXTERNAL_CHIP_CHRONTEL:				ivideo.hasVB = HASVB_CHRONTEL;				break;			   default:				break;			}		}	} else {		sisfb_has_VB_300();	}	//sishw_ext.hasVB = ivideo.hasVB;}static int sisfb_has_VB_300(void){	// Eden Chen	//u8 sr38, sr39, vb_chipid;	u8 vb_chipid;	//vgawb(SEQ_ADR, IND_SIS_POWER_ON_TRAP);	//sr38 = vgarb(SEQ_DATA);	//vgawb(SEQ_ADR, IND_SIS_POWER_ON_TRAP2);	//sr39 = vgarb(SEQ_DATA);	vgawb(VB_PART4_ADR, 0x0);	vb_chipid = vgarb(VB_PART4_DATA);        	switch (vb_chipid) {	   case 0x01:		ivideo.hasVB = HASVB_301;		break;	   case 0x02:		ivideo.hasVB = HASVB_302;		break;	   case 0x03:		ivideo.hasVB = HASVB_303;		break;	   default:		ivideo.hasVB = HASVB_NONE;		return FALSE;	}	return TRUE;	//if (	//	( (ivideo.chip == SIS_300) && (sr38 & 0x20) )	//	||	//	( (ivideo.chip == SIS_540) && (sr38 & 0x20) && (!(sr39 & 0x80)) )	//	||	//	( (ivideo.chip == SIS_630 ) && (sr38 & 0x20) && (!(sr39 & 0x80)) && 	//		((ivideo.revision_id & 0xf0) < 0x30) && (vb_chipid == 1) ) 	//	||	//	( (ivideo.chip == SIS_630 ) && ((ivideo.revision_id & 0xf0) >= 0x30) && 	//		(vb_chipid == 1) ) 	//	||	//	( (ivideo.chip == SIS_730) && (vb_chipid == 1) ) /* 730 */	//) {	//	ivideo.hasVB = HASVB_301;	//	return TRUE;	//} else {	//	ivideo.hasVB = HASVB_NONE;	//	return FALSE;	//}	// ~Eden Chen}#endif  /* CONFIG_FB_SIS_300 */#ifdef CONFIG_FB_SIS_315    /* for SiS 315H/315PRO/550/650/740 */static int sisfb_get_dram_size_315(void){	struct pci_dev *pdev = NULL;	int pdev_valid = 0;	u8  pci_data;	u8  reg = 0;	if (ivideo.chip == SIS_550 || ivideo.chip == SIS_650) {#ifdef LINUXBIOS		pci_for_each_dev(pdev) {			if ( (pdev->vendor == PCI_VENDOR_ID_SI)				&& ( (pdev->device == PCI_DEVICE_ID_SI_550)				  || (pdev->device == PCI_DEVICE_ID_SI_650))) {				pci_read_config_byte(pdev, IND_BRI_DRAM_STATUS,				                     &pci_data);				pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;				ivideo.video_size =				    (unsigned int)(1 << (pci_data+21));				pdev_valid = 1;				/* TW: Initialize SR14 "by hand" */				vgawb(SEQ_ADR, IND_SIS_DRAM_SIZE);				reg = vgarb(SEQ_DATA) & 0xC0;				switch (pci_data) {				//case BRI_DRAM_SIZE_2MB:				//	reg |= (SIS315_DRAM_SIZE_2MB << 4); break;				   case BRI_DRAM_SIZE_4MB:					reg |= SIS550_DRAM_SIZE_4MB;					break;				   case BRI_DRAM_SIZE_8MB:					reg |= SIS550_DRAM_SIZE_8MB;					break;				   case BRI_DRAM_SIZE_16MB:					reg |= SIS550_DRAM_SIZE_16MB;					break;				   case BRI_DRAM_SIZE_32MB:					reg |= SIS550_DRAM_SIZE_32MB;					break;				   case BRI_DRAM_SIZE_64MB:					reg |= SIS550_DRAM_SIZE_64MB;					break;				   /* case BRI_DRAM_SIZE_128MB:					reg |= (SIS315_DRAM_SIZE_128MB << 4); break; */				}			        /* TODO : set Dual channel and bus width bits here */				vgawb(SEQ_DATA, reg);				break;			}  		}			if (!pdev_valid)			return -1;#else		vgawb(SEQ_ADR, IND_SIS_DRAM_SIZE);		reg = vgarb(SEQ_DATA);		switch (reg & SIS550_DRAM_SIZE_MASK) {		   case SIS550_DRAM_SIZE_4MB:			ivideo.video_size = 0x400000;   break;		   case SIS550_DRAM_SIZE_8MB:			ivideo.video_size = 0x800000;   break;		   case SIS550_DRAM_SIZE_16MB:			ivideo.video_size = 0x1000000;  break;		   case SIS550_DRAM_SIZE_24MB:			ivideo.video_size = 0x1800000;  break;		   case SIS550_DRAM_SIZE_32MB:			ivideo.video_size = 0x2000000;	break;		   case SIS550_DRAM_SIZE_64MB:			ivideo.video_size = 0x4000000;	break;		   case SIS550_DRAM_SIZE_96MB:			ivideo.video_size = 0x6000000;	break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -