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

📄 atyfb_base.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			clk.dsp_precision = (dsp_config >> 20) & 7;			clk.dsp_off = dsp_on_off & 0x7ff;			clk.dsp_on = (dsp_on_off >> 16) & 0x7ff;			if (copy_to_user((struct atyclk __user *) arg, &clk,					 sizeof(clk)))				return -EFAULT;		} else			return -EINVAL;		break;	case ATYIO_CLKW:		if (M64_HAS(INTEGRATED)) {			struct atyclk clk;			union aty_pll *pll = &(par->pll);			if (copy_from_user(&clk, (struct atyclk __user *) arg, sizeof(clk)))				return -EFAULT;			par->ref_clk_per = clk.ref_clk_per;			pll->ct.pll_ref_div = clk.pll_ref_div;			pll->ct.mclk_fb_div = clk.mclk_fb_div;			pll->ct.mclk_post_div_real = clk.mclk_post_div;			pll->ct.mclk_fb_mult = clk.mclk_fb_mult;			pll->ct.xclk_post_div_real = clk.xclk_post_div;			pll->ct.vclk_fb_div = clk.vclk_fb_div;			pll->ct.vclk_post_div_real = clk.vclk_post_div;			pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |				((clk.dsp_loop_latency & 0xf)<<16)| ((clk.dsp_precision & 7)<<20);			pll->ct.dsp_on_off = (clk.dsp_off & 0x7ff) | ((clk.dsp_on & 0x7ff)<<16);			/*aty_calc_pll_ct(info, &pll->ct);*/			aty_set_pll_ct(info, pll);		} else			return -EINVAL;		break;	case ATYIO_FEATR:		if (get_user(par->features, (u32 __user *) arg))			return -EFAULT;		break;	case ATYIO_FEATW:		if (put_user(par->features, (u32 __user *) arg))			return -EFAULT;		break;#endif /* DEBUG && CONFIG_FB_ATY_CT */	default:		return -EINVAL;	}	return 0;}static int atyfb_sync(struct fb_info *info){	struct atyfb_par *par = (struct atyfb_par *) info->par;	if (par->blitter_may_be_busy)		wait_for_idle(par);	return 0;}#ifdef __sparc__static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma){	struct atyfb_par *par = (struct atyfb_par *) info->par;	unsigned int size, page, map_size = 0;	unsigned long map_offset = 0;	unsigned long off;	int i;	if (!par->mmap_map)		return -ENXIO;	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))		return -EINVAL;	off = vma->vm_pgoff << PAGE_SHIFT;	size = vma->vm_end - vma->vm_start;	/* To stop the swapper from even considering these pages. */	vma->vm_flags |= (VM_IO | VM_RESERVED);	if (((vma->vm_pgoff == 0) && (size == info->fix.smem_len)) ||	    ((off == info->fix.smem_len) && (size == PAGE_SIZE)))		off += 0x8000000000000000UL;	vma->vm_pgoff = off >> PAGE_SHIFT;	/* propagate off changes */	/* Each page, see which map applies */	for (page = 0; page < size;) {		map_size = 0;		for (i = 0; par->mmap_map[i].size; i++) {			unsigned long start = par->mmap_map[i].voff;			unsigned long end = start + par->mmap_map[i].size;			unsigned long offset = off + page;			if (start > offset)				continue;			if (offset >= end)				continue;			map_size = par->mmap_map[i].size - (offset - start);			map_offset =			    par->mmap_map[i].poff + (offset - start);			break;		}		if (!map_size) {			page += PAGE_SIZE;			continue;		}		if (page + map_size > size)			map_size = size - page;		pgprot_val(vma->vm_page_prot) &=		    ~(par->mmap_map[i].prot_mask);		pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag;		if (remap_pfn_range(vma, vma->vm_start + page,			map_offset >> PAGE_SHIFT, map_size, vma->vm_page_prot))			return -EAGAIN;		page += map_size;	}	if (!map_size)		return -EINVAL;	if (!par->mmaped)		par->mmaped = 1;	return 0;}#endif /* __sparc__ */#if defined(CONFIG_PM) && defined(CONFIG_PCI)#ifdef CONFIG_PPC_PMAC/* Power management routines. Those are used for PowerBook sleep. */static int aty_power_mgmt(int sleep, struct atyfb_par *par){	u32 pm;	int timeout;	pm = aty_ld_lcd(POWER_MANAGEMENT, par);	pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;	aty_st_lcd(POWER_MANAGEMENT, pm, par);	pm = aty_ld_lcd(POWER_MANAGEMENT, par);	timeout = 2000;	if (sleep) {		/* Sleep */		pm &= ~PWR_MGT_ON;		aty_st_lcd(POWER_MANAGEMENT, pm, par);		pm = aty_ld_lcd(POWER_MANAGEMENT, par);		udelay(10);		pm &= ~(PWR_BLON | AUTO_PWR_UP);		pm |= SUSPEND_NOW;		aty_st_lcd(POWER_MANAGEMENT, pm, par);		pm = aty_ld_lcd(POWER_MANAGEMENT, par);		udelay(10);		pm |= PWR_MGT_ON;		aty_st_lcd(POWER_MANAGEMENT, pm, par);		do {			pm = aty_ld_lcd(POWER_MANAGEMENT, par);			mdelay(1);			if ((--timeout) == 0)				break;		} while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);	} else {		/* Wakeup */		pm &= ~PWR_MGT_ON;		aty_st_lcd(POWER_MANAGEMENT, pm, par);		pm = aty_ld_lcd(POWER_MANAGEMENT, par);		udelay(10);		pm &= ~SUSPEND_NOW;		pm |= (PWR_BLON | AUTO_PWR_UP);		aty_st_lcd(POWER_MANAGEMENT, pm, par);		pm = aty_ld_lcd(POWER_MANAGEMENT, par);		udelay(10);		pm |= PWR_MGT_ON;		aty_st_lcd(POWER_MANAGEMENT, pm, par);		do {			pm = aty_ld_lcd(POWER_MANAGEMENT, par);			mdelay(1);			if ((--timeout) == 0)				break;		} while ((pm & PWR_MGT_STATUS_MASK) != 0);	}	mdelay(500);	return timeout ? 0 : -EIO;}#endif /* CONFIG_PPC_PMAC */static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state){	struct fb_info *info = pci_get_drvdata(pdev);	struct atyfb_par *par = (struct atyfb_par *) info->par;	if (state.event == pdev->dev.power.power_state.event)		return 0;	acquire_console_sem();	fb_set_suspend(info, 1);	/* Idle & reset engine */	wait_for_idle(par);	aty_reset_engine(par);	/* Blank display and LCD */	atyfb_blank(FB_BLANK_POWERDOWN, info);	par->asleep = 1;	par->lock_blank = 1;	/* Because we may change PCI D state ourselves, we need to	 * first save the config space content so the core can	 * restore it properly on resume.	 */	pci_save_state(pdev);#ifdef CONFIG_PPC_PMAC	/* Set chip to "suspend" mode */	if (machine_is(powermac) && aty_power_mgmt(1, par)) {		par->asleep = 0;		par->lock_blank = 0;		atyfb_blank(FB_BLANK_UNBLANK, info);		fb_set_suspend(info, 0);		release_console_sem();		return -EIO;	}#else	pci_set_power_state(pdev, pci_choose_state(pdev, state));#endif	release_console_sem();	pdev->dev.power.power_state = state;	return 0;}static void aty_resume_chip(struct fb_info *info){	struct atyfb_par *par = info->par;	aty_st_le32(MEM_CNTL, par->mem_cntl, par);	if (par->pll_ops->resume_pll)		par->pll_ops->resume_pll(info, &par->pll);	if (par->aux_start)		aty_st_le32(BUS_CNTL,			aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par);}static int atyfb_pci_resume(struct pci_dev *pdev){	struct fb_info *info = pci_get_drvdata(pdev);	struct atyfb_par *par = (struct atyfb_par *) info->par;	if (pdev->dev.power.power_state.event == PM_EVENT_ON)		return 0;	acquire_console_sem();	/* PCI state will have been restored by the core, so	 * we should be in D0 now with our config space fully	 * restored	 */#ifdef CONFIG_PPC_PMAC	if (machine_is(powermac) &&	    pdev->dev.power.power_state.event == PM_EVENT_SUSPEND)		aty_power_mgmt(0, par);#endif	aty_resume_chip(info);	par->asleep = 0;	/* Restore display */	atyfb_set_par(info);	/* Refresh */	fb_set_suspend(info, 0);	/* Unblank */	par->lock_blank = 0;	atyfb_blank(FB_BLANK_UNBLANK, info);	release_console_sem();	pdev->dev.power.power_state = PMSG_ON;	return 0;}#endif /*  defined(CONFIG_PM) && defined(CONFIG_PCI) *//* Backlight */#ifdef CONFIG_FB_ATY_BACKLIGHT#define MAX_LEVEL 0xFFstatic int aty_bl_get_level_brightness(struct atyfb_par *par, int level){	struct fb_info *info = pci_get_drvdata(par->pdev);	int atylevel;	/* Get and convert the value */	/* No locking of bl_curve since we read a single value */	atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;	if (atylevel < 0)		atylevel = 0;	else if (atylevel > MAX_LEVEL)		atylevel = MAX_LEVEL;	return atylevel;}static int aty_bl_update_status(struct backlight_device *bd){	struct atyfb_par *par = bl_get_data(bd);	unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);	int level;	if (bd->props.power != FB_BLANK_UNBLANK ||	    bd->props.fb_blank != FB_BLANK_UNBLANK)		level = 0;	else		level = bd->props.brightness;	reg |= (BLMOD_EN | BIASMOD_EN);	if (level > 0) {		reg &= ~BIAS_MOD_LEVEL_MASK;		reg |= (aty_bl_get_level_brightness(par, level) << BIAS_MOD_LEVEL_SHIFT);	} else {		reg &= ~BIAS_MOD_LEVEL_MASK;		reg |= (aty_bl_get_level_brightness(par, 0) << BIAS_MOD_LEVEL_SHIFT);	}	aty_st_lcd(LCD_MISC_CNTL, reg, par);	return 0;}static int aty_bl_get_brightness(struct backlight_device *bd){	return bd->props.brightness;}static struct backlight_ops aty_bl_data = {	.get_brightness = aty_bl_get_brightness,	.update_status	= aty_bl_update_status,};static void aty_bl_init(struct atyfb_par *par){	struct fb_info *info = pci_get_drvdata(par->pdev);	struct backlight_device *bd;	char name[12];#ifdef CONFIG_PMAC_BACKLIGHT	if (!pmac_has_backlight_type("ati"))		return;#endif	snprintf(name, sizeof(name), "atybl%d", info->node);	bd = backlight_device_register(name, info->dev, par, &aty_bl_data);	if (IS_ERR(bd)) {		info->bl_dev = NULL;		printk(KERN_WARNING "aty: Backlight registration failed\n");		goto error;	}	info->bl_dev = bd;	fb_bl_default_curve(info, 0,		0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,		0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);	bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;	bd->props.brightness = bd->props.max_brightness;	bd->props.power = FB_BLANK_UNBLANK;	backlight_update_status(bd);	printk("aty: Backlight initialized (%s)\n", name);	return;error:	return;}static void aty_bl_exit(struct backlight_device *bd){	backlight_device_unregister(bd);	printk("aty: Backlight unloaded\n");}#endif /* CONFIG_FB_ATY_BACKLIGHT */static void __devinit aty_calc_mem_refresh(struct atyfb_par *par, int xclk){	const int ragepro_tbl[] = {		44, 50, 55, 66, 75, 80, 100	};	const int ragexl_tbl[] = {		50, 66, 75, 83, 90, 95, 100, 105,		110, 115, 120, 125, 133, 143, 166	};	const int *refresh_tbl;	int i, size;	if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) {		refresh_tbl = ragexl_tbl;		size = ARRAY_SIZE(ragexl_tbl);	} else {		refresh_tbl = ragepro_tbl;		size = ARRAY_SIZE(ragepro_tbl);	}	for (i=0; i < size; i++) {		if (xclk < refresh_tbl[i])		break;	}	par->mem_refresh_rate = i;}    /*     *  Initialisation     */static struct fb_info *fb_list = NULL;#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)static int __devinit atyfb_get_timings_from_lcd(struct atyfb_par *par,						struct fb_var_screeninfo *var){	int ret = -EINVAL;	if (par->lcd_table != 0 && (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {		*var = default_var;		var->xres = var->xres_virtual = par->lcd_hdisp;		var->right_margin = par->lcd_right_margin;		var->left_margin = par->lcd_hblank_len -			(pa

⌨️ 快捷键说明

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