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

📄 sis_main.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 5 页
字号:
	u8 cr32, temp=0;	ivideo.TV_plug = ivideo.TV_type = 0;        switch(ivideo.hasVB) {	  case HASVB_LVDS_CHRONTEL:	  case HASVB_CHRONTEL:	     SiS_SenseCh();	     break;	  case HASVB_301:	  case HASVB_302:	     SiS_Sense30x();	     break;	}	inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR32, cr32);	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 with option */		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;	if(sisfb_tvplug != -1)		/* PR/TW: Override with option */	        ivideo.TV_plug = sisfb_tvplug;#ifdef oldHV	else if (cr32 & SIS_VB_HIVISION) {		ivideo.TV_type = TVMODE_HIVISION;		ivideo.TV_plug = TVPLUG_SVIDEO;	}#endif	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) {	    /* TW: PAL/NTSC changed for 650 */	    if(ivideo.chip <= SIS_315PRO) {                inSISIDXREG(SISCR, 0x38, temp);		if(temp & 0x10)			ivideo.TV_type = TVMODE_PAL;		else			ivideo.TV_type = TVMODE_NTSC;	    } else {	        inSISIDXREG(SISCR, 0x79, temp);		if(temp & 0x20)			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) {    		if (sisfb_forcecrt1) sisfb_crt1off = 0;		else   	             sisfb_crt1off = 1;    	}}static void sisfb_get_VB_type_315(void){	u8 reg;		if (!sisfb_has_VB_315()) {		        inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR37, reg);			/* TW: CR37 changed on 310/325 series */			switch ((reg & SIS_EXTERNAL_CHIP_MASK) >> 1) {			   case SIS_EXTERNAL_CHIP_SIS301:				ivideo.hasVB = HASVB_301;				break;			   case SIS310_EXTERNAL_CHIP_LVDS:				ivideo.hasVB = HASVB_LVDS;				break;			   case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:				ivideo.hasVB = HASVB_LVDS_CHRONTEL;				break;			   default:				break;			}		}}static int sisfb_has_VB_315(void){	u8 vb_chipid;	inSISIDXREG(SISPART4, 0x00, vb_chipid);	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;}#endif   /* CONFIG_FB_SIS_315 *//* -------------- Sensing routines --------------- *//* TW: Determine and detect attached devices on SiS30x */intSISDoSense(int tempbl, int tempbh, int tempcl, int tempch){    int temp,i;    outSISIDXREG(SISPART4,0x11,tempbl);    temp = tempbh | tempcl;    setSISIDXREG(SISPART4,0x10,0xe0,temp);    for(i=0; i<10; i++) SiS_LongWait(&SiS_Pr);    tempch &= 0x7f;    inSISIDXREG(SISPART4,0x03,temp);    temp ^= 0x0e;    temp &= tempch;    return(temp);}voidSiS_Sense30x(void){  u8 backupP4_0d;  u8 testsvhs_tempbl, testsvhs_tempbh;  u8 testsvhs_tempcl, testsvhs_tempch;  u8 testcvbs_tempbl, testcvbs_tempbh;  u8 testcvbs_tempcl, testcvbs_tempch;  int myflag, result;  inSISIDXREG(SISPART4,0x0d,backupP4_0d);  outSISIDXREG(SISPART4,0x0d,(backupP4_0d | 0x04));  if(sisvga_engine == SIS_300_VGA) {        testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;	testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;	if((sishw_ext.ujVBChipID != VB_CHIP_301) &&	   (sishw_ext.ujVBChipID != VB_CHIP_302) ) {	   testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;	   testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;	}	inSISIDXREG(SISPART4,0x01,myflag);	if(myflag & 0x04) {	   testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;	   testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;	}	testsvhs_tempch = 0x06;	testsvhs_tempcl = 0x04;	testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;  } else if((ivideo.chip == SIS_315) ||    	    (ivideo.chip == SIS_315H) ||	    (ivideo.chip == SIS_315PRO)) {        testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xb9;	testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xb3;	if((sishw_ext.ujVBChipID != VB_CHIP_301) &&	   (sishw_ext.ujVBChipID != VB_CHIP_302) ) {	      testsvhs_tempbh = 0x01; testsvhs_tempbl = 0x6b;	      testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x74;	}	inSISIDXREG(SISPART4,0x01,myflag);	if(myflag & 0x04) {	   testsvhs_tempbh = 0x00; testsvhs_tempbl = 0xdd;	   testcvbs_tempbh = 0x00; testcvbs_tempbl = 0xee;	}	testsvhs_tempch = 0x06;	testsvhs_tempcl = 0x04;	testcvbs_tempch = 0x08; testcvbs_tempcl = 0x04;    } else {        testsvhs_tempbh = 0x02; testsvhs_tempbl = 0x00;	testcvbs_tempbh = 0x01; testcvbs_tempbl = 0x00;	testsvhs_tempch = 0x04;	testsvhs_tempcl = 0x08;	testcvbs_tempch = 0x08; testcvbs_tempcl = 0x08;    }    result = SISDoSense(testsvhs_tempbl, testsvhs_tempbh,                        testsvhs_tempcl, testsvhs_tempch);    if(result) {        printk(KERN_INFO "sisfb: Detected TV connected to SVHS output\n");        /* TW: So we can be sure that there IS a SVHS output */	ivideo.TV_plug = TVPLUG_SVIDEO;	orSISIDXREG(SISCR, 0x32, 0x02);    }    if(!result) {        result = SISDoSense(testcvbs_tempbl, testcvbs_tempbh,	                    testcvbs_tempcl, testcvbs_tempch);	if(result) {	    printk(KERN_INFO "sisfb: Detected TV connected to CVBS output\n");	    /* TW: So we can be sure that there IS a CVBS output */	    ivideo.TV_plug = TVPLUG_COMPOSITE;	    orSISIDXREG(SISCR, 0x32, 0x01);	}    }    SISDoSense(0, 0, 0, 0);    outSISIDXREG(SISPART4,0x0d,backupP4_0d);}/* TW: Determine and detect attached TV's on Chrontel */voidSiS_SenseCh(void){   u8 temp1;#ifdef CONFIG_FB_SIS_315   u8 temp2;#endif   if(ivideo.chip < SIS_315H) {#ifdef CONFIG_FB_SIS_300       SiS_Pr.SiS_IF_DEF_CH70xx = 1;		/* TW: Chrontel 7005 */       temp1 = SiS_GetCH700x(&SiS_Pr, 0x25);       if ((temp1 >= 50) && (temp1 <= 100)) {	   /* TW: Read power status */	   temp1 = SiS_GetCH700x(&SiS_Pr, 0x0e);	   if((temp1 & 0x03) != 0x03) {     	        /* TW: Power all outputs */		SiS_SetCH70xxANDOR(&SiS_Pr, 0x030E,0xF8);	   }	   /* TW: Sense connected TV devices */	   SiS_SetCH700x(&SiS_Pr, 0x0110);	   SiS_SetCH700x(&SiS_Pr, 0x0010);	   temp1 = SiS_GetCH700x(&SiS_Pr, 0x10);	   if(!(temp1 & 0x08)) {		printk(KERN_INFO		   "sisfb: Chrontel: Detected TV connected to SVHS output\n");		/* TW: So we can be sure that there IS a SVHS output */		ivideo.TV_plug = TVPLUG_SVIDEO;		orSISIDXREG(SISCR, 0x32, 0x02);	   } else if (!(temp1 & 0x02)) {		printk(KERN_INFO		   "sisfb: Chrontel: Detected TV connected to CVBS output\n");		/* TW: So we can be sure that there IS a CVBS output */		ivideo.TV_plug = TVPLUG_COMPOSITE;		orSISIDXREG(SISCR, 0x32, 0x01);	   } else { 		SiS_SetCH70xxANDOR(&SiS_Pr, 0x010E,0xF8);	   }       } else if(temp1 == 0) {	  SiS_SetCH70xxANDOR(&SiS_Pr, 0x010E,0xF8);       }#endif   } else {#ifdef CONFIG_FB_SIS_315	SiS_Pr.SiS_IF_DEF_CH70xx = 2;		/* TW: Chrontel 7019 */        temp1 = SiS_GetCH701x(&SiS_Pr, 0x49);	SiS_SetCH701x(&SiS_Pr, 0x2049);	SiS_DDC2Delay(&SiS_Pr, 0x96);	temp2 = SiS_GetCH701x(&SiS_Pr, 0x20);	temp2 |= 0x01;	SiS_SetCH701x(&SiS_Pr, (temp2 << 8) | 0x20);	SiS_DDC2Delay(&SiS_Pr, 0x96);	temp2 ^= 0x01;	SiS_SetCH701x(&SiS_Pr, (temp2 << 8) | 0x20);	SiS_DDC2Delay(&SiS_Pr, 0x96);	temp2 = SiS_GetCH701x(&SiS_Pr, 0x20);	SiS_SetCH701x(&SiS_Pr, (temp1 << 8) | 0x49);        temp1 = 0;	if(temp2 & 0x02) temp1 |= 0x01;	if(temp2 & 0x10) temp1 |= 0x01;	if(temp2 & 0x04) temp1 |= 0x02;	if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;	switch(temp1) {	case 0x01:	     printk(KERN_INFO		"sisfb: Chrontel: Detected TV connected to CVBS output\n");	     ivideo.TV_plug = TVPLUG_COMPOSITE;	     orSISIDXREG(SISCR, 0x32, 0x01);             break;	case 0x02:	     printk(KERN_INFO		"sisfb: Chrontel: Detected TV connected to SVHS output\n");	     ivideo.TV_plug = TVPLUG_SVIDEO;	     orSISIDXREG(SISCR, 0x32, 0x02);             break;	case 0x04:	     /* TW: This should not happen */	     printk(KERN_INFO		"sisfb: Chrontel: Detected TV connected to SCART output!?\n");             break;	}#endif   }}/* --------------------- Heap Routines ------------------------------- */static int sisfb_heap_init(void){	SIS_OH *poh;	u8 temp=0;#ifdef CONFIG_FB_SIS_315	int            agp_enabled = 1;	u32            agp_size;	unsigned long *cmdq_baseport = 0;	unsigned long *read_port = 0;	unsigned long *write_port = 0;	SIS_CMDTYPE    cmd_type;#ifndef AGPOFF	agp_kern_info  *agp_info;	agp_memory     *agp;	u32            agp_phys;#endif#endif/* TW: The heap start is either set manually using the "mem" parameter, or *     defaults as follows: *     -) If more than 16MB videoRAM available, let our heap start at 12MB. *     -) If more than  8MB videoRAM available, let our heap start at  8MB. *     -) If 4MB or less is available, let it start at 4MB. *     This is for avoiding a clash with X driver which uses the beginning *     of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem *     in XF86Config-4. *     The heap start can also be specified by parameter "mem" when starting the sisfb *     driver. sisfb mem=1024 lets heap starts at 1MB, etc. */     if ((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {        if (ivideo.video_size > 0x1000000) {	        ivideo.heapstart = 0xc00000;	} else if (ivideo.video_size > 0x800000) {	        ivideo.heapstart = 0x800000;	} else {		ivideo.heapstart = 0x400000;	}     } else {           ivideo.heapstart = sisfb_mem * 1024;     }     sisfb_heap_start =	       (unsigned long) (ivideo.video_vbase + ivideo.heapstart);     printk(KERN_INFO "sisfb: Memory heap starting at %dK\n",     					(int)(ivideo.heapstart / 1024));     sisfb_heap_end = (unsigned long) ivideo.video_vbase + ivideo.video_size;     sisfb_heap_size = sisfb_heap_end - sisfb_heap_start;#ifdef CONFIG_FB_SIS_315     if (sisvga_engine == SIS_315_VGA) {        /* TW: Now initialize the 310 series' command queue mode.	 * On 310/325, there are three queue modes available which	 * are chosen by setting bits 7:5 in SR26:	 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep	 *    track of the queue, the FIFO, command parsing and so	 *    on. This is the one comparable to the 300 series.	 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will	 *    have to do queue management himself. Register 0x85c4 will	 *    hold the location of the next free queue slot, 0x85c8	 *    is the "queue read pointer" whose way of working is	 *    unknown to me. Anyway, this mode would require a	 *    translation of the MMIO commands to some kind of	 *    accelerator assembly and writing these commands	 *    to the memory location pointed to by 0x85c4.	 *    We will not use this, as nobody knows how this	 *    "assembly" works, and as it would require a complete	 *    re-write of the accelerator code.	 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the	 *    queue in AGP memory space.	 *	 * SR26 bit 4 is called "Bypass H/W queue".	 * SR26 bit 1 is called "Enable Command Queue Auto Correction"	 * SR26 bit 0 resets the queue	 * Size of queue memory is encoded in bits 3:2 like this:	 *    00  (0x00)  512K	 *    01  (0x04)  1M	 *    10  (0x08)  2M	 *    11  (0x0C)  4M	 * The queue location is to be written to 0x85C0.	 *         */	cmdq_baseport = (unsigned long *)(ivideo.mmio_vbase + MMIO_QUEUE_PHYBASE);	write_port    = (unsigned long *)(ivideo.mmio_vbase + MMIO_QUEUE_WRITEPORT);	read_port     = (unsigned long *)(ivideo.mmio_vbase + MMIO_QUEUE_READPORT);	DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);	agp_size  = COMMAND_QUEUE_AREA_SIZE;#ifndef AGPOFF	if (sisfb_queuemode == AGP_CMD_QUEUE) {		agp_info = vmalloc(sizeof(agp_kern_info));		memset((void*)agp_info, 0x00, sizeof(agp_kern_info));		agp_copy_info(agp_info);		agp_backend_acquire();		agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE,					  AGP_NORMAL_MEMORY);		if (agp == NULL) {			DPRINTK("sisfb: Allocating AGP buffer failed.\n");			agp_enabled = 0;		} else {			if (agp_bind_memory(agp, agp->pg_start) != 0) {				DPRINTK("sisfb: AGP: Failed to bind memory\n");				/* TODO: Free AGP memory here */				agp_enabled = 0;			} else {				agp_enable(0);			}		}	}#else	agp_enabled = 0;#endif	/* TW: Now select the queue mode */	if ((agp_enabled) && (sisfb_queuemode == AGP_CMD_QUEUE)) {		cmd_type = AGP_CMD_QUEUE;		printk(KERN_INFO "sisfb: Using AGP queue mode\n");/*	} else if (sisfb_heap_size >= COMMAND_QUEUE_AREA_SIZE)  */        } else if (sisfb_queuemode == VM_CMD_QUEUE) {		cmd_type = VM_CMD_QUEUE;		printk(KERN_INFO "sisfb: Using VRAM queue mode\n");	} else {		printk(KERN_INFO "sisfb: Using MMIO queue mode\n");		cmd_type = MMIO_CMD;	}	switch (agp_size) {	   case 0x80000:		temp = SIS_CMD_QUEUE_SIZE_512k;		break;	   case 0x100000:		temp = SIS_CMD_QUEUE_SIZE_1M;		break;	   case 0x200000:		temp = SIS_CMD_QUEUE_SIZE_2M;		break;	   case 0x400000:		temp = SIS_CMD_QUEUE_SIZE_4M;		break;	}	switch (cmd_type) {	   case AGP_CMD_QUEUE:#ifndef AGPOFF		DPRINTK("sisfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",			agp_info->aper_base, agp->physical, agp_size/1024);		agp_phys = agp_info->aper_base + agp->physical;		outSISIDXREG(SISCR,  IND_SIS_AGP_IO_PAD, 0);		outSISIDXREG(SISCR,  IND_SIS_AGP_IO_PAD, SIS_AGP_2X);                outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);		*write_port = *read_port;		temp |= SIS_AGP_CMDQUEUE_ENABLE;		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);		*cmdq_baseport = agp_phys;		sisfb_caps |= AGP_CMD_QUEUE_CAP;#endif		break;	   case VM_CMD_QUEUE:		sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;		sisfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);		*write_port = *read_port;		temp |= SIS_VRAM_CMDQUEUE_ENABLE;		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);		*cmdq_baseport = ivideo.video_size - COMMAND_QU

⌨️ 快捷键说明

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