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

📄 radeon_base.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct device_node *dp = rinfo->of_node;	u32 *val;	if (dp == NULL)		return -ENODEV;	val = (u32 *) get_property(dp, "ATY,RefCLK", NULL);	if (!val || !*val) {		printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n");		return -EINVAL;	}	rinfo->pll.ref_clk = (*val) / 10;	val = (u32 *) get_property(dp, "ATY,SCLK", NULL);	if (val && *val)		rinfo->pll.sclk = (*val) / 10;	val = (u32 *) get_property(dp, "ATY,MCLK", NULL);	if (val && *val)		rinfo->pll.mclk = (*val) / 10;       	return 0;}#endif /* CONFIG_PPC_OF *//* * Read PLL infos from chip registers */static int __devinit radeon_probe_pll_params(struct radeonfb_info *rinfo){	unsigned char ppll_div_sel;	unsigned Ns, Nm, M;	unsigned sclk, mclk, tmp, ref_div;	int hTotal, vTotal, num, denom, m, n;	unsigned long long hz, vclk;	long xtal;	struct timeval start_tv, stop_tv;	long total_secs, total_usecs;	int i;	/* Ugh, we cut interrupts, bad bad bad, but we want some precision	 * here, so... --BenH	 */	/* Flush PCI buffers ? */	tmp = INREG16(DEVICE_ID);	local_irq_disable();	for(i=0; i<1000000; i++)		if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0)			break;	do_gettimeofday(&start_tv);	for(i=0; i<1000000; i++)		if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) != 0)			break;	for(i=0; i<1000000; i++)		if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0)			break;		do_gettimeofday(&stop_tv);		local_irq_enable();	total_secs = stop_tv.tv_sec - start_tv.tv_sec;	if (total_secs > 10)		return -1;	total_usecs = stop_tv.tv_usec - start_tv.tv_usec;	total_usecs += total_secs * 1000000;	if (total_usecs < 0)		total_usecs = -total_usecs;	hz = 1000000/total_usecs; 	hTotal = ((INREG(CRTC_H_TOTAL_DISP) & 0x1ff) + 1) * 8;	vTotal = ((INREG(CRTC_V_TOTAL_DISP) & 0x3ff) + 1);	vclk = (long long)hTotal * (long long)vTotal * hz;	switch((INPLL(PPLL_REF_DIV) & 0x30000) >> 16) {	case 0:	default:		num = 1;		denom = 1;		break;	case 1:		n = ((INPLL(M_SPLL_REF_FB_DIV) >> 16) & 0xff);		m = (INPLL(M_SPLL_REF_FB_DIV) & 0xff);		num = 2*n;		denom = 2*m;		break;	case 2:		n = ((INPLL(M_SPLL_REF_FB_DIV) >> 8) & 0xff);		m = (INPLL(M_SPLL_REF_FB_DIV) & 0xff);		num = 2*n;		denom = 2*m;        break;	}	ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;	radeon_pll_errata_after_index(rinfo);	n = (INPLL(PPLL_DIV_0 + ppll_div_sel) & 0x7ff);	m = (INPLL(PPLL_REF_DIV) & 0x3ff);	num *= n;	denom *= m;	switch ((INPLL(PPLL_DIV_0 + ppll_div_sel) >> 16) & 0x7) {	case 1:		denom *= 2;		break;	case 2:		denom *= 4;		break;	case 3:		denom *= 8;		break;	case 4:		denom *= 3;		break;	case 6:		denom *= 6;   		break;	case 7:		denom *= 12;		break;	}	vclk *= denom;	do_div(vclk, 1000 * num);	xtal = vclk;	if ((xtal > 26900) && (xtal < 27100))		xtal = 2700;	else if ((xtal > 14200) && (xtal < 14400))		xtal = 1432;	else if ((xtal > 29400) && (xtal < 29600))		xtal = 2950;	else {		printk(KERN_WARNING "xtal calculation failed: %ld\n", xtal);		return -1;	}	tmp = INPLL(M_SPLL_REF_FB_DIV);	ref_div = INPLL(PPLL_REF_DIV) & 0x3ff;	Ns = (tmp & 0xff0000) >> 16;	Nm = (tmp & 0xff00) >> 8;	M = (tmp & 0xff);	sclk = round_div((2 * Ns * xtal), (2 * M));	mclk = round_div((2 * Nm * xtal), (2 * M));	/* we're done, hopefully these are sane values */	rinfo->pll.ref_clk = xtal;	rinfo->pll.ref_div = ref_div;	rinfo->pll.sclk = sclk;	rinfo->pll.mclk = mclk;	return 0;}/* * Retreive PLL infos by different means (BIOS, Open Firmware, register probing...) */static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo){	/*	 * In the case nothing works, these are defaults; they are mostly	 * incomplete, however.  It does provide ppll_max and _min values	 * even for most other methods, however.	 */	switch (rinfo->chipset) {	case PCI_DEVICE_ID_ATI_RADEON_QW:	case PCI_DEVICE_ID_ATI_RADEON_QX:		rinfo->pll.ppll_max = 35000;		rinfo->pll.ppll_min = 12000;		rinfo->pll.mclk = 23000;		rinfo->pll.sclk = 23000;		rinfo->pll.ref_clk = 2700;		break;	case PCI_DEVICE_ID_ATI_RADEON_QL:	case PCI_DEVICE_ID_ATI_RADEON_QN:	case PCI_DEVICE_ID_ATI_RADEON_QO:	case PCI_DEVICE_ID_ATI_RADEON_Ql:	case PCI_DEVICE_ID_ATI_RADEON_BB:		rinfo->pll.ppll_max = 35000;		rinfo->pll.ppll_min = 12000;		rinfo->pll.mclk = 27500;		rinfo->pll.sclk = 27500;		rinfo->pll.ref_clk = 2700;		break;	case PCI_DEVICE_ID_ATI_RADEON_Id:	case PCI_DEVICE_ID_ATI_RADEON_Ie:	case PCI_DEVICE_ID_ATI_RADEON_If:	case PCI_DEVICE_ID_ATI_RADEON_Ig:		rinfo->pll.ppll_max = 35000;		rinfo->pll.ppll_min = 12000;		rinfo->pll.mclk = 25000;		rinfo->pll.sclk = 25000;		rinfo->pll.ref_clk = 2700;		break;	case PCI_DEVICE_ID_ATI_RADEON_ND:	case PCI_DEVICE_ID_ATI_RADEON_NE:	case PCI_DEVICE_ID_ATI_RADEON_NF:	case PCI_DEVICE_ID_ATI_RADEON_NG:		rinfo->pll.ppll_max = 40000;		rinfo->pll.ppll_min = 20000;		rinfo->pll.mclk = 27000;		rinfo->pll.sclk = 27000;		rinfo->pll.ref_clk = 2700;		break;	case PCI_DEVICE_ID_ATI_RADEON_QD:	case PCI_DEVICE_ID_ATI_RADEON_QE:	case PCI_DEVICE_ID_ATI_RADEON_QF:	case PCI_DEVICE_ID_ATI_RADEON_QG:	default:		rinfo->pll.ppll_max = 35000;		rinfo->pll.ppll_min = 12000;		rinfo->pll.mclk = 16600;		rinfo->pll.sclk = 16600;		rinfo->pll.ref_clk = 2700;		break;	}	rinfo->pll.ref_div = INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;#ifdef CONFIG_PPC_OF	/*	 * Retreive PLL infos from Open Firmware first	 */       	if (!force_measure_pll && radeon_read_xtal_OF(rinfo) == 0) {       		printk(KERN_INFO "radeonfb: Retreived PLL infos from Open Firmware\n");		goto found;	}#endif /* CONFIG_PPC_OF */	/*	 * Check out if we have an X86 which gave us some PLL informations	 * and if yes, retreive them	 */	if (!force_measure_pll && rinfo->bios_seg) {		u16 pll_info_block = BIOS_IN16(rinfo->fp_bios_start + 0x30);		rinfo->pll.sclk		= BIOS_IN16(pll_info_block + 0x08);		rinfo->pll.mclk		= BIOS_IN16(pll_info_block + 0x0a);		rinfo->pll.ref_clk	= BIOS_IN16(pll_info_block + 0x0e);		rinfo->pll.ref_div	= BIOS_IN16(pll_info_block + 0x10);		rinfo->pll.ppll_min	= BIOS_IN32(pll_info_block + 0x12);		rinfo->pll.ppll_max	= BIOS_IN32(pll_info_block + 0x16);		printk(KERN_INFO "radeonfb: Retreived PLL infos from BIOS\n");		goto found;	}	/*	 * We didn't get PLL parameters from either OF or BIOS, we try to	 * probe them	 */	if (radeon_probe_pll_params(rinfo) == 0) {		printk(KERN_INFO "radeonfb: Retreived PLL infos from registers\n");		goto found;	}	/*	 * Fall back to already-set defaults...	 */       	printk(KERN_INFO "radeonfb: Used default PLL infos\n");found:	/*	 * Some methods fail to retreive SCLK and MCLK values, we apply default	 * settings in this case (200Mhz). If that really happne often, we could	 * fetch from registers instead...	 */	if (rinfo->pll.mclk == 0)		rinfo->pll.mclk = 20000;	if (rinfo->pll.sclk == 0)		rinfo->pll.sclk = 20000;	printk("radeonfb: Reference=%d.%02d MHz (RefDiv=%d) Memory=%d.%02d Mhz, System=%d.%02d MHz\n",	       rinfo->pll.ref_clk / 100, rinfo->pll.ref_clk % 100,	       rinfo->pll.ref_div,	       rinfo->pll.mclk / 100, rinfo->pll.mclk % 100,	       rinfo->pll.sclk / 100, rinfo->pll.sclk % 100);	printk("radeonfb: PLL min %d max %d\n", rinfo->pll.ppll_min, rinfo->pll.ppll_max);}static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info){	struct radeonfb_info *rinfo = info->par;        struct fb_var_screeninfo v;        int nom, den;	unsigned int pitch;	if (radeon_match_mode(rinfo, &v, var))		return -EINVAL;        switch (v.bits_per_pixel) {		case 0 ... 8:			v.bits_per_pixel = 8;			break;		case 9 ... 16:			v.bits_per_pixel = 16;			break;		case 17 ... 24:#if 0 /* Doesn't seem to work */			v.bits_per_pixel = 24;			break;#endif						return -EINVAL;		case 25 ... 32:			v.bits_per_pixel = 32;			break;		default:			return -EINVAL;	}	switch (var_to_depth(&v)) {                case 8:                        nom = den = 1;                        v.red.offset = v.green.offset = v.blue.offset = 0;                        v.red.length = v.green.length = v.blue.length = 8;                        v.transp.offset = v.transp.length = 0;                        break;		case 15:			nom = 2;			den = 1;			v.red.offset = 10;			v.green.offset = 5;			v.blue.offset = 0;			v.red.length = v.green.length = v.blue.length = 5;			v.transp.offset = v.transp.length = 0;			break;                case 16:                        nom = 2;                        den = 1;                        v.red.offset = 11;                        v.green.offset = 5;                        v.blue.offset = 0;                        v.red.length = 5;                        v.green.length = 6;                        v.blue.length = 5;                        v.transp.offset = v.transp.length = 0;                        break;                                          case 24:                        nom = 4;                        den = 1;                        v.red.offset = 16;                        v.green.offset = 8;                        v.blue.offset = 0;                        v.red.length = v.blue.length = v.green.length = 8;                        v.transp.offset = v.transp.length = 0;                        break;                case 32:                        nom = 4;                        den = 1;                        v.red.offset = 16;                        v.green.offset = 8;                        v.blue.offset = 0;                        v.red.length = v.blue.length = v.green.length = 8;                        v.transp.offset = 24;                        v.transp.length = 8;                        break;                default:                        printk ("radeonfb: mode %dx%dx%d rejected, color depth invalid\n",                                var->xres, var->yres, var->bits_per_pixel);                        return -EINVAL;        }	if (v.yres_virtual < v.yres)		v.yres_virtual = v.yres;	if (v.xres_virtual < v.xres)		v.xres_virtual = v.xres;                	/* XXX I'm adjusting xres_virtual to the pitch, that may help XFree	 * with some panels, though I don't quite like this solution	 */  	if (rinfo->info->flags & FBINFO_HWACCEL_DISABLED) {		v.xres_virtual = v.xres_virtual & ~7ul;	} else {		pitch = ((v.xres_virtual * ((v.bits_per_pixel + 1) / 8) + 0x3f) 				& ~(0x3f)) >> 6;		v.xres_virtual = (pitch << 6) / ((v.bits_per_pixel + 1) / 8);	}	if (((v.xres_virtual * v.yres_virtual * nom) / den) > rinfo->mapped_vram)		return -EINVAL;	if (v.xres_virtual < v.xres)		v.xres = v.xres_virtual;	if (v.xoffset < 0)                v.xoffset = 0;        if (v.yoffset < 0)                v.yoffset = 0;                 if (v.xoffset > v.xres_virtual - v.xres)                v.xoffset = v.xres_virtual - v.xres - 1;                                if (v.yoffset > v.yres_virtual - v.yres)                v.yoffset = v.yres_virtual - v.yres - 1;                 v.red.msb_right = v.green.msb_right = v.blue.msb_right =                          v.transp.offset = v.transp.length =                          v.transp.msb_right = 0;	        memcpy(var, &v, sizeof(v));        return 0;}static int radeonfb_pan_display (struct fb_var_screeninfo *var,                                 struct fb_info *info){        struct radeonfb_info *rinfo = info->par;        if ((var->xoffset + var->xres > var->xres_virtual)	    || (var->yoffset + var->yres > var->yres_virtual))               return -EINVAL;                        if (rinfo->asleep)        	return 0;	radeon_fifo_wait(2);        OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset)			     * var->bits_per_pixel / 8) & ~7);        return 0;}

⌨️ 快捷键说明

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