radeon_base.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,181 行 · 第 1/5 页

C
2,181
字号
	    count = rinfo->mapped_vram - p;	    err = -ENOSPC;	}	radeonfb_sync(info);	if (count) {	    char *base_addr;	    base_addr = info->screen_base;	    count -= copy_from_user(base_addr+p, buf, count);	    *ppos += count;	    err = -EFAULT;	}	if (count)		return count;	return err;}static struct fb_ops radeonfb_ops = {	.owner			= THIS_MODULE,	.fb_check_var		= radeonfb_check_var,	.fb_set_par		= radeonfb_set_par,	.fb_setcolreg		= radeonfb_setcolreg,	.fb_pan_display 	= radeonfb_pan_display,	.fb_blank		= radeonfb_blank,	.fb_ioctl		= radeonfb_ioctl,	.fb_sync		= radeonfb_sync,	.fb_fillrect		= radeonfb_fillrect,	.fb_copyarea		= radeonfb_copyarea,	.fb_imageblit		= radeonfb_imageblit,	.fb_read		= radeonfb_read,	.fb_write		= radeonfb_write,	.fb_cursor		= soft_cursor,};static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo){	struct fb_info *info = rinfo->info;	info->currcon = -1;	info->par = rinfo;	info->pseudo_palette = rinfo->pseudo_palette;	info->flags = FBINFO_DEFAULT		    | FBINFO_HWACCEL_COPYAREA		    | FBINFO_HWACCEL_FILLRECT		    | FBINFO_HWACCEL_XPAN		    | FBINFO_HWACCEL_YPAN;	info->fbops = &radeonfb_ops;	info->screen_base = (char *)rinfo->fb_base;	/* Fill fix common fields */	strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id));        info->fix.smem_start = rinfo->fb_base_phys;        info->fix.smem_len = rinfo->video_ram;        info->fix.type = FB_TYPE_PACKED_PIXELS;        info->fix.visual = FB_VISUAL_PSEUDOCOLOR;        info->fix.xpanstep = 8;        info->fix.ypanstep = 1;        info->fix.ywrapstep = 0;        info->fix.type_aux = 0;        info->fix.mmio_start = rinfo->mmio_base_phys;        info->fix.mmio_len = RADEON_REGSIZE;	fb_alloc_cmap(&info->cmap, 256, 0);	if (noaccel)		info->flags |= FBINFO_HWACCEL_DISABLED;        return 0;}#ifdef CONFIG_PMAC_BACKLIGHT/* TODO: Dbl check these tables, we don't go up to full ON backlight * in these, possibly because we noticed MacOS doesn't, but I'd prefer * having some more official numbers from ATI */static int backlight_conv_m6[] = {	0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e,	0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24};static int backlight_conv_m7[] = {	0x00, 0x3f, 0x4a, 0x55, 0x60, 0x6b, 0x76, 0x81,	0x8c, 0x97, 0xa2, 0xad, 0xb8, 0xc3, 0xce, 0xd9};#define BACKLIGHT_LVDS_OFF#undef BACKLIGHT_DAC_OFF/* We turn off the LCD completely instead of just dimming the backlight. * This provides some greater power saving and the display is useless * without backlight anyway. */static int radeon_set_backlight_enable(int on, int level, void *data){	struct radeonfb_info *rinfo = (struct radeonfb_info *)data;	unsigned int lvds_gen_cntl = INREG(LVDS_GEN_CNTL);	unsigned long tmpPixclksCntl = INPLL(PIXCLKS_CNTL);	int* conv_table;	if (rinfo->mon1_type != MT_LCD)		return 0;	/* Pardon me for that hack... maybe some day we can figure	 * out in what direction backlight should work on a given	 * panel ?	 */	if ((rinfo->family == CHIP_FAMILY_RV200 ||	     rinfo->family == CHIP_FAMILY_RV250 ||	     rinfo->family == CHIP_FAMILY_RV280 ||	     rinfo->family == CHIP_FAMILY_RV350) &&	    !machine_is_compatible("PowerBook4,3") &&	    !machine_is_compatible("PowerBook6,3") &&	    !machine_is_compatible("PowerBook6,5"))		conv_table = backlight_conv_m7;	else		conv_table = backlight_conv_m6;	del_timer_sync(&rinfo->lvds_timer);	lvds_gen_cntl |= (LVDS_BL_MOD_EN | LVDS_BLON);	radeon_fifo_wait(3);	if (on && (level > BACKLIGHT_OFF)) {		lvds_gen_cntl |= LVDS_DIGON;		if (!(lvds_gen_cntl & LVDS_ON)) {			lvds_gen_cntl &= ~LVDS_BLON;			OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);			(void)INREG(LVDS_GEN_CNTL);			mdelay(rinfo->panel_info.pwr_delay);/* OUCH !!! FIXME */			lvds_gen_cntl |= LVDS_BLON;			OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);		}		lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;		lvds_gen_cntl |= (conv_table[level] <<				  LVDS_BL_MOD_LEVEL_SHIFT);		lvds_gen_cntl |= (LVDS_ON | LVDS_EN);		lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;	} else {		/* Asic bug, when turning off LVDS_ON, we have to make sure		   RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off		*/		if (rinfo->is_mobility || rinfo->is_IGP)			OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);		lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;		lvds_gen_cntl |= (conv_table[0] <<				  LVDS_BL_MOD_LEVEL_SHIFT);		lvds_gen_cntl |= LVDS_DISPLAY_DIS | LVDS_BLON;		OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);		mdelay(rinfo->panel_info.pwr_delay);/* OUCH !!! FIXME */		lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGON);	}	OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);	if (rinfo->is_mobility || rinfo->is_IGP)		OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);	rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;	rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK);	return 0;}static int radeon_set_backlight_level(int level, void *data){	return radeon_set_backlight_enable(1, level, data);}#endif /* CONFIG_PMAC_BACKLIGHT *//* * This reconfigure the card's internal memory map. In theory, we'd like * to setup the card's memory at the same address as it's PCI bus address, * and the AGP aperture right after that so that system RAM on 32 bits * machines at least, is directly accessible. However, doing so would * conflict with the current XFree drivers... * Ultimately, I hope XFree, GATOS and ATI binary drivers will all agree * on the proper way to set this up and duplicate this here. In the meantime, * I put the card's memory at 0 in card space and AGP at some random high * local (0xe0000000 for now) that will be changed by XFree/DRI anyway */#ifdef CONFIG_PPC_OF#undef SET_MC_FB_FROM_APERTUREstatic void fixup_memory_mappings(struct radeonfb_info *rinfo){	u32 save_crtc_gen_cntl, save_crtc2_gen_cntl;	u32 save_crtc_ext_cntl;	u32 aper_base, aper_size;	u32 agp_base;	/* First, we disable display to avoid interfering */	if (rinfo->has_CRTC2) {		save_crtc2_gen_cntl = INREG(CRTC2_GEN_CNTL);		OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl | CRTC2_DISP_REQ_EN_B);	}	save_crtc_gen_cntl = INREG(CRTC_GEN_CNTL);	save_crtc_ext_cntl = INREG(CRTC_EXT_CNTL);		OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl | CRTC_DISPLAY_DIS);	OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B);	mdelay(100);	aper_base = INREG(CONFIG_APER_0_BASE);	aper_size = INREG(CONFIG_APER_SIZE);#ifdef SET_MC_FB_FROM_APERTURE	/* Set framebuffer to be at the same address as set in PCI BAR */	OUTREG(MC_FB_LOCATION, 		((aper_base + aper_size - 1) & 0xffff0000) | (aper_base >> 16));	rinfo->fb_local_base = aper_base;#else	OUTREG(MC_FB_LOCATION, 0x7fff0000);	rinfo->fb_local_base = 0;#endif	agp_base = aper_base + aper_size;	if (agp_base & 0xf0000000)		agp_base = (aper_base | 0x0fffffff) + 1;	/* Set AGP to be just after the framebuffer on a 256Mb boundary. This	 * assumes the FB isn't mapped to 0xf0000000 or above, but this is	 * always the case on PPCs afaik.	 */#ifdef SET_MC_FB_FROM_APERTURE	OUTREG(MC_AGP_LOCATION, 0xffff0000 | (agp_base >> 16));#else	OUTREG(MC_AGP_LOCATION, 0xffffe000);#endif	/* Fixup the display base addresses & engine offsets while we	 * are at it as well	 */#ifdef SET_MC_FB_FROM_APERTURE	OUTREG(DISPLAY_BASE_ADDR, aper_base);	if (rinfo->has_CRTC2)		OUTREG(CRTC2_DISPLAY_BASE_ADDR, aper_base);#else	OUTREG(DISPLAY_BASE_ADDR, 0);	if (rinfo->has_CRTC2)		OUTREG(CRTC2_DISPLAY_BASE_ADDR, 0);#endif	mdelay(100);	/* Restore display settings */	OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl);	OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl);	if (rinfo->has_CRTC2)		OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl);		RTRACE("aper_base: %08x MC_FB_LOC to: %08x, MC_AGP_LOC to: %08x\n",		aper_base,		((aper_base + aper_size - 1) & 0xffff0000) | (aper_base >> 16),		0xffff0000 | (agp_base >> 16));}#endif /* CONFIG_PPC_OF *//* * Sysfs */static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u8 *edid){	if (off > EDID_LENGTH)		return 0;	if (off + count > EDID_LENGTH)		count = EDID_LENGTH - off;	memcpy(buf, edid + off, count);	return count;}static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, size_t count){	struct device *dev = container_of(kobj, struct device, kobj);	struct pci_dev *pdev = to_pci_dev(dev);        struct fb_info *info = pci_get_drvdata(pdev);        struct radeonfb_info *rinfo = info->par;	return radeon_show_one_edid(buf, off, count, rinfo->mon1_EDID);}static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, size_t count){	struct device *dev = container_of(kobj, struct device, kobj);	struct pci_dev *pdev = to_pci_dev(dev);        struct fb_info *info = pci_get_drvdata(pdev);        struct radeonfb_info *rinfo = info->par;	return radeon_show_one_edid(buf, off, count, rinfo->mon2_EDID);}static struct bin_attribute edid1_attr = {	.attr   = {		.name	= "edid1",		.owner	= THIS_MODULE,		.mode	= 0444,	},	.size	= EDID_LENGTH,	.read	= radeon_show_edid1,};static struct bin_attribute edid2_attr = {	.attr   = {		.name	= "edid2",		.owner	= THIS_MODULE,		.mode	= 0444,	},	.size	= EDID_LENGTH,	.read	= radeon_show_edid2,};static int radeonfb_pci_register (struct pci_dev *pdev,				  const struct pci_device_id *ent){	struct fb_info *info;	struct radeonfb_info *rinfo;	u32 tmp;	RTRACE("radeonfb_pci_register BEGIN\n");		/* Enable device in PCI config */	if (pci_enable_device(pdev) != 0) {		printk(KERN_ERR "radeonfb: Cannot enable PCI device\n");		return -ENODEV;	}	info = framebuffer_alloc(sizeof(struct radeonfb_info), &pdev->dev);	if (!info) {		printk (KERN_ERR "radeonfb: could not allocate memory\n");		return -ENODEV;	}	rinfo = info->par;	rinfo->info = info;		rinfo->pdev = pdev;		spin_lock_init(&rinfo->reg_lock);	init_timer(&rinfo->lvds_timer);	rinfo->lvds_timer.function = radeon_lvds_timer_func;	rinfo->lvds_timer.data = (unsigned long)rinfo;	strcpy(rinfo->name, "ATI Radeon XX ");	rinfo->name[11] = ent->device >> 8;	rinfo->name[12] = ent->device & 0xFF;	rinfo->family = ent->driver_data & CHIP_FAMILY_MASK;	rinfo->chipset = pdev->device;	rinfo->has_CRTC2 = (ent->driver_data & CHIP_HAS_CRTC2) != 0;	rinfo->is_mobility = (ent->driver_data & CHIP_IS_MOBILITY) != 0;	rinfo->is_IGP = (ent->driver_data & CHIP_IS_IGP) != 0;			/* Set base addrs */	rinfo->fb_base_phys = pci_resource_start (pdev, 0);	rinfo->mmio_base_phys = pci_resource_start (pdev, 2);	/* request the mem regions */	if (!request_mem_region (rinfo->fb_base_phys,				 pci_resource_len(pdev, 0), "radeonfb")) {		printk (KERN_ERR "radeonfb: cannot reserve FB region\n");		goto free_rinfo;	}	if (!request_mem_region (rinfo->mmio_base_phys,				 pci_resource_len(pdev, 2), "radeonfb")) {		printk (KERN_ERR "radeonfb: cannot reserve MMIO region\n");		goto release_fb;	}	/* map the regions */	rinfo->mmio_base = (unsigned long) ioremap (rinfo->mmio_base_phys, RADEON_REGSIZE);	if (!rinfo->mmio_base) {		printk (KERN_ERR "radeonfb: cannot map MMIO\n");		goto release_mmio;	}	/* On PPC, the firmware sets up a memory mapping that tends	 * to cause lockups when enabling the engine. We reconfigure	 * the card internal memory mappings properly	 */#ifdef CONFIG_PPC_OF	fixup_memory_mappings(rinfo);#else		rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;#endif /* CONFIG_PPC_OF */	/* framebuffer size */        if ((rinfo->family == CHIP_FAMILY_RS100) ||            (rinfo->family == CHIP_FAMILY_RS200) ||            (rinfo->family == CHIP_FAMILY_RS300)) {          u32 tom = INREG(NB_TOM);          tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);  		radeon_fifo_wait(6);          OUTREG(MC_FB_LOCATION, tom);          OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);          OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);          OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16);           /* This is supposed to fix the crtc2 noise problem. */          OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);           if ((rinfo->family == CHIP_FAMILY_RS100) ||              (rinfo->family == CHIP_FAMILY_RS200)) {             /* This is to workaround the asic bug for RMX, some versions                of BIOS dosen't have this register initialized correctly.             */             OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,                     ~CRTC_H_CUTOFF_ACTIVE_EN);          }        } else {          tmp = INREG(CONFIG_MEMSIZE);        }	/* mem size is bits [28:0], mask off the rest */	rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK;	/* ram type */	tmp = INREG(MEM_SDRAM_MODE_REG);	switch ((MEM_CFG_TYPE & tmp) >> 30) {       	case 0:       		/* SDR SGRAM (2:1) */       		strcpy(rinfo->ram_type, "SDR SGRAM");       		rinfo->ram.ml = 4;       		rinfo->ram.mb = 4;       		rinfo->ram.trcd = 1;       		rinfo->ram.trp = 2;       		rinfo->ram.twr = 1;       		rinfo->ram.cl = 2;       		rinfo->ram.loop_laten

⌨️ 快捷键说明

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