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

📄 sis_main.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 5 页
字号:
}static u8 sisfb_search_refresh_rate(unsigned int rate, int mode_idx){	u16 xres, yres;	int i = 0;	xres = sisbios_mode[mode_idx].xres;	yres = sisbios_mode[mode_idx].yres;	sisfb_rate_idx = 0;	while ((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {		if ((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {			if (sisfb_vrate[i].refresh == rate) {				sisfb_rate_idx = sisfb_vrate[i].idx;				break;			} else if (sisfb_vrate[i].refresh > rate) {				if ((sisfb_vrate[i].refresh - rate) <= 3) {					DPRINTK("sisfb: Adjusting rate from %d up to %d\n",						rate, sisfb_vrate[i].refresh);					sisfb_rate_idx = sisfb_vrate[i].idx;					ivideo.refresh_rate = sisfb_vrate[i].refresh;				} else if (((rate - sisfb_vrate[i-1].refresh) <= 2)						&& (sisfb_vrate[i].idx != 1)) {					DPRINTK("sisfb: Adjusting rate from %d down to %d\n",						rate, sisfb_vrate[i-1].refresh);					sisfb_rate_idx = sisfb_vrate[i-1].idx;					ivideo.refresh_rate = sisfb_vrate[i-1].refresh;				} 				break;			} else if((rate - sisfb_vrate[i].refresh) <= 2) {				DPRINTK("sisfb: Adjusting rate from %d down to %d\n",						rate, sisfb_vrate[i].refresh);	           		sisfb_rate_idx = sisfb_vrate[i].idx;		   		break;	       		}		}		i++;	}	if (sisfb_rate_idx > 0) {		return sisfb_rate_idx;	} else {		printk(KERN_INFO			"sisfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);		return 0;	}}static void sisfb_search_tvstd(const char *name){	int i = 0;	if(name == NULL)		return;	while (sis_tvtype[i].type_no != -1) {		if (!strcmp(name, sis_tvtype[i].name)) {			ivideo.vbflags |= sis_tvtype[i].type_no;			break;		}		i++;	}}static BOOLEAN sisfb_bridgeisslave(void){   unsigned char P1_00;   if(!(ivideo.vbflags & VB_VIDEOBRIDGE)) return FALSE;   inSISIDXREG(SISPART1,0x00,P1_00);   if( ((sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||       ((sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {	   return TRUE;   } else {           return FALSE;   }}static BOOLEAN sisfbcheckvretracecrt1(void){   unsigned char temp;   inSISIDXREG(SISCR,0x17,temp);   if(!(temp & 0x80)) return FALSE;      if(sisvga_engine == SIS_315_VGA) {      inSISIDXREG(SISSR,0x1f,temp);      if(temp & 0xc0) return FALSE;   }   if(inSISREG(SISINPSTAT) & 0x08) return TRUE;   else 			   return FALSE;}static BOOLEAN sisfbcheckvretracecrt2(void){   unsigned char temp, reg;   switch(sisvga_engine) {   case SIS_300_VGA:   	reg = 0x25;	break;   case SIS_315_VGA:   	reg = 0x30;	break;   default:        return FALSE;   }   inSISIDXREG(SISPART1, reg, temp);   if(temp & 0x02) return FALSE;   else 	   return TRUE;}static BOOLEAN sisfb_CheckVBRetrace(void) {   if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {      if(sisfb_bridgeisslave()) {         return(sisfbcheckvretracecrt1());      } else {         return(sisfbcheckvretracecrt2());      }   }    return(sisfbcheckvretracecrt1());}/* ----------- FBDev related routines for all series ----------- */static void sisfb_set_vparms(void){	switch(ivideo.video_bpp) {        case 8:        	ivideo.DstColor = 0x0000;		ivideo.SiS310_AccelDepth = 0x00000000;		ivideo.video_cmap_len = 256;        	break;        case 16:        	ivideo.DstColor = 0x8000;        	ivideo.SiS310_AccelDepth = 0x00010000;		ivideo.video_cmap_len = 16;        	break;        case 32:        	ivideo.DstColor = 0xC000;		ivideo.SiS310_AccelDepth = 0x00020000;		ivideo.video_cmap_len = 16;            	break;	default:		ivideo.video_cmap_len = 16;	        printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo.video_bpp);		ivideo.accel = 0;		break;    	}}static int sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,		      struct fb_info *info){	unsigned int htotal = 0, vtotal = 0; 	double drate = 0, hrate = 0;	int found_mode = 0;	int old_mode;	u32 pixclock;	htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;	vtotal = var->upper_margin + var->lower_margin + var->vsync_len;	pixclock = var->pixclock;	if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {		vtotal += var->yres;		vtotal <<= 1;	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {		vtotal += var->yres;		vtotal <<= 2;	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {		vtotal += var->yres;		vtotal <<= 1;	} else 	vtotal += var->yres;	if(!(htotal) || !(vtotal)) {		DPRINTK("sisfb: Invalid 'var' information\n");		return -EINVAL;	}	if(pixclock && htotal && vtotal) {	   drate = 1E12 / pixclock;	   hrate = drate / htotal;	   ivideo.refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);	} else ivideo.refresh_rate = 60;#if 0	printk(KERN_DEBUG "sisfb: Change mode to %dx%dx%d-%dHz\n",		var->xres,var->yres,var->bits_per_pixel,ivideo.refresh_rate);#endif			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_mode_idx = sisfb_validate_mode(sisfb_mode_idx, ivideo.currentvbflags);	else		sisfb_mode_idx = -1;       	if(sisfb_mode_idx < 0) {		printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,		       var->yres, var->bits_per_pixel);		sisfb_mode_idx = old_mode;		return -EINVAL;	}	if(sisfb_search_refresh_rate(ivideo.refresh_rate, sisfb_mode_idx) == 0) {		sisfb_rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;		ivideo.refresh_rate = 60;	}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	if(((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {#else	if(isactive) {#endif		sisfb_pre_setmode();		if(SiSSetMode(&SiS_Pr, &sishw_ext, sisfb_mode_no) == 0) {			printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", sisfb_mode_no);			return -EINVAL;		}		outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);				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;		ivideo.video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);		ivideo.accel = 0;		if(sisfb_accel) {		   ivideo.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;		}		sisfb_set_vparms();				ivideo.current_width = ivideo.video_width;		ivideo.current_height = ivideo.video_height;		ivideo.current_bpp = ivideo.video_bpp;		ivideo.current_htotal = htotal;		ivideo.current_vtotal = vtotal;		ivideo.current_pixclock = var->pixclock;		ivideo.current_refresh_rate = ivideo.refresh_rate;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)                sisfb_lastrates[sisfb_mode_no] = ivideo.refresh_rate;#endif				sisfb_post_setmode();	}	return 0;}static int sisfb_pan_var(struct fb_var_screeninfo *var){	unsigned int base;	if (var->xoffset > (var->xres_virtual - var->xres)) {		return -EINVAL;	}	if(var->yoffset > (var->yres_virtual - var->yres)) {		return -EINVAL;	}				base = var->yoffset * var->xres_virtual + var->xoffset;		        /* calculate base bpp dep. */        switch(var->bits_per_pixel) {        case 16:        	base >>= 1;        	break;	case 32:            	break;	case 8:        default:        	base >>= 2;            	break;        }		outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);        outSISIDXREG(SISCR, 0x0D, base & 0xFF);	outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);	outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);	if(sisvga_engine == SIS_315_VGA) {		setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);	}        if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {		orSISIDXREG(SISPART1, sisfb_CRT2_write_enable, 0x01);        	outSISIDXREG(SISPART1, 0x06, (base & 0xFF));        	outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));        	outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));		if(sisvga_engine == SIS_315_VGA) {			setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);		}        }	return 0;}static void sisfb_bpp_to_var(struct fb_var_screeninfo *var){	switch(var->bits_per_pixel) {	   case 8:	   	var->red.offset = var->green.offset = var->blue.offset = 0;		var->red.length = var->green.length = var->blue.length = 6;		ivideo.video_cmap_len = 256;		break;	   case 16:		var->red.offset = 11;		var->red.length = 5;		var->green.offset = 5;		var->green.length = 6;		var->blue.offset = 0;		var->blue.length = 5;		var->transp.offset = 0;		var->transp.length = 0;		ivideo.video_cmap_len = 16;		break;	   case 32:		var->red.offset = 16;		var->red.length = 8;		var->green.offset = 8;		var->green.length = 8;		var->blue.offset = 0;		var->blue.length = 8;		var->transp.offset = 24;		var->transp.length = 8;		ivideo.video_cmap_len = 16;		break;	}}void sis_dispinfo(struct ap_data *rec){	rec->minfo.bpp      = ivideo.video_bpp;	rec->minfo.xres     = ivideo.video_width;	rec->minfo.yres     = ivideo.video_height;	rec->minfo.v_xres   = ivideo.video_vwidth;	rec->minfo.v_yres   = ivideo.video_vheight;	rec->minfo.org_x    = ivideo.org_x;	rec->minfo.org_y    = ivideo.org_y;	rec->minfo.vrate    = ivideo.refresh_rate;	rec->iobase         = ivideo.vga_base - 0x30;	rec->mem_size       = ivideo.video_size;	rec->disp_state     = ivideo.disp_state; 	rec->version        = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL; 	rec->hasVB          = ivideo.hasVB;	rec->TV_type        = ivideo.TV_type; 	rec->TV_plug        = ivideo.TV_plug; 	rec->chip           = ivideo.chip;	rec->vbflags	    = ivideo.vbflags;	rec->currentvbflags = ivideo.currentvbflags;}/* ------------ FBDev related routines for 2.4 series ----------- */#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)static void sisfb_crtc_to_var(struct fb_var_screeninfo *var){	u16 VRE, VBE, VRS, VBS, VDE, VT;	u16 HRE, HBE, HRS, HBS, HDE, HT;	u8  sr_data, cr_data, cr_data2, cr_data3, mr_data;	int A, B, C, D, E, F, temp;	double hrate, drate;	inSISIDXREG(SISSR, IND_SIS_COLOR_MODE, sr_data);	if (sr_data & SIS_INTERLACED_MODE)		var->vmode = FB_VMODE_INTERLACED;	else		var->vmode = FB_VMODE_NONINTERLACED;	switch ((sr_data & 0x1C) >> 2) {	   case SIS_8BPP_COLOR_MODE:		var->bits_per_pixel = 8;		break;	   case SIS_16BPP_COLOR_MODE:		var->bits_per_pixel = 16;		break;	   case SIS_32BPP_COLOR_MODE:		var->bits_per_pixel = 32;		break;	}	sisfb_bpp_to_var(var);		inSISIDXREG(SISSR, 0x0A, sr_data);        inSISIDXREG(SISCR, 0x06, cr_data);        inSISIDXREG(SISCR, 0x07, cr_data2);	VT = (cr_data & 0xFF) | ((u16) (cr_data2 & 0x01) << 8) |	     ((u16) (cr_data2 & 0x20) << 4) | ((u16) (sr_data & 0x01) << 10);	A = VT + 2;	inSISIDXREG(SISCR, 0x12, cr_data);	VDE = (cr_data & 0xff) | ((u16) (cr_data2 & 0x02) << 7) |	      ((u16) (cr_data2 & 0x40) << 3) | ((u16) (sr_data & 0x02) << 9);	E = VDE + 1;	inSISIDXREG(SISCR, 0x10, cr_data);	VRS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x04) << 6) |	      ((u16) (cr_data2 & 0x80) << 2) | ((u16) (sr_data & 0x08) << 7);	F = VRS + 1 - E;	inSISIDXREG(SISCR, 0x15, cr_data);	inSISIDXREG(SISCR, 0x09, cr_data3);	if(cr_data3 & 0x80) var->vmode = FB_VMODE_DOUBLE;	VBS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x08) << 5) |	      ((u16) (cr_data3 & 0x20) << 4) | ((u16) (sr_data & 0x04) << 8);	inSISIDXREG(SISCR, 0x16, cr_data);	VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4);	temp = VBE - ((E - 1) & 511);	B = (temp > 0) ? temp : (temp + 512);	inSISIDXREG(SISCR, 0x11, cr_data);	VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);	temp = VRE - ((E + F - 1) & 31);	C = (temp > 0) ? temp : (temp + 32);	D = B - F - C;        var->yres = E;	var->upper_margin = D;	var->lower_margin = F;	var->vsync_len = C;	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {		var->yres <<= 1;		var->upper_margin <<= 1;		var->lower_margin <<= 1;		var->vsync_len <<= 1;	} else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {		var->yres >>= 1;		var->upper_margin >>= 1;		var->lower_margin >>= 1;		var->vsync_len >>= 1;	}	inSISIDXREG(SISSR, 0x0b, sr_data);	inSISIDXREG(SISCR, 0x00, cr_data);	HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8);	A = HT + 5;	inSISIDXREG(SISCR, 0x01, cr_data);	HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6);	E = HDE + 1;	inSISIDXREG(SISCR, 0x04, cr_data);	HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2);	F = HRS - E - 3;	inSISIDXREG(SISCR, 0x02, cr_data);	HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4);	inSISIDXREG(SISSR, 0x0c, sr_data);	inSISIDXREG(SISCR, 0x03, cr_data);	inSISIDXREG(SISCR, 0x05, cr_data2);	HBE = (cr_data & 0x1f) | ((u16) (cr_data2 & 0x80) >> 2) |	      ((u16) (sr_data & 0x03) << 6);	HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);	temp = HBE - ((E - 1) & 255);	B = (temp > 0) ? temp : (temp + 256);	temp = HRE - ((E + F + 3) & 63);	C = (temp > 0) ? temp : (temp + 64);	D = B - F - C;	var->xres = var->xres_virtual = E * 8;	if((var->xres == 320) &&	   (var->yres == 200 || var->yres == 240)) {

⌨️ 快捷键说明

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