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

📄 mach64_ct.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	tmp &= 0xF0U;	tmp |= pll->ct.pll_ext_cntl;	aty_st_pll_ct(PLL_EXT_CNTL, tmp, par);	/* Set feedback divider */	tmp = VCLK0_FB_DIV + par->clk_wr_offset;	aty_st_pll_ct(tmp, (pll->ct.vclk_fb_div & 0xFFU), par);	aty_st_pll_ct(PLL_GEN_CNTL, (pll->ct.pll_gen_cntl & (~(PLL_OVERRIDE | PLL_MCLK_RST))) | OSC_EN, par);	/* End VCLK generator reset */	aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl & ~(PLL_VCLK_RST), par);	mdelay(5);	aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);	aty_st_pll_ct(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, par);	mdelay(1);	/* Restore mode register */	if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN))		aty_st_le32(CRTC_GEN_CNTL, crtc_gen_cntl, par);	if (M64_HAS(GTB_DSP)) {		u8 dll_cntl;		if (M64_HAS(XL_DLL))			dll_cntl = 0x80;		else if (par->ram_type >= SDRAM)			dll_cntl = 0xa6;		else			dll_cntl = 0xa0;		aty_st_pll_ct(DLL_CNTL, dll_cntl, par);		aty_st_pll_ct(VFC_CNTL, 0x1b, par);		aty_st_le32(DSP_CONFIG, pll->ct.dsp_config, par);		aty_st_le32(DSP_ON_OFF, pll->ct.dsp_on_off, par);		mdelay(10);		aty_st_pll_ct(DLL_CNTL, dll_cntl, par);		mdelay(10);		aty_st_pll_ct(DLL_CNTL, dll_cntl | 0x40, par);		mdelay(10);		aty_st_pll_ct(DLL_CNTL, dll_cntl & ~0x40, par);	}#ifdef CONFIG_FB_ATY_GENERIC_LCD	if (par->lcd_table != 0) {		/* restore LCD */		aty_st_lcd(LCD_GEN_CNTL, lcd_gen_cntrl, par);	}#endif}static void __init aty_get_pll_ct(const struct fb_info *info,				  union aty_pll *pll){	struct atyfb_par *par = (struct atyfb_par *) info->par;	u8 tmp, clock;	clock = aty_ld_8(CLOCK_CNTL, par) & 0x03U;	tmp = clock << 1;	pll->ct.vclk_post_div = (aty_ld_pll_ct(VCLK_POST_DIV, par) >> tmp) & 0x03U;	pll->ct.pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par) & 0x0FU;	pll->ct.vclk_fb_div = aty_ld_pll_ct(VCLK0_FB_DIV + clock, par) & 0xFFU;	pll->ct.pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);	pll->ct.mclk_fb_div = aty_ld_pll_ct(MCLK_FB_DIV, par);	pll->ct.pll_gen_cntl = aty_ld_pll_ct(PLL_GEN_CNTL, par);	pll->ct.pll_vclk_cntl = aty_ld_pll_ct(PLL_VCLK_CNTL, par);	if (M64_HAS(GTB_DSP)) {		pll->ct.dsp_config = aty_ld_le32(DSP_CONFIG, par);		pll->ct.dsp_on_off = aty_ld_le32(DSP_ON_OFF, par);	}}static int __init aty_init_pll_ct(const struct fb_info *info,				 union aty_pll *pll){	struct atyfb_par *par = (struct atyfb_par *) info->par;	u8 mpost_div, xpost_div, sclk_post_div_real, sclk_fb_div, spll_cntl2;	u32 q, i, memcntl, trp;	u32 dsp_config, dsp_on_off, vga_dsp_config, vga_dsp_on_off;#ifdef DEBUG	int pllmclk, pllsclk;#endif	pll->ct.pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par);	pll->ct.xclk_post_div = pll->ct.pll_ext_cntl & 0x07;	pll->ct.xclk_ref_div = 1;	switch (pll->ct.xclk_post_div) {	case 0:  case 1:  case 2:  case 3:		break;	case 4:		pll->ct.xclk_ref_div = 3;		pll->ct.xclk_post_div = 0;		break;	default:		printk(KERN_CRIT "atyfb: Unsupported xclk source:  %d.\n", pll->ct.xclk_post_div);		return -EINVAL;	}	pll->ct.mclk_fb_mult = 2;	if(pll->ct.pll_ext_cntl & PLL_MFB_TIMES_4_2B) {		pll->ct.mclk_fb_mult = 4;		pll->ct.xclk_post_div -= 1;	}#ifdef DEBUG	printk("atyfb(%s): mclk_fb_mult=%d, xclk_post_div=%d\n",		__FUNCTION__, pll->ct.mclk_fb_mult, pll->ct.xclk_post_div);#endif	memcntl = aty_ld_le32(MEM_CNTL, par);	trp = (memcntl & 0x300) >> 8;	pll->ct.xclkpagefaultdelay = ((memcntl & 0xc00) >> 10) + ((memcntl & 0x1000) >> 12) + trp + 2;	pll->ct.xclkmaxrasdelay = ((memcntl & 0x70000) >> 16) + trp + 2;	if (M64_HAS(FIFO_32)) {		pll->ct.fifo_size = 32;	} else {		pll->ct.fifo_size = 24;		pll->ct.xclkpagefaultdelay += 2;		pll->ct.xclkmaxrasdelay += 3;	}	switch (par->ram_type) {	case DRAM:		if (info->fix.smem_len<=ONE_MB) {			pll->ct.dsp_loop_latency = 10;		} else {			pll->ct.dsp_loop_latency = 8;			pll->ct.xclkpagefaultdelay += 2;		}		break;	case EDO:	case PSEUDO_EDO:		if (info->fix.smem_len<=ONE_MB) {			pll->ct.dsp_loop_latency = 9;		} else {			pll->ct.dsp_loop_latency = 8;			pll->ct.xclkpagefaultdelay += 1;		}		break;	case SDRAM:		if (info->fix.smem_len<=ONE_MB) {			pll->ct.dsp_loop_latency = 11;		} else {			pll->ct.dsp_loop_latency = 10;			pll->ct.xclkpagefaultdelay += 1;		}		break;	case SGRAM:		pll->ct.dsp_loop_latency = 8;		pll->ct.xclkpagefaultdelay += 3;		break;	default:		pll->ct.dsp_loop_latency = 11;		pll->ct.xclkpagefaultdelay += 3;		break;	}	if (pll->ct.xclkmaxrasdelay <= pll->ct.xclkpagefaultdelay)		pll->ct.xclkmaxrasdelay = pll->ct.xclkpagefaultdelay + 1;	/* Allow BIOS to override */	dsp_config = aty_ld_le32(DSP_CONFIG, par);	dsp_on_off = aty_ld_le32(DSP_ON_OFF, par);	vga_dsp_config = aty_ld_le32(VGA_DSP_CONFIG, par);	vga_dsp_on_off = aty_ld_le32(VGA_DSP_ON_OFF, par);	if (dsp_config)		pll->ct.dsp_loop_latency = (dsp_config & DSP_LOOP_LATENCY) >> 16;#if 0	FIXME: is it relevant for us?	if ((!dsp_on_off && !M64_HAS(RESET_3D)) ||		((dsp_on_off == vga_dsp_on_off) &&		(!dsp_config || !((dsp_config ^ vga_dsp_config) & DSP_XCLKS_PER_QW)))) {		vga_dsp_on_off &= VGA_DSP_OFF;		vga_dsp_config &= VGA_DSP_XCLKS_PER_QW;		if (ATIDivide(vga_dsp_on_off, vga_dsp_config, 5, 1) > 24)			pll->ct.fifo_size = 32;		else			pll->ct.fifo_size = 24;	}#endif	/* Exit if the user does not want us to tamper with the clock	rates of her chip. */	if (par->mclk_per == 0) {		u8 mclk_fb_div, pll_ext_cntl;		pll->ct.pll_ref_div = aty_ld_pll_ct(PLL_REF_DIV, par);		pll_ext_cntl = aty_ld_pll_ct(PLL_EXT_CNTL, par);		pll->ct.xclk_post_div_real = postdividers[pll_ext_cntl & 0x07];		mclk_fb_div = aty_ld_pll_ct(MCLK_FB_DIV, par);		if (pll_ext_cntl & PLL_MFB_TIMES_4_2B)			mclk_fb_div <<= 1;		pll->ct.mclk_fb_div = mclk_fb_div;		return 0;	}	pll->ct.pll_ref_div = par->pll_per * 2 * 255 / par->ref_clk_per;	/* FIXME: use the VTB/GTB /3 post divider if it's better suited */	q = par->ref_clk_per * pll->ct.pll_ref_div * 8 /		(pll->ct.mclk_fb_mult * par->xclk_per);	if (q < 16*8 || q > 255*8) {		printk(KERN_CRIT "atxfb: xclk out of range\n");		return -EINVAL;	} else {		xpost_div  = (q < 128*8);		xpost_div += (q <  64*8);		xpost_div += (q <  32*8);	}	pll->ct.xclk_post_div_real = postdividers[xpost_div];	pll->ct.mclk_fb_div = q * pll->ct.xclk_post_div_real / 8;#ifdef DEBUG	pllmclk = (1000000 * pll->ct.mclk_fb_mult * pll->ct.mclk_fb_div) /			(par->ref_clk_per * pll->ct.pll_ref_div);	printk("atyfb(%s): pllmclk=%d MHz, xclk=%d MHz\n",		__FUNCTION__, pllmclk, pllmclk / pll->ct.xclk_post_div_real);#endif	if (M64_HAS(SDRAM_MAGIC_PLL) && (par->ram_type >= SDRAM))		pll->ct.pll_gen_cntl = OSC_EN;	else		pll->ct.pll_gen_cntl = OSC_EN | DLL_PWDN /* | FORCE_DCLK_TRI_STATE */;	if (M64_HAS(MAGIC_POSTDIV))		pll->ct.pll_ext_cntl = 0;	else		pll->ct.pll_ext_cntl = xpost_div;	if (pll->ct.mclk_fb_mult == 4)		pll->ct.pll_ext_cntl |= PLL_MFB_TIMES_4_2B;	if (par->mclk_per == par->xclk_per) {		pll->ct.pll_gen_cntl |= (xpost_div << 4); /* mclk == xclk */	} else {		/*		* The chip clock is not equal to the memory clock.		* Therefore we will use sclk to clock the chip.		*/		pll->ct.pll_gen_cntl |= (6 << 4); /* mclk == sclk */		q = par->ref_clk_per * pll->ct.pll_ref_div * 4 / par->mclk_per;		if (q < 16*8 || q > 255*8) {			printk(KERN_CRIT "atyfb: mclk out of range\n");			return -EINVAL;		} else {			mpost_div  = (q < 128*8);			mpost_div += (q <  64*8);			mpost_div += (q <  32*8);		}		sclk_post_div_real = postdividers[mpost_div];		sclk_fb_div = q * sclk_post_div_real / 8;		spll_cntl2 = mpost_div << 4;#ifdef DEBUG		pllsclk = (1000000 * 2 * sclk_fb_div) /			(par->ref_clk_per * pll->ct.pll_ref_div);		printk("atyfb(%s): use sclk, pllsclk=%d MHz, sclk=mclk=%d MHz\n",			__FUNCTION__, pllsclk, pllsclk / sclk_post_div_real);#endif		/*		* This disables the sclk, crashes the computer as reported:		* aty_st_pll_ct(SPLL_CNTL2, 3, info);		*		* So it seems the sclk must be enabled before it is used;		* so PLL_GEN_CNTL must be programmed *after* the sclk.		*/		aty_st_pll_ct(SCLK_FB_DIV, sclk_fb_div, par);		aty_st_pll_ct(SPLL_CNTL2, spll_cntl2, par);		/*		 * The sclk has been started. However, I believe the first clock		 * ticks it generates are not very stable. Hope this primitive loop		 * helps for Rage Mobilities that sometimes crash when		 * we switch to sclk. (Daniel Mantione, 13-05-2003)		 */		for (i=0;i<=0x1ffff;i++);	}	aty_st_pll_ct(PLL_REF_DIV, pll->ct.pll_ref_div, par);	aty_st_pll_ct(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, par);	aty_st_pll_ct(MCLK_FB_DIV, pll->ct.mclk_fb_div, par);	aty_st_pll_ct(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, par);	/* Disable the extra precision pixel clock controls since we do not use them. */	aty_st_pll_ct(EXT_VPLL_CNTL, aty_ld_pll_ct(EXT_VPLL_CNTL, par) &		~(EXT_VPLL_EN | EXT_VPLL_VGA_EN | EXT_VPLL_INSYNC), par);	return 0;}static int dummy(void){	return 0;}const struct aty_dac_ops aty_dac_ct = {	.set_dac	= (void *) dummy,};const struct aty_pll_ops aty_pll_ct = {	.var_to_pll	= aty_var_to_pll_ct,	.pll_to_var	= aty_pll_to_var_ct,	.set_pll	= aty_set_pll_ct,	.get_pll	= aty_get_pll_ct,	.init_pll       = aty_init_pll_ct};

⌨️ 快捷键说明

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