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

📄 creatorfb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		}	}	spin_unlock_irqrestore(&fb->lock, flags);}static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,		      int count, int yy, int xx){	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;	register struct ffb_fbc *fbc = fb->s.ffb.fbc;	unsigned long flags;	int i, xy;	u8 *fd1, *fd2, *fd3, *fd4;	u16 c;	u64 fgbg;	spin_lock_irqsave(&fb->lock, flags);	c = scr_readw(s);	fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p, c)])) << 32) |	       ((u32 *)p->dispsw_data)[attr_bgcol(p, c)];	if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {		FFBFifo(fb, 2);		upa_writeq(fgbg, &fbc->fg);		*(u64 *)&fb->s.ffb.fg_cache = fgbg;	}	xy = fb->s.ffb.xy_margin;	if (fontwidthlog(p))		xy += (xx << fontwidthlog(p));	else		xy += xx * fontwidth(p);	if (fontheightlog(p))		xy += (yy << (16 + fontheightlog(p)));	else		xy += ((yy * fontheight(p)) << 16);	if (fontwidth(p) <= 8) {		while (count >= 4) {			count -= 4;			FFBFifo(fb, 2 + fontheight(p));			upa_writel(4 * fontwidth(p), &fbc->fontw);			upa_writel(xy, &fbc->fontxy);			if (fontheightlog(p)) {				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));			} else {				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));			}			if (fontwidth(p) == 8) {				for (i = 0; i < fontheight(p); i++) {					u32 val;					val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 						<< 8)) << 8)) << 8);					upa_writel(val, &fbc->font);				}				xy += 32;			} else {				for (i = 0; i < fontheight(p); i++) {					u32 val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 						<< fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));					upa_writel(val, &fbc->font);				}				xy += 4 * fontwidth(p);			}		}	} else {		while (count >= 2) {			count -= 2;			FFBFifo(fb, 2 + fontheight(p));			upa_writel(2 * fontwidth(p), &fbc->fontw);			upa_writel(xy, &fbc->fontxy);			if (fontheightlog(p)) {				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));			} else {				fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);				fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);			}			for (i = 0; i < fontheight(p); i++) {				u32 val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));				upa_writel(val, &fbc->font);				fd1 += 2; fd2 += 2;			}			xy += 2 * fontwidth(p);		}	}	while (count) {		count--;		FFBFifo(fb, 2 + fontheight(p));		upa_writel(fontwidth(p), &fbc->fontw);		upa_writel(xy, &fbc->fontxy);		if (fontheightlog(p))			i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));		else			i = ((scr_readw(s++) & p->charmask) * fontheight(p));		if (fontwidth(p) <= 8) {			fd1 = p->fontdata + i;			for (i = 0; i < fontheight(p); i++) {				u32 val = *fd1++ << 24;				upa_writel(val, &fbc->font);			}		} else {			fd1 = p->fontdata + (i << 1);			for (i = 0; i < fontheight(p); i++) {				u32 val = *(u16 *)fd1 << 16;				upa_writel(val, &fbc->font);				fd1 += 2;			}		}		xy += fontwidth(p);	}	spin_unlock_irqrestore(&fb->lock, flags);}static void ffb_revc(struct display *p, int xx, int yy){	/* Not used if hw cursor */}#if 0static void ffb_blank(struct fb_info_sbusfb *fb){	struct ffb_dac *dac = fb->s.ffb.dac;	unsigned long flags;	u32 tmp;	spin_lock_irqsave(&fb->lock, flags);	upa_writel(0x6000, &dac->type);	tmp = (upa_readl(&dac->value) & ~0x1);	upa_writel(0x6000, &dac->type);	upa_writel(tmp, &dac->value);	spin_unlock_irqrestore(&fb->lock, flags);}#endifstatic void ffb_unblank(struct fb_info_sbusfb *fb){	struct ffb_dac *dac = fb->s.ffb.dac;	unsigned long flags;	u32 tmp;	spin_lock_irqsave(&fb->lock, flags);	upa_writel(0x6000, &dac->type);	tmp = (upa_readl(&dac->value) | 0x1);	upa_writel(0x6000, &dac->type);	upa_writel(tmp, &dac->value);	spin_unlock_irqrestore(&fb->lock, flags);}static void ffb_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count){	struct ffb_dac *dac = fb->s.ffb.dac;	unsigned long flags;	int i, j = count;		spin_lock_irqsave(&fb->lock, flags);	upa_writel(0x2000 | index, &dac->type);	for (i = index; j--; i++) {		u32 val;		/* Feed the colors in :)) */		val = ((fb->color_map CM(i,0))) |			((fb->color_map CM(i,1)) << 8) |			((fb->color_map CM(i,2)) << 16);		upa_writel(val, &dac->value);	}	if (!p)		goto out;	for (i = index, j = count; i < 16 && j--; i++)		((u32 *)p->dispsw_data)[i] = ((fb->color_map CM(i,0))) |			      		     ((fb->color_map CM(i,1)) << 8) |					     ((fb->color_map CM(i,2)) << 16);out:	spin_unlock_irqrestore(&fb->lock, flags);}static struct display_switch ffb_dispsw __initdata = {	setup:		ffb_setup,	bmove:		fbcon_redraw_bmove,	clear:		ffb_clear,	putc:		ffb_putc,	putcs:		ffb_putcs,	revc:		ffb_revc, 	fontwidthmask:	FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */};static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin){	register struct ffb_fbc *fbc = fb->s.ffb.fbc;	unsigned long flags;	spin_lock_irqsave(&fb->lock, flags);	fb->s.ffb.xy_margin = (y_margin << 16) + x_margin;	fb->s.ffb.yx_margin = (((u64)y_margin) << 32) + x_margin;	p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);	FFBWait(fbc);	spin_unlock_irqrestore(&fb->lock, flags);}static __inline__ void __ffb_curs_enable (struct fb_info_sbusfb *fb, int enable){	struct ffb_dac *dac = fb->s.ffb.dac;	u32 val;	upa_writel(0x100, &dac->type2);	if (fb->s.ffb.dac_rev <= 2) {		val = enable ? 3 : 0;	} else {		val = enable ? 0 : 3;	}	upa_writel(val, &dac->value2);}static void ffb_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue){	struct ffb_dac *dac = fb->s.ffb.dac;	unsigned long flags;		spin_lock_irqsave(&fb->lock, flags);	__ffb_curs_enable (fb, 0);	upa_writel(0x102, &dac->type2);	upa_writel((red[0] | (green[0]<<8) | (blue[0]<<16)), &dac->value2);	upa_writel((red[1] | (green[1]<<8) | (blue[1]<<16)), &dac->value2);	spin_unlock_irqrestore(&fb->lock, flags);}/* Set cursor shape */static void ffb_setcurshape (struct fb_info_sbusfb *fb){	struct ffb_dac *dac = fb->s.ffb.dac;	unsigned long flags;	int i, j;	spin_lock_irqsave(&fb->lock, flags);	__ffb_curs_enable (fb, 0);	for (j = 0; j < 2; j++) {		u32 val = j ? 0 : 0x80;		upa_writel(val, &dac->type2);		for (i = 0; i < 0x40; i++) {			if (fb->cursor.size.fbx <= 32) {				upa_writel(fb->cursor.bits [j][i], &dac->value2);				upa_writel(0, &dac->value2);			} else {				upa_writel(fb->cursor.bits [j][2*i], &dac->value2);				upa_writel(fb->cursor.bits [j][2*i+1], &dac->value2);			}		}	}		spin_unlock_irqrestore(&fb->lock, flags);}/* Load cursor information */static void ffb_setcursor (struct fb_info_sbusfb *fb){	struct ffb_dac *dac = fb->s.ffb.dac;	struct cg_cursor *c = &fb->cursor;	unsigned long flags;	u32 val;	spin_lock_irqsave(&fb->lock, flags);	upa_writel(0x104, &dac->type2);	/* Should this be just 0x7ff?? 	   Should I do some margin handling and setcurshape in that case? */	val = (((c->cpos.fby - c->chot.fby) & 0xffff) << 16)		|((c->cpos.fbx - c->chot.fbx) & 0xffff);	upa_writel(val, &dac->value2);	__ffb_curs_enable (fb, fb->cursor.enable);	spin_unlock_irqrestore(&fb->lock, flags);}static void ffb_switch_from_graph (struct fb_info_sbusfb *fb){	register struct ffb_fbc *fbc = fb->s.ffb.fbc;	unsigned long flags;	spin_lock_irqsave(&fb->lock, flags);	FFBWait(fbc);	fb->s.ffb.fifo_cache = 0;	FFBFifo(fb, 8);	upa_writel(FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|		   FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST,		   &fbc->ppc);	upa_writel(0x2000707f, &fbc->fbc);	upa_writel(FFB_ROP_NEW, &fbc->rop);	upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop);	upa_writel(0xffffffff, &fbc->pmask);	upa_writel(0x10000, &fbc->fontinc);	upa_writel(fb->s.ffb.fg_cache, &fbc->fg);	upa_writel(fb->s.ffb.bg_cache, &fbc->bg);	FFBWait(fbc);	spin_unlock_irqrestore(&fb->lock, flags);}static int __init ffb_rasterimg (struct fb_info *info, int start){	ffb_switch_from_graph (sbusfbinfo(info));	return 0;}static char idstring[60] __initdata = { 0 };static int __init creator_apply_upa_parent_ranges(int parent, struct linux_prom64_registers *regs){	struct linux_prom64_ranges ranges[PROMREG_MAX];	char name[128];	int len, i;	prom_getproperty(parent, "name", name, sizeof(name));	if (strcmp(name, "upa") != 0)		return 0;	len = prom_getproperty(parent, "ranges", (void *) ranges, sizeof(ranges));	if (len <= 0)		return 1;	len /= sizeof(struct linux_prom64_ranges);	for (i = 0; i < len; i++) {		struct linux_prom64_ranges *rng = &ranges[i];		u64 phys_addr = regs->phys_addr;		if (phys_addr >= rng->ot_child_base &&		    phys_addr < (rng->ot_child_base + rng->or_size)) {			regs->phys_addr -= rng->ot_child_base;			regs->phys_addr += rng->ot_parent_base;			return 0;		}	}	return 1;}char __init *creatorfb_init(struct fb_info_sbusfb *fb){	struct fb_fix_screeninfo *fix = &fb->fix;	struct fb_var_screeninfo *var = &fb->var;	struct display *disp = &fb->disp;	struct fbtype *type = &fb->type;	struct linux_prom64_registers regs[2*PROMREG_MAX];	int i, afb = 0;	unsigned int btype;	char name[64];	struct fb_ops *fbops;	if (prom_getproperty(fb->prom_node, "reg", (void *) regs, sizeof(regs)) <= 0)		return NULL;	if (creator_apply_upa_parent_ranges(fb->prom_parent, &regs[0]))		return NULL;			disp->dispsw_data = (void *)kmalloc(16 * sizeof(u32), GFP_KERNEL);	if (disp->dispsw_data == NULL)		return NULL;	memset(disp->dispsw_data, 0, 16 * sizeof(u32));	fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);	if (fbops == NULL) {		kfree(disp->dispsw_data);		return NULL;	}		*fbops = *fb->info.fbops;	fbops->fb_rasterimg = ffb_rasterimg;	fb->info.fbops = fbops;	prom_getstring(fb->prom_node, "name", name, sizeof(name));	if (!strcmp(name, "SUNW,afb"))		afb = 1;			btype = prom_getintdefault(fb->prom_node, "board_type", 0);			strcpy(fb->info.modename, "Creator");	if (!afb) {		if ((btype & 7) == 3)		    strcpy(fix->id, "Creator 3D");		else		    strcpy(fix->id, "Creator");	} else		strcpy(fix->id, "Elite 3D");		fix->visual = FB_VISUAL_TRUECOLOR;	fix->line_length = 8192;	fix->accel = FB_ACCEL_SUN_CREATOR;		var->bits_per_pixel = 32;	var->green.offset = 8;	var->blue.offset = 16;	var->accel_flags = FB_ACCELF_TEXT;		disp->scrollmode = SCROLL_YREDRAW;	disp->screen_base = (char *)__va(regs[0].phys_addr) + FFB_DFB24_POFF + 8192 * fb->y_margin + 4 * fb->x_margin;	fb->s.ffb.xy_margin = (fb->y_margin << 16) + fb->x_margin;	fb->s.ffb.yx_margin = (((u64)fb->y_margin) << 32) + fb->x_margin;	fb->s.ffb.fbc = (struct ffb_fbc *)(regs[0].phys_addr + FFB_FBC_REGS_POFF);	fb->s.ffb.dac = (struct ffb_dac *)(regs[0].phys_addr + FFB_DAC_POFF);	fb->dispsw = ffb_dispsw;	fb->margins = ffb_margins;	fb->loadcmap = ffb_loadcmap;	fb->setcursor = ffb_setcursor;	fb->setcursormap = ffb_setcursormap;	fb->setcurshape = ffb_setcurshape;	fb->switch_from_graph = ffb_switch_from_graph;	fb->fill = ffb_fill;#if 0	/* XXX Can't enable this for now, I've seen cases	 * XXX where the VC was blanked, and Xsun24 was started	 * XXX via a remote login, the sunfb code did not	 * XXX unblank creator when it was mmap'd for some	 * XXX reason, investigate later... -DaveM	 */	fb->blank = ffb_blank;	fb->unblank = ffb_unblank;#endif		/* If there are any read errors or fifo overflow conditions,	 * clear them now.	 */	if((upa_readl(&fb->s.ffb.fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)		upa_writel(FFB_UCSR_ALL_ERRORS, &fb->s.ffb.fbc->ucsr);	ffb_switch_from_graph(fb);		fb->physbase = regs[0].phys_addr;	fb->mmap_map = ffb_mmap_map;		fb->cursor.hwsize.fbx = 64;	fb->cursor.hwsize.fby = 64;		type->fb_depth = 24;		upa_writel(0x8000, &fb->s.ffb.dac->type);	fb->s.ffb.dac_rev = (upa_readl(&fb->s.ffb.dac->value) >> 0x1c);	                	i = prom_getintdefault (fb->prom_node, "board_type", 8);	sprintf(idstring, "%s at %016lx type %d DAC %d",		fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev);		/* Elite3D has different DAC revision numbering, and no DAC revisions	   have the reversed meaning of cursor enable */	if (afb)		fb->s.ffb.dac_rev = 10;		/* Unblank it just to be sure.  When there are multiple	 * FFB/AFB cards in the system, or it is not the OBP	 * chosen console, it will have video outputs off in	 * the DAC.	 */	ffb_unblank(fb);	return idstring;}MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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