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

📄 atyfb_base.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif /* DEBUG */	if (!M64_HAS(INTEGRATED)) {		/* Don't forget MEM_CNTL */		tmp = aty_ld_le32(MEM_CNTL, par) & 0xf0ffffff;		switch (var->bits_per_pixel) {		case 8:			tmp |= 0x02000000;			break;		case 16:			tmp |= 0x03000000;			break;		case 32:			tmp |= 0x06000000;			break;		}		aty_st_le32(MEM_CNTL, tmp, par);	} else {		tmp = aty_ld_le32(MEM_CNTL, par) & 0xf00fffff;		if (!M64_HAS(MAGIC_POSTDIV))			tmp |= par->mem_refresh_rate << 20;		switch (var->bits_per_pixel) {		case 8:		case 24:			tmp |= 0x00000000;			break;		case 16:			tmp |= 0x04000000;			break;		case 32:			tmp |= 0x08000000;			break;		}		if (M64_HAS(CT_BUS)) {			aty_st_le32(DAC_CNTL, 0x87010184, par);			aty_st_le32(BUS_CNTL, 0x680000f9, par);		} else if (M64_HAS(VT_BUS)) {			aty_st_le32(DAC_CNTL, 0x87010184, par);			aty_st_le32(BUS_CNTL, 0x680000f9, par);		} else if (M64_HAS(MOBIL_BUS)) {			aty_st_le32(DAC_CNTL, 0x80010102, par);			aty_st_le32(BUS_CNTL, 0x7b33a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);		} else {			/* GT */			aty_st_le32(DAC_CNTL, 0x86010102, par);			aty_st_le32(BUS_CNTL, 0x7b23a040 | (par->aux_start ? BUS_APER_REG_DIS : 0), par);			aty_st_le32(EXT_MEM_CNTL, aty_ld_le32(EXT_MEM_CNTL, par) | 0x5000001, par);		}		aty_st_le32(MEM_CNTL, tmp, par);	}	aty_st_8(DAC_MASK, 0xff, par);	info->fix.line_length = var->xres_virtual * var->bits_per_pixel/8;	info->fix.visual = var->bits_per_pixel <= 8 ?		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;	/* Initialize the graphics engine */	if (par->accel_flags & FB_ACCELF_TEXT)		aty_init_engine(par, info);#ifdef CONFIG_BOOTX_TEXT	btext_update_display(info->fix.smem_start,		(((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8,		((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1,		var->bits_per_pixel,		par->crtc.vxres * var->bits_per_pixel / 8);#endif /* CONFIG_BOOTX_TEXT */#if 0	/* switch to accelerator mode */	if (!(par->crtc.gen_cntl & CRTC_EXT_DISP_EN))		aty_st_le32(CRTC_GEN_CNTL, par->crtc.gen_cntl | CRTC_EXT_DISP_EN, par);#endif#ifdef DEBUG{	/* dump non shadow CRTC, pll, LCD registers */	int i; u32 base;	/* CRTC registers */	base = 0x2000;	printk("debug atyfb: Mach64 non-shadow register values:");	for (i = 0; i < 256; i = i+4) {		if(i%16 == 0) printk("\ndebug atyfb: 0x%04X: ", base + i);		printk(" %08X", aty_ld_le32(i, par));	}	printk("\n\n");#ifdef CONFIG_FB_ATY_CT	/* PLL registers */	base = 0x00;	printk("debug atyfb: Mach64 PLL register values:");	for (i = 0; i < 64; i++) {		if(i%16 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i);		if(i%4 == 0)  printk(" ");		printk("%02X", aty_ld_pll_ct(i, par));	}	printk("\n\n");#endif	/* CONFIG_FB_ATY_CT */#ifdef CONFIG_FB_ATY_GENERIC_LCD	if (par->lcd_table != 0) {		/* LCD registers */		base = 0x00;		printk("debug atyfb: LCD register values:");		if(M64_HAS(LT_LCD_REGS)) {		    for(i = 0; i <= POWER_MANAGEMENT; i++) {			if(i == EXT_VERT_STRETCH)			    continue;			printk("\ndebug atyfb: 0x%04X: ", lt_lcd_regs[i]);			printk(" %08X", aty_ld_lcd(i, par));		    }		} else {		    for (i = 0; i < 64; i++) {			if(i%4 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i);			printk(" %08X", aty_ld_lcd(i, par));		    }		}		printk("\n\n");	}#endif /* CONFIG_FB_ATY_GENERIC_LCD */}#endif /* DEBUG */	return 0;}static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){	struct atyfb_par *par = (struct atyfb_par *) info->par;	int err;	struct crtc crtc;	union aty_pll pll;	u32 pixclock;	memcpy(&pll, &(par->pll), sizeof(pll));	if((err = aty_var_to_crtc(info, var, &crtc)))		return err;	pixclock = atyfb_get_pixclock(var, par);	if (pixclock == 0) {		if (!(var->activate & FB_ACTIVATE_TEST))			PRINTKE("Invalid pixclock\n");		return -EINVAL;	} else {		if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &pll)))			return err;	}	if (var->accel_flags & FB_ACCELF_TEXT)		info->var.accel_flags = FB_ACCELF_TEXT;	else		info->var.accel_flags = 0;	aty_crtc_to_var(&crtc, var);	var->pixclock = par->pll_ops->pll_to_var(info, &pll);	return 0;}static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info){	u32 xoffset = info->var.xoffset;	u32 yoffset = info->var.yoffset;	u32 vxres = par->crtc.vxres;	u32 bpp = info->var.bits_per_pixel;	par->crtc.off_pitch = ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19);}    /*     *  Open/Release the frame buffer device     */static int atyfb_open(struct fb_info *info, int user){	struct atyfb_par *par = (struct atyfb_par *) info->par;	if (user) {		par->open++;#ifdef __sparc__		par->mmaped = 0;#endif	}	return (0);}static irqreturn_t aty_irq(int irq, void *dev_id){	struct atyfb_par *par = dev_id;	int handled = 0;	u32 int_cntl;	spin_lock(&par->int_lock);	int_cntl = aty_ld_le32(CRTC_INT_CNTL, par);	if (int_cntl & CRTC_VBLANK_INT) {		/* clear interrupt */		aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) | CRTC_VBLANK_INT_AK, par);		par->vblank.count++;		if (par->vblank.pan_display) {			par->vblank.pan_display = 0;			aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);		}		wake_up_interruptible(&par->vblank.wait);		handled = 1;	}	spin_unlock(&par->int_lock);	return IRQ_RETVAL(handled);}static int aty_enable_irq(struct atyfb_par *par, int reenable){	u32 int_cntl;	if (!test_and_set_bit(0, &par->irq_flags)) {		if (request_irq(par->irq, aty_irq, IRQF_SHARED, "atyfb", par)) {			clear_bit(0, &par->irq_flags);			return -EINVAL;		}		spin_lock_irq(&par->int_lock);		int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;		/* clear interrupt */		aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_AK, par);		/* enable interrupt */		aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par);		spin_unlock_irq(&par->int_lock);	} else if (reenable) {		spin_lock_irq(&par->int_lock);		int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;		if (!(int_cntl & CRTC_VBLANK_INT_EN)) {			printk("atyfb: someone disabled IRQ [%08x]\n", int_cntl);			/* re-enable interrupt */			aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par );		}		spin_unlock_irq(&par->int_lock);	}	return 0;}static int aty_disable_irq(struct atyfb_par *par){	u32 int_cntl;	if (test_and_clear_bit(0, &par->irq_flags)) {		if (par->vblank.pan_display) {			par->vblank.pan_display = 0;			aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);		}		spin_lock_irq(&par->int_lock);		int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK;		/* disable interrupt */		aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par );		spin_unlock_irq(&par->int_lock);		free_irq(par->irq, par);	}	return 0;}static int atyfb_release(struct fb_info *info, int user){	struct atyfb_par *par = (struct atyfb_par *) info->par;	if (user) {		par->open--;		mdelay(1);		wait_for_idle(par);		if (!par->open) {#ifdef __sparc__			int was_mmaped = par->mmaped;			par->mmaped = 0;			if (was_mmaped) {				struct fb_var_screeninfo var;				/* Now reset the default display config, we have no				 * idea what the program(s) which mmap'd the chip did				 * to the configuration, nor whether it restored it				 * correctly.				 */				var = default_var;				if (noaccel)					var.accel_flags &= ~FB_ACCELF_TEXT;				else					var.accel_flags |= FB_ACCELF_TEXT;				if (var.yres == var.yres_virtual) {					u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2));					var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual;					if (var.yres_virtual < var.yres)						var.yres_virtual = var.yres;				}			}#endif			aty_disable_irq(par);		}	}	return (0);}    /*     *  Pan or Wrap the Display     *     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag     */static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){	struct atyfb_par *par = (struct atyfb_par *) info->par;	u32 xres, yres, xoffset, yoffset;	xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;	yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;	if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)		yres >>= 1;	xoffset = (var->xoffset + 7) & ~7;	yoffset = var->yoffset;	if (xoffset + xres > par->crtc.vxres || yoffset + yres > par->crtc.vyres)		return -EINVAL;	info->var.xoffset = xoffset;	info->var.yoffset = yoffset;	if (par->asleep)		return 0;	set_off_pitch(par, info);	if ((var->activate & FB_ACTIVATE_VBL) && !aty_enable_irq(par, 0)) {		par->vblank.pan_display = 1;	} else {		par->vblank.pan_display = 0;		aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);	}	return 0;}static int aty_waitforvblank(struct atyfb_par *par, u32 crtc){	struct aty_interrupt *vbl;	unsigned int count;	int ret;	switch (crtc) {	case 0:		vbl = &par->vblank;		break;	default:		return -ENODEV;	}	ret = aty_enable_irq(par, 0);	if (ret)		return ret;	count = vbl->count;	ret = wait_event_interruptible_timeout(vbl->wait, count != vbl->count, HZ/10);	if (ret < 0) {		return ret;	}	if (ret == 0) {		aty_enable_irq(par, 1);		return -ETIMEDOUT;	}	return 0;}#ifdef DEBUG#define ATYIO_CLKR		0x41545900	/* ATY\00 */#define ATYIO_CLKW		0x41545901	/* ATY\01 */struct atyclk {	u32 ref_clk_per;	u8 pll_ref_div;	u8 mclk_fb_div;	u8 mclk_post_div;	/* 1,2,3,4,8 */	u8 mclk_fb_mult;	/* 2 or 4 */	u8 xclk_post_div;	/* 1,2,3,4,8 */	u8 vclk_fb_div;	u8 vclk_post_div;	/* 1,2,3,4,6,8,12 */	u32 dsp_xclks_per_row;	/* 0-16383 */	u32 dsp_loop_latency;	/* 0-15 */	u32 dsp_precision;	/* 0-7 */	u32 dsp_on;		/* 0-2047 */	u32 dsp_off;		/* 0-2047 */};#define ATYIO_FEATR		0x41545902	/* ATY\02 */#define ATYIO_FEATW		0x41545903	/* ATY\03 */#endif#ifndef FBIO_WAITFORVSYNC#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)#endifstatic int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg){	struct atyfb_par *par = (struct atyfb_par *) info->par;#ifdef __sparc__	struct fbtype fbtyp;#endif	switch (cmd) {#ifdef __sparc__	case FBIOGTYPE:		fbtyp.fb_type = FBTYPE_PCI_GENERIC;		fbtyp.fb_width = par->crtc.vxres;		fbtyp.fb_height = par->crtc.vyres;		fbtyp.fb_depth = info->var.bits_per_pixel;		fbtyp.fb_cmsize = info->cmap.len;		fbtyp.fb_size = info->fix.smem_len;		if (copy_to_user((struct fbtype __user *) arg, &fbtyp, sizeof(fbtyp)))			return -EFAULT;		break;#endif /* __sparc__ */	case FBIO_WAITFORVSYNC:		{			u32 crtc;			if (get_user(crtc, (__u32 __user *) arg))				return -EFAULT;			return aty_waitforvblank(par, crtc);		}		break;#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)	case ATYIO_CLKR:		if (M64_HAS(INTEGRATED)) {			struct atyclk clk;			union aty_pll *pll = &(par->pll);			u32 dsp_config = pll->ct.dsp_config;			u32 dsp_on_off = pll->ct.dsp_on_off;			clk.ref_clk_per = par->ref_clk_per;			clk.pll_ref_div = pll->ct.pll_ref_div;			clk.mclk_fb_div = pll->ct.mclk_fb_div;			clk.mclk_post_div = pll->ct.mclk_post_div_real;			clk.mclk_fb_mult = pll->ct.mclk_fb_mult;			clk.xclk_post_div = pll->ct.xclk_post_div_real;			clk.vclk_fb_div = pll->ct.vclk_fb_div;			clk.vclk_post_div = pll->ct.vclk_post_div_real;			clk.dsp_xclks_per_row = dsp_config & 0x3fff;			clk.dsp_loop_latency = (dsp_config >> 16) & 0xf;

⌨️ 快捷键说明

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