atyfb_base.c

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

C
2,413
字号
	return aty_ld_le32(LCD_DATA, par);}#endif				/* CONFIG_PMAC_PBOOK || CONFIG_PMAC_BACKLIGHT *//* ------------------------------------------------------------------------- */    /*     *  CRTC programming     */static void aty_set_crtc(const struct atyfb_par *par,			 const struct crtc *crtc){	aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, par);	aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, par);	aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, par);	aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, par);	aty_st_le32(CRTC_VLINE_CRNT_VLINE, 0, par);	aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, par);	aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, par);}static int aty_var_to_crtc(const struct fb_info *info,			   const struct fb_var_screeninfo *var,			   struct crtc *crtc){	struct atyfb_par *par = (struct atyfb_par *) info->par;	u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;	u32 left, right, upper, lower, hslen, vslen, sync, vmode;	u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid,	    h_sync_pol;	u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;	u32 pix_width, dp_pix_width, dp_chain_mask;	/* input */	xres = var->xres;	yres = var->yres;	vxres = var->xres_virtual;	vyres = var->yres_virtual;	xoffset = var->xoffset;	yoffset = var->yoffset;	bpp = var->bits_per_pixel;	left = var->left_margin;	right = var->right_margin;	upper = var->upper_margin;	lower = var->lower_margin;	hslen = var->hsync_len;	vslen = var->vsync_len;	sync = var->sync;	vmode = var->vmode;	/* convert (and round up) and validate */	xres = (xres + 7) & ~7;	xoffset = (xoffset + 7) & ~7;	vxres = (vxres + 7) & ~7;	if (vxres < xres + xoffset)		vxres = xres + xoffset;	h_disp = xres / 8 - 1;	if (h_disp > 0xff)		FAIL("h_disp too large");	h_sync_strt = h_disp + (right / 8);	if (h_sync_strt > 0x1ff)		FAIL("h_sync_start too large");	h_sync_dly = right & 7;	h_sync_wid = (hslen + 7) / 8;	if (h_sync_wid > 0x1f)		FAIL("h_sync_wid too large");	h_total = h_sync_strt + h_sync_wid + (h_sync_dly + left + 7) / 8;	if (h_total > 0x1ff)		FAIL("h_total too large");	h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;	if (vyres < yres + yoffset)		vyres = yres + yoffset;	v_disp = yres - 1;	if (v_disp > 0x7ff)		FAIL("v_disp too large");	v_sync_strt = v_disp + lower;	if (v_sync_strt > 0x7ff)		FAIL("v_sync_strt too large");	v_sync_wid = vslen;	if (v_sync_wid > 0x1f)		FAIL("v_sync_wid too large");	v_total = v_sync_strt + v_sync_wid + upper;	if (v_total > 0x7ff)		FAIL("v_total too large");	v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;	c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;	if (bpp <= 8) {		bpp = 8;		pix_width = CRTC_PIX_WIDTH_8BPP;		dp_pix_width =		    HOST_8BPP | SRC_8BPP | DST_8BPP |		    BYTE_ORDER_LSB_TO_MSB;		dp_chain_mask = 0x8080;	} else if (bpp <= 16) {		bpp = 16;		pix_width = CRTC_PIX_WIDTH_15BPP;		dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |		    BYTE_ORDER_LSB_TO_MSB;		dp_chain_mask = 0x4210;	} else if (bpp <= 24 && M64_HAS(INTEGRATED)) {		bpp = 24;		pix_width = CRTC_PIX_WIDTH_24BPP;		dp_pix_width =		    HOST_8BPP | SRC_8BPP | DST_8BPP |		    BYTE_ORDER_LSB_TO_MSB;		dp_chain_mask = 0x8080;	} else if (bpp <= 32) {		bpp = 32;		pix_width = CRTC_PIX_WIDTH_32BPP;		dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |		    BYTE_ORDER_LSB_TO_MSB;		dp_chain_mask = 0x8080;	} else		FAIL("invalid bpp");	if (vxres * vyres * bpp / 8 > info->fix.smem_len)		FAIL("not enough video RAM");	if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)		FAIL("invalid vmode");	/* output */	crtc->vxres = vxres;	crtc->vyres = vyres;	crtc->h_tot_disp = h_total | (h_disp << 16);	crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly << 8) |	    ((h_sync_strt & 0x100) << 4) | (h_sync_wid << 16) |	    (h_sync_pol << 21);	crtc->v_tot_disp = v_total | (v_disp << 16);	crtc->v_sync_strt_wid =	    v_sync_strt | (v_sync_wid << 16) | (v_sync_pol << 21);	crtc->off_pitch =	    ((yoffset * vxres + xoffset) * bpp / 64) | (vxres << 19);	crtc->gen_cntl =	    pix_width | c_sync | CRTC_EXT_DISP_EN | CRTC_ENABLE;	if (M64_HAS(MAGIC_FIFO)) {		/* Not VTB/GTB */		/* FIXME: magic FIFO values */		crtc->gen_cntl |=		    aty_ld_le32(CRTC_GEN_CNTL, par) & 0x000e0000;	}	crtc->dp_pix_width = dp_pix_width;	crtc->dp_chain_mask = dp_chain_mask;	return 0;}static int aty_crtc_to_var(const struct crtc *crtc,			   struct fb_var_screeninfo *var){	u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;	u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid,	    h_sync_pol;	u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;	u32 pix_width;	/* input */	h_total = crtc->h_tot_disp & 0x1ff;	h_disp = (crtc->h_tot_disp >> 16) & 0xff;	h_sync_strt = (crtc->h_sync_strt_wid & 0xff) |	    ((crtc->h_sync_strt_wid >> 4) & 0x100);	h_sync_dly = (crtc->h_sync_strt_wid >> 8) & 0x7;	h_sync_wid = (crtc->h_sync_strt_wid >> 16) & 0x1f;	h_sync_pol = (crtc->h_sync_strt_wid >> 21) & 0x1;	v_total = crtc->v_tot_disp & 0x7ff;	v_disp = (crtc->v_tot_disp >> 16) & 0x7ff;	v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;	v_sync_wid = (crtc->v_sync_strt_wid >> 16) & 0x1f;	v_sync_pol = (crtc->v_sync_strt_wid >> 21) & 0x1;	c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;	pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;	/* convert */	xres = (h_disp + 1) * 8;	yres = v_disp + 1;	left = (h_total - h_sync_strt - h_sync_wid) * 8 - h_sync_dly;	right = (h_sync_strt - h_disp) * 8 + h_sync_dly;	hslen = h_sync_wid * 8;	upper = v_total - v_sync_strt - v_sync_wid;	lower = v_sync_strt - v_disp;	vslen = v_sync_wid;	sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |	    (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |	    (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);	switch (pix_width) {#if 0	case CRTC_PIX_WIDTH_4BPP:		bpp = 4;		var->red.offset = 0;		var->red.length = 8;		var->green.offset = 0;		var->green.length = 8;		var->blue.offset = 0;		var->blue.length = 8;		var->transp.offset = 0;		var->transp.length = 0;		break;#endif	case CRTC_PIX_WIDTH_8BPP:		bpp = 8;		var->red.offset = 0;		var->red.length = 8;		var->green.offset = 0;		var->green.length = 8;		var->blue.offset = 0;		var->blue.length = 8;		var->transp.offset = 0;		var->transp.length = 0;		break;	case CRTC_PIX_WIDTH_15BPP:	/* RGB 555 */		bpp = 16;		var->red.offset = 10;		var->red.length = 5;		var->green.offset = 5;		var->green.length = 5;		var->blue.offset = 0;		var->blue.length = 5;		var->transp.offset = 0;		var->transp.length = 0;		break;#if 0	case CRTC_PIX_WIDTH_16BPP:	/* RGB 565 */		bpp = 16;		var->red.offset = 11;		var->red.length = 5;		var->green.offset = 5;		var->green.length = 6;		var->blue.offset = 0;		var->blue.length = 5;		var->transp.offset = 0;		var->transp.length = 0;		break;#endif	case CRTC_PIX_WIDTH_24BPP:	/* RGB 888 */		bpp = 24;		var->red.offset = 16;		var->red.length = 8;		var->green.offset = 8;		var->green.length = 8;		var->blue.offset = 0;		var->blue.length = 8;		var->transp.offset = 0;		var->transp.length = 0;		break;	case CRTC_PIX_WIDTH_32BPP:	/* ARGB 8888 */		bpp = 32;		var->red.offset = 16;		var->red.length = 8;		var->green.offset = 8;		var->green.length = 8;		var->blue.offset = 0;		var->blue.length = 8;		var->transp.offset = 24;		var->transp.length = 8;		break;	default:		FAIL("Invalid pixel width");	}	/* output */	var->xres = xres;	var->yres = yres;	var->xres_virtual = crtc->vxres;	var->yres_virtual = crtc->vyres;	var->bits_per_pixel = bpp;	var->left_margin = left;	var->right_margin = right;	var->upper_margin = upper;	var->lower_margin = lower;	var->hsync_len = hslen;	var->vsync_len = vslen;	var->sync = sync;	var->vmode = FB_VMODE_NONINTERLACED;	return 0;}/* ------------------------------------------------------------------------- */static int atyfb_set_par(struct fb_info *info){	struct atyfb_par *par = (struct atyfb_par *) info->par;	struct fb_var_screeninfo *var = &info->var;	u8 tmp;	u32 i;	int err;	if ((err = aty_var_to_crtc(info, var, &par->crtc)) ||	    (err = par->pll_ops->var_to_pll(info, var->pixclock,					var->bits_per_pixel, &par->pll)))		return err;	par->accel_flags = var->accel_flags;	/* hack */	if (par->blitter_may_be_busy)		wait_for_idle(par);	tmp = aty_ld_8(CRTC_GEN_CNTL + 3, par);	aty_set_crtc(par, &par->crtc);	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, 0, par);	/* better call aty_StrobeClock ?? */	aty_st_8(CLOCK_CNTL + par->clk_wr_offset, CLOCK_STROBE, par);	par->dac_ops->set_dac(info, &par->pll, var->bits_per_pixel,			      par->accel_flags);	par->pll_ops->set_pll(info, &par->pll);	if (!M64_HAS(INTEGRATED)) {		/* Don't forget MEM_CNTL */		i = aty_ld_le32(MEM_CNTL, par) & 0xf0ffffff;		switch (var->bits_per_pixel) {		case 8:			i |= 0x02000000;			break;		case 16:			i |= 0x03000000;			break;		case 32:			i |= 0x06000000;			break;		}		aty_st_le32(MEM_CNTL, i, par);	} else {		i = aty_ld_le32(MEM_CNTL, par) & 0xf00fffff;		if (!M64_HAS(MAGIC_POSTDIV))			i |= par->mem_refresh_rate << 20;		switch (var->bits_per_pixel) {		case 8:		case 24:			i |= 0x00000000;			break;		case 16:			i |= 0x04000000;			break;		case 32:			i |= 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);		} else {			/* GT */			aty_st_le32(DAC_CNTL, 0x86010102, par);			aty_st_le32(BUS_CNTL, 0x7b23a040, par);			aty_st_le32(EXT_MEM_CNTL,				    aty_ld_le32(EXT_MEM_CNTL,						par) | 0x5000001, par);		}		aty_st_le32(MEM_CNTL, i, 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 */	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;	struct crtc crtc;	union aty_pll pll;	int err;	if ((err = aty_var_to_crtc(info, var, &crtc)) ||	    (err = par->pll_ops->var_to_pll(info, var->pixclock,					var->bits_per_pixel, &pll)))		return err;#if 0	/* fbmon is not done. uncomment for 2.5.x -brad */	if (!fbmon_valid_timings(var->pixclock, htotal, vtotal, info))		return -EINVAL;#endif	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);	aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, par);}    /*     *  Open/Release the frame buffer device     */static int atyfb_open(struct fb_info *info, int user){#ifdef __sparc__	struct atyfb_par *par = (struct atyfb_par *) info->par;	if (user) {		par->open++;		par->mmaped = 0;	}#endif	return (0);}struct fb_var_screeninfo default_var = {	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */	640, 480, 640, 480, 0, 0, 8, 0,	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},	0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,	0, FB_VMODE_NONINTERLACED};static int atyfb_release(struct fb_info *info, int user){#ifdef __sparc__	struct atyfb_par *par = (struct atyfb_par *) info->par;		if (user) {		par->open--;		mdelay(1);		wait_for_idle(par);		if (!par->open) {			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 vram =					    (info->fix.smem_len -					     (PAGE_SIZE << 2));					var.yres_virtual =					    ((vram * 8) /					     var.bits_per_pixel) /					    var.xres_virtual;					if (var.yres_virtual < var.yres)						var.yres_virtual =						    var.yres;				}			}

⌨️ 快捷键说明

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