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

📄 radeonfb.c

📁 ati driver
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifdef CONFIG_ALL_PPC	if (!radeon_get_EDID_OF(rinfo))		RTRACE("radeonfb: could not retrieve EDID from OF\n");#else	/* XXX use other methods later */#endif}#ifdef CONFIG_ALL_PPCstatic int radeon_get_EDID_OF(struct radeonfb_info *rinfo){        struct device_node *dp;        unsigned char *pedid = NULL;        static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", NULL };        int i;          dp = pci_device_to_OF_node(rinfo->pdev);        while (dp != NULL) {                for (i = 0; propnames[i] != NULL; ++i) {                        pedid = (unsigned char *)                                get_property(dp, propnames[i], NULL);                        if (pedid != NULL) {                                rinfo->EDID = pedid;                                return 1;                        }                }                dp = dp->child;        }        return 0;}#endif /* CONFIG_ALL_PPC */static int radeon_dfp_parse_EDID(struct radeonfb_info *rinfo){	unsigned char *block = rinfo->EDID;	if (!block)		return 0;	/* jump to the detailed timing block section */	block += 54;	rinfo->clock = (block[0] + (block[1] << 8));	rinfo->panel_xres = (block[2] + ((block[4] & 0xf0) << 4));	rinfo->hblank = (block[3] + ((block[4] & 0x0f) << 8));	rinfo->panel_yres = (block[5] + ((block[7] & 0xf0) << 4));	rinfo->vblank = (block[6] + ((block[7] & 0x0f) << 8));	rinfo->hOver_plus = (block[8] + ((block[11] & 0xc0) << 2));	rinfo->hSync_width = (block[9] + ((block[11] & 0x30) << 4));	rinfo->vOver_plus = ((block[10] >> 4) + ((block[11] & 0x0c) << 2));	rinfo->vSync_width = ((block[10] & 0x0f) + ((block[11] & 0x03) << 4));	rinfo->interlaced = ((block[17] & 0x80) >> 7);	rinfo->synct = ((block[17] & 0x18) >> 3);	rinfo->misc = ((block[17] & 0x06) >> 1);	rinfo->hAct_high = rinfo->vAct_high = 0;	if (rinfo->synct == 3) {		if (rinfo->misc & 2)			rinfo->hAct_high = 1;		if (rinfo->misc & 1)			rinfo->vAct_high = 1;	}	printk("radeonfb: detected DFP panel size from EDID: %dx%d\n",		rinfo->panel_xres, rinfo->panel_yres);	rinfo->got_dfpinfo = 1;	return 1;}static void radeon_update_default_var(struct radeonfb_info *rinfo){	struct fb_var_screeninfo *var = &radeonfb_default_var;	var->xres = rinfo->panel_xres;	var->yres = rinfo->panel_yres;	var->xres_virtual = rinfo->panel_xres;	var->yres_virtual = rinfo->panel_yres;	var->xoffset = var->yoffset = 0;	var->bits_per_pixel = 8;	var->pixclock = 100000000 / rinfo->clock;	var->left_margin = (rinfo->hblank - rinfo->hOver_plus - rinfo->hSync_width);	var->right_margin = rinfo->hOver_plus;	var->upper_margin = (rinfo->vblank - rinfo->vOver_plus - rinfo->vSync_width);	var->lower_margin = rinfo->vOver_plus;	var->hsync_len = rinfo->hSync_width;	var->vsync_len = rinfo->vSync_width;	var->sync = 0;	if (rinfo->synct == 3) {		if (rinfo->hAct_high)			var->sync |= FB_SYNC_HOR_HIGH_ACT;		if (rinfo->vAct_high)			var->sync |= FB_SYNC_VERT_HIGH_ACT;	}	var->vmode = 0;	if (rinfo->interlaced)		var->vmode |= FB_VMODE_INTERLACED;	rinfo->use_default_var = 1;}static int radeon_get_dfpinfo_BIOS(struct radeonfb_info *rinfo){	char *fpbiosstart, *tmp, *tmp0;	char stmp[30];	int i;	if (!rinfo->bios_seg)		return 0;	if (!(fpbiosstart = rinfo->bios_seg + readw(rinfo->bios_seg + 0x48))) {		printk("radeonfb: Failed to detect DFP panel info using BIOS\n");		return 0;	}	if (!(tmp = rinfo->bios_seg + readw(fpbiosstart + 0x40))) {		printk("radeonfb: Failed to detect DFP panel info using BIOS\n");		return 0;	}	for(i=0; i<24; i++)		stmp[i] = readb(tmp+i+1);	stmp[24] = 0;	printk("radeonfb: panel ID string: %s\n", stmp);	rinfo->panel_xres = readw(tmp + 25);	rinfo->panel_yres = readw(tmp + 27);	printk("radeonfb: detected DFP panel size from BIOS: %dx%d\n",		rinfo->panel_xres, rinfo->panel_yres);	for(i=0; i<20; i++) {		tmp0 = rinfo->bios_seg + readw(tmp+64+i*2);		if (tmp0 == 0)			break;		if ((readw(tmp0) == rinfo->panel_xres) &&		    (readw(tmp0+2) == rinfo->panel_yres)) {			rinfo->hblank = (readw(tmp0+17) - readw(tmp0+19)) * 8;			rinfo->hOver_plus = ((readw(tmp0+21) - readw(tmp0+19) -1) * 8) & 0x7fff;			rinfo->hSync_width = readb(tmp0+23) * 8;			rinfo->vblank = readw(tmp0+24) - readw(tmp0+26);			rinfo->vOver_plus = (readw(tmp0+28) & 0x7ff) - readw(tmp0+26);			rinfo->vSync_width = (readw(tmp0+28) & 0xf800) >> 11;			rinfo->clock = readw(tmp0+9);			rinfo->got_dfpinfo = 1;			return 1;		}	}	return 0;}static int radeon_get_dfpinfo (struct radeonfb_info *rinfo){	unsigned int tmp;	unsigned short a, b;	if (radeon_get_dfpinfo_BIOS(rinfo))		radeon_update_default_var(rinfo);	if (radeon_dfp_parse_EDID(rinfo))		radeon_update_default_var(rinfo);	if (!rinfo->got_dfpinfo) {		/*		 * it seems all else has failed now and we		 * resort to probing registers for our DFP info	         */		if (panel_yres) {			rinfo->panel_yres = panel_yres;		} else {			tmp = INREG(FP_VERT_STRETCH);			tmp &= 0x00fff000;			rinfo->panel_yres = (unsigned short)(tmp >> 0x0c) + 1;		}		switch (rinfo->panel_yres) {			case 480:				rinfo->panel_xres = 640;				break;			case 600:				rinfo->panel_xres = 800;				break;			case 768:#if defined(__powerpc__)				if (rinfo->dviDisp_type == MT_LCD)					rinfo->panel_xres = 1152;				else#endif				rinfo->panel_xres = 1024;				break;			case 1024:				rinfo->panel_xres = 1280;				break;			case 1050:				rinfo->panel_xres = 1400;				break;			case 1200:				rinfo->panel_xres = 1600;				break;			default:				printk("radeonfb: Failed to detect DFP panel size\n");				return 0;		}		printk("radeonfb: detected DFP panel size from registers: %dx%d\n",			rinfo->panel_xres, rinfo->panel_yres);		tmp = INREG(FP_CRTC_H_TOTAL_DISP);		a = (tmp & FP_CRTC_H_TOTAL_MASK) + 4;		b = (tmp & 0x01ff0000) >> FP_CRTC_H_DISP_SHIFT;		rinfo->hblank = (a - b + 1) * 8;		tmp = INREG(FP_H_SYNC_STRT_WID);		rinfo->hOver_plus = (unsigned short) ((tmp & FP_H_SYNC_STRT_CHAR_MASK) >>					FP_H_SYNC_STRT_CHAR_SHIFT) - b - 1;		rinfo->hOver_plus *= 8;		rinfo->hSync_width = (unsigned short) ((tmp & FP_H_SYNC_WID_MASK) >>					FP_H_SYNC_WID_SHIFT);		rinfo->hSync_width *= 8;		tmp = INREG(FP_CRTC_V_TOTAL_DISP);		a = (tmp & FP_CRTC_V_TOTAL_MASK) + 1;		b = (tmp & FP_CRTC_V_DISP_MASK) >> FP_CRTC_V_DISP_SHIFT;		rinfo->vblank = a - b /* + 24 */ ;		tmp = INREG(FP_V_SYNC_STRT_WID);		rinfo->vOver_plus = (unsigned short) (tmp & FP_V_SYNC_STRT_MASK)					- b + 1;		rinfo->vSync_width = (unsigned short) ((tmp & FP_V_SYNC_WID_MASK) >>					FP_V_SYNC_WID_SHIFT);		return 1;	}	return 1;}#ifdef CONFIG_ALL_PPCstatic int radeon_read_OF (struct radeonfb_info *rinfo){	struct device_node *dp;	unsigned int *xtal;	dp = pci_device_to_OF_node(rinfo->pdev);	xtal = (unsigned int *) get_property(dp, "ATY,RefCLK", 0);	rinfo->pll.ref_clk = *xtal / 10;	if (*xtal)		return 1;	else		return 0;}#endif	static void radeon_engine_init (struct radeonfb_info *rinfo){	u32 temp;	/* disable 3D engine */	OUTREG(RB3D_CNTL, 0);	radeon_engine_reset ();	radeon_fifo_wait (1);	OUTREG(RB2D_DSTCACHE_MODE, 0);	/* XXX */	rinfo->pitch = ((rinfo->xres_virtual * (rinfo->bpp / 8) + 0x3f)) >> 6;	radeon_fifo_wait (1);	temp = INREG(DEFAULT_PITCH_OFFSET);	OUTREG(DEFAULT_PITCH_OFFSET, ((temp & 0xc0000000) | 				      (rinfo->pitch << 0x16)));	radeon_fifo_wait (1);	OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);	radeon_fifo_wait (1);	OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX |					 DEFAULT_SC_BOTTOM_MAX));	temp = radeon_get_dstbpp(rinfo->depth);	rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS);	radeon_fifo_wait (1);	OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl |				    GMC_BRUSH_SOLID_COLOR |				    GMC_SRC_DATATYPE_COLOR));	radeon_fifo_wait (7);	/* clear line drawing regs */	OUTREG(DST_LINE_START, 0);	OUTREG(DST_LINE_END, 0);	/* set brush color regs */	OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);	OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);	/* set source color regs */	OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);	OUTREG(DP_SRC_BKGD_CLR, 0x00000000);	/* default write mask */	OUTREG(DP_WRITE_MSK, 0xffffffff);	radeon_engine_idle ();}static int __devinit radeon_init_disp (struct radeonfb_info *rinfo){        struct fb_info *info = &rinfo->info;	struct fb_var_screeninfo var;        var = radeonfb_default_var;        if ((radeon_init_disp_var(rinfo, &var)) < 0)                return -1;	rinfo->depth = var_to_depth(&var);	rinfo->bpp = var.bits_per_pixel;        	info->var = var;	fb_alloc_cmap(&info->cmap, 256, 0);	var.activate = FB_ACTIVATE_NOW;	fb_set_var(&var, info);        return 0;}static int radeon_init_disp_var (struct radeonfb_info *rinfo,				 struct fb_var_screeninfo *var){#ifndef MODULE        if (mode_option)                fb_find_mode (var, &rinfo->info, mode_option,                              NULL, 0, NULL, 8);        else#endif	if (rinfo->use_default_var)		/* We will use the modified default far */		*var = radeonfb_default_var;	else                fb_find_mode (var, &rinfo->info, "640x480-8@60",                              NULL, 0, NULL, 0);	if (noaccel)		var->accel_flags &= ~FB_ACCELF_TEXT;	else		var->accel_flags |= FB_ACCELF_TEXT;         return 0;}static int radeon_do_maximize(struct radeonfb_info *rinfo,                                struct fb_var_screeninfo *var,                                struct fb_var_screeninfo *v,                                int nom, int den){        static struct {                int xres, yres;        } modes[] = {                {1600, 1280},                {1280, 1024},                {1024, 768},                {800, 600},                {640, 480},                {-1, -1}        };        int i;          /* use highest possible virtual resolution */        if (v->xres_virtual == -1 && v->yres_virtual == -1) {                printk("radeonfb: using max available virtual resolution\n");                for (i=0; modes[i].xres != -1; i++) {                        if (modes[i].xres * nom / den * modes[i].yres <                            rinfo->video_ram / 2)                                break;                }                if (modes[i].xres == -1) {                        printk("radeonfb: could not find virtual resolution that fits into video memory!\n");                        return -EINVAL;                }                v->xres_virtual = modes[i].xres;                  v->yres_virtual = modes[i].yres;                                printk("radeonfb: virtual resolution set to max of %dx%d\n",                        v->xres_virtual, v->yres_virtual);        } else if (v->xres_virtual == -1) {                v->xres_virtual = (rinfo->video_ram * den /                                   (nom * v->yres_virtual * 2)) & ~15;        } else if (v->yres_virtual == -1) {                v->xres_virtual = (v->xres_virtual + 15) & ~15;                v->yres_virtual = rinfo->video_ram * den /                        (nom * v->xres_virtual *2);        } else {                if (v->xres_virtual * nom / den * v->yres_virtual >                        rinfo->video_ram) {                        return -EINVAL;                }        }                        if (v->xres_virtual * nom / den >= 8192) {                v->xres_virtual = 8192 * den / nom - 16;        }                       if (v->xres_virtual < v->xres)                return -EINVAL;                        if (v->yres_virtual < v->yres)                return -EINVAL;                                        return 0;}static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info){        struct radeonfb_info *rinfo = (struct radeonfb_info *) info->par;        struct fb_var_screeninfo v;        int nom, den;        memcpy (&v, var, sizeof (v));        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.red.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;

⌨️ 快捷键说明

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