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

📄 atyfb_base.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	chip_id = aty_ld_le32(CNFG_CHIP_ID, par);	type = chip_id & CFG_CHIP_TYPE;	rev = (chip_id & CFG_CHIP_REV) >> 24;	switch(par->pci_id) {#ifdef CONFIG_FB_ATY_GX	case PCI_CHIP_MACH64GX:		if(type != 0x00d7)			return -ENODEV;		break;	case PCI_CHIP_MACH64CX:		if(type != 0x0057)			return -ENODEV;		break;#endif#ifdef CONFIG_FB_ATY_CT	case PCI_CHIP_MACH64VT:		switch (rev & 0x07) {		case 0x00:			switch (rev & 0xc0) {			case 0x00:				name = "ATI264VT (A3) (Mach64 VT)";				par->pll_limits.pll_max = 170;				par->pll_limits.mclk = 67;				par->pll_limits.xclk = 67;				par->pll_limits.ecp_max = 80;				par->features = ATI_CHIP_264VT;				break;			case 0x40:				name = "ATI264VT2 (A4) (Mach64 VT)";				par->pll_limits.pll_max = 200;				par->pll_limits.mclk = 67;				par->pll_limits.xclk = 67;				par->pll_limits.ecp_max = 80;				par->features = ATI_CHIP_264VT | M64F_MAGIC_POSTDIV;				break;			}			break;		case 0x01:			name = "ATI264VT3 (B1) (Mach64 VT)";			par->pll_limits.pll_max = 200;			par->pll_limits.mclk = 67;			par->pll_limits.xclk = 67;			par->pll_limits.ecp_max = 80;			par->features = ATI_CHIP_264VTB;			break;		case 0x02:			name = "ATI264VT3 (B2) (Mach64 VT)";			par->pll_limits.pll_max = 200;			par->pll_limits.mclk = 67;			par->pll_limits.xclk = 67;			par->pll_limits.ecp_max = 80;			par->features = ATI_CHIP_264VT3;			break;		}		break;	case PCI_CHIP_MACH64GT:		switch (rev & 0x07) {		case 0x01:			name = "3D RAGE II (Mach64 GT)";			par->pll_limits.pll_max = 170;			par->pll_limits.mclk = 67;			par->pll_limits.xclk = 67;			par->pll_limits.ecp_max = 80;			par->features = ATI_CHIP_264GTB;			break;		case 0x02:			name = "3D RAGE II+ (Mach64 GT)";			par->pll_limits.pll_max = 200;			par->pll_limits.mclk = 67;			par->pll_limits.xclk = 67;			par->pll_limits.ecp_max = 100;			par->features = ATI_CHIP_264GTB;			break;		}		break;#endif	}	PRINTKI("%s [0x%04x rev 0x%02x]\n", name, type, rev);	return 0;}static char ram_dram[] __devinitdata = "DRAM";static char ram_resv[] __devinitdata = "RESV";#ifdef CONFIG_FB_ATY_GXstatic char ram_vram[] __devinitdata = "VRAM";#endif /* CONFIG_FB_ATY_GX */#ifdef CONFIG_FB_ATY_CTstatic char ram_edo[] __devinitdata = "EDO";static char ram_sdram[] __devinitdata = "SDRAM (1:1)";static char ram_sgram[] __devinitdata = "SGRAM (1:1)";static char ram_sdram32[] __devinitdata = "SDRAM (2:1) (32-bit)";static char ram_off[] __devinitdata = "OFF";#endif /* CONFIG_FB_ATY_CT */#ifdef CONFIG_FB_ATY_GXstatic char *aty_gx_ram[8] __devinitdata = {	ram_dram, ram_vram, ram_vram, ram_dram,	ram_dram, ram_vram, ram_vram, ram_resv};#endif /* CONFIG_FB_ATY_GX */#ifdef CONFIG_FB_ATY_CTstatic char *aty_ct_ram[8] __devinitdata = {	ram_off, ram_dram, ram_edo, ram_edo,	ram_sdram, ram_sgram, ram_sdram32, ram_resv};#endif /* CONFIG_FB_ATY_CT */static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, struct atyfb_par *par){	u32 pixclock = var->pixclock;#ifdef CONFIG_FB_ATY_GENERIC_LCD	u32 lcd_on_off;	par->pll.ct.xres = 0;	if (par->lcd_table != 0) {		lcd_on_off = aty_ld_lcd(LCD_GEN_CNTL, par);		if(lcd_on_off & LCD_ON) {			par->pll.ct.xres = var->xres;			pixclock = par->lcd_pixclock;		}	}#endif	return pixclock;}#if defined(CONFIG_PPC)/* *  Apple monitor sense */static int __devinit read_aty_sense(const struct atyfb_par *par){	int sense, i;	aty_st_le32(GP_IO, 0x31003100, par); /* drive outputs high */	__delay(200);	aty_st_le32(GP_IO, 0, par); /* turn off outputs */	__delay(2000);	i = aty_ld_le32(GP_IO, par); /* get primary sense value */	sense = ((i & 0x3000) >> 3) | (i & 0x100);	/* drive each sense line low in turn and collect the other 2 */	aty_st_le32(GP_IO, 0x20000000, par); /* drive A low */	__delay(2000);	i = aty_ld_le32(GP_IO, par);	sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4);	aty_st_le32(GP_IO, 0x20002000, par); /* drive A high again */	__delay(200);	aty_st_le32(GP_IO, 0x10000000, par); /* drive B low */	__delay(2000);	i = aty_ld_le32(GP_IO, par);	sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6);	aty_st_le32(GP_IO, 0x10001000, par); /* drive B high again */	__delay(200);	aty_st_le32(GP_IO, 0x01000000, par); /* drive C low */	__delay(2000);	sense |= (aty_ld_le32(GP_IO, par) & 0x3000) >> 12;	aty_st_le32(GP_IO, 0, par); /* turn off outputs */	return sense;}#endif /* defined(CONFIG_PPC) *//* ------------------------------------------------------------------------- *//* *  CRTC programming */static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc){#ifdef CONFIG_FB_ATY_GENERIC_LCD	if (par->lcd_table != 0) {		if(!M64_HAS(LT_LCD_REGS)) {		    crtc->lcd_index = aty_ld_le32(LCD_INDEX, par);		    aty_st_le32(LCD_INDEX, crtc->lcd_index, par);		}		crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par);		crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par);		/* switch to non shadow registers */		aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &                    ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);		/* save stretching */		crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par);		crtc->vert_stretching = aty_ld_lcd(VERT_STRETCHING, par);		if (!M64_HAS(LT_LCD_REGS))			crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par);	}#endif	crtc->h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);	crtc->h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);	crtc->v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);	crtc->v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);	crtc->vline_crnt_vline = aty_ld_le32(CRTC_VLINE_CRNT_VLINE, par);	crtc->off_pitch = aty_ld_le32(CRTC_OFF_PITCH, par);	crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par);#ifdef CONFIG_FB_ATY_GENERIC_LCD	if (par->lcd_table != 0) {		/* switch to shadow registers */		aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |			SHADOW_EN | SHADOW_RW_EN, par);		crtc->shadow_h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par);		crtc->shadow_h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par);		crtc->shadow_v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, par);		crtc->shadow_v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, par);		aty_st_le32(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);	}#endif /* CONFIG_FB_ATY_GENERIC_LCD */}static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc){#ifdef CONFIG_FB_ATY_GENERIC_LCD	if (par->lcd_table != 0) {		/* stop CRTC */		aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par);		/* update non-shadow registers first */		aty_st_lcd(CNFG_PANEL, crtc->lcd_config_panel, par);		aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl &			~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par);		/* temporarily disable stretching */		aty_st_lcd(HORZ_STRETCHING,			crtc->horz_stretching &			~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN), par);		aty_st_lcd(VERT_STRETCHING,			crtc->vert_stretching &			~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 |			VERT_STRETCH_USE0 | VERT_STRETCH_EN), par);	}#endif	/* turn off CRT */	aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~CRTC_EN, par);	DPRINTK("setting up CRTC\n");	DPRINTK("set primary CRT to %ix%i %c%c composite %c\n",	    ((((crtc->h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->v_tot_disp>>16) & 0x7ff) + 1),	    (crtc->h_sync_strt_wid & 0x200000)?'N':'P', (crtc->v_sync_strt_wid & 0x200000)?'N':'P',	    (crtc->gen_cntl & CRTC_CSYNC_EN)?'P':'N');	DPRINTK("CRTC_H_TOTAL_DISP: %x\n",crtc->h_tot_disp);	DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n",crtc->h_sync_strt_wid);	DPRINTK("CRTC_V_TOTAL_DISP: %x\n",crtc->v_tot_disp);	DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n",crtc->v_sync_strt_wid);	DPRINTK("CRTC_OFF_PITCH: %x\n", crtc->off_pitch);	DPRINTK("CRTC_VLINE_CRNT_VLINE: %x\n", crtc->vline_crnt_vline);	DPRINTK("CRTC_GEN_CNTL: %x\n",crtc->gen_cntl);	aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, par);	aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, par);	aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, par);	aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, par);	aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, par);	aty_st_le32(CRTC_VLINE_CRNT_VLINE, crtc->vline_crnt_vline, par);	aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, par);#if 0	FIXME	if (par->accel_flags & FB_ACCELF_TEXT)		aty_init_engine(par, info);#endif#ifdef CONFIG_FB_ATY_GENERIC_LCD	/* after setting the CRTC registers we should set the LCD registers. */	if (par->lcd_table != 0) {		/* switch to shadow registers */		aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) |			(SHADOW_EN | SHADOW_RW_EN), par);		DPRINTK("set shadow CRT to %ix%i %c%c\n",		    ((((crtc->shadow_h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->shadow_v_tot_disp>>16) & 0x7ff) + 1),		    (crtc->shadow_h_sync_strt_wid & 0x200000)?'N':'P', (crtc->shadow_v_sync_strt_wid & 0x200000)?'N':'P');		DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n", crtc->shadow_h_tot_disp);		DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n", crtc->shadow_h_sync_strt_wid);		DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n", crtc->shadow_v_tot_disp);		DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n", crtc->shadow_v_sync_strt_wid);		aty_st_le32(CRTC_H_TOTAL_DISP, crtc->shadow_h_tot_disp, par);		aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->shadow_h_sync_strt_wid, par);		aty_st_le32(CRTC_V_TOTAL_DISP, crtc->shadow_v_tot_disp, par);		aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->shadow_v_sync_strt_wid, par);		/* restore CRTC selection & shadow state and enable stretching */		DPRINTK("LCD_GEN_CNTL: %x\n", crtc->lcd_gen_cntl);		DPRINTK("HORZ_STRETCHING: %x\n", crtc->horz_stretching);		DPRINTK("VERT_STRETCHING: %x\n", crtc->vert_stretching);		if(!M64_HAS(LT_LCD_REGS))		    DPRINTK("EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch);		aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);		aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching, par);		aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching, par);		if(!M64_HAS(LT_LCD_REGS)) {		    aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par);		    aty_ld_le32(LCD_INDEX, par);		    aty_st_le32(LCD_INDEX, crtc->lcd_index, par);		}	}#endif /* CONFIG_FB_ATY_GENERIC_LCD */}static int aty_var_to_crtc(const struct fb_info *info,	const struct fb_var_screeninfo *var, struct crtc *crtc){	struct atyfb_par *par = (struct atyfb_par *) info->par;	u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;	u32 sync, vmode, vdisplay;	u32 h_total, h_disp, h_sync_strt, h_sync_end, h_sync_dly, h_sync_wid, h_sync_pol;	u32 v_total, v_disp, v_sync_strt, v_sync_end, v_sync_wid, v_sync_pol, c_sync;	u32 pix_width, dp_pix_width, dp_chain_mask;	/* input */	xres = var->xres;	yres = var->yres;	vxres = var->xres_virtual;	vyres = var->yres_virtual;	xoffset = var->xoffset;	yoffset = var->yoffset;	bpp = var->bits_per_pixel;	if (bpp == 16)		bpp = (var->green.length == 5) ? 15 : 16;	sync = var->sync;	vmode = var->vmode;	/* convert (and round up) and validate */	if (vxres < xres + xoffset)		vxres = xres + xoffset;	h_disp = xres;	if (vyres < yres + yoffset)		vyres = yres + yoffset;	v_disp = yres;	if (bpp <= 8) {		bpp = 8;		pix_width = CRTC_PIX_WIDTH_8BPP;		dp_pix_width =		    HOST_8BPP | SRC_8BPP | DST_8BPP |		    BYTE_ORDER_LSB_TO_MSB;		dp_chain_mask = DP_CHAIN_8BPP;	} else if (bpp <= 15) {		bpp = 16;		pix_width = CRTC_PIX_WIDTH_15BPP;		dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |		    BYTE_ORDER_LSB_TO_MSB;		dp_chain_mask = DP_CHAIN_15BPP;	} else if (bpp <= 16) {		bpp = 16;		pix_width = CRTC_PIX_WIDTH_16BPP;		dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP |		    BYTE_ORDER_LSB_TO_MSB;		dp_chain_mask = DP_CHAIN_16BPP;	} else if (bpp <= 24 && M64_HAS(INTEGRATED)) {		bpp = 24;		pix_width = CRTC_PIX_WIDTH_24BPP;		dp_pix_width =		    HOST_8BPP | SRC_8BPP | DST_8BPP |		    BYTE_ORDER_LSB_TO_MSB;		dp_chain_mask = DP_CHAIN_24BPP;	} else if (bpp <= 32) {		bpp = 32;		pix_width = CRTC_PIX_WIDTH_32BPP;		dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |		    BYTE_ORDER_LSB_TO_MSB;		dp_chain_mask = DP_CHAIN_32BPP;	} else		FAIL("invalid bpp");	if (vxres * vyres * bpp / 8 > info->fix.smem_len)		FAIL("not enough video RAM");	h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;	v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;	if((xres > 1600) || (yres > 1200)) {		FAIL("MACH64 chips are designed for max 1600x1200\n"		"select anoter resolution.");	}	h_sync_strt = h_disp + var->right_margin;	h_sync_end = h_sync_strt + var->hsync_len;	h_sync_dly  = var->right_margin & 7;	h_total = h_sync_end + h_sync_dly + var->left_margin;	v_sync_strt = v_disp + var->lower_margin;	v_sync_end = v_sync_strt + var->vsync_len;	v_total = v_sync_end + var->upper_margin;#ifdef CONFIG_FB_ATY_GENERIC_LCD	if (par->lcd_table != 0) {		if(!M64_HAS(LT_LCD_REGS)) {		    u32 lcd_index = aty_ld_le32(LCD_INDEX, par);		    crtc->lcd_index = lcd_index &			~(LCD_INDEX_MASK | LCD_DISPLAY_DIS | LCD_SRC_SEL | CRTC2_DISPLAY_DIS);		    aty_st_le32(LCD_INDEX, lcd_index, par);		}		if (!M64_HAS(MOBIL_BUS))			crtc->lcd_index |= CRTC2_DISPLAY_DIS;		crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par) | 0x4000;		crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT;		crtc->lcd_gen_cntl &=			~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | TVCLK_PM_EN |			/*VCLK_DAC_PM_EN | USE_SHADOWED_VEND |*/			USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN);		crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR | LOCK_8DOT;		if((crtc->lcd_gen_cntl & LCD_ON) &&			((xres > par->lcd_width) || (yres > par->lcd_height))) {			/* We cannot display the mode on the LCD. If the CRT is enabled			   we can turn off the LCD.			   If the CRT is off, it isn't a good idea to switch it on; we don't			   know if one is connected. So it's better to fail then.			 */			if (crtc->lcd_gen_cntl & CRT_ON) {				if (!(var->activate & FB_ACTIVATE_TEST))					PRINTKI("Disable LCD panel, because video mode does not fit.\n");				crtc->lcd_gen_cntl &= ~LCD_ON;				/*aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par);*/			} else {				if (!(var->activate & FB_ACTIVATE_TEST))					PRINTKE("Video mode exceeds size of LCD panel.\nConnect this computer to a conventional monitor if you really need this mode.\n");				return -EINVAL;			}		}	}	if ((par->lcd_table != 0) && (crtc->lcd_gen_cntl & LCD_ON)) {		int VScan = 1;		/* bpp -> bytespp, 1,4 -> 0; 8 -> 2; 15,16 -> 1; 24 -> 6; 32 -> 5		const u8 DFP_h_sync_dly_LT[] = { 0, 2, 1, 6, 5 };		const u8 ADD_to_strt_wid_and_dly_LT_DAC[] = { 0, 5, 6, 9, 9, 12, 12 };  */		vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED);

⌨️ 快捷键说明

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