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

📄 cgsixfb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 2 页
字号:
					u32 val = ((u32)*fd4++) |						((((u32)*fd3++) |						  ((((u32)*fd2++) |						    (((u32)*fd1++)						     << 8)) << 8)) << 8);					sbus_writel(val, &fbc->font);				}			} 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));					sbus_writel(val, &fbc->font);				}			}		}	} else {		while (count >= 2) {			count -= 2;			sbus_writel(0, &fbc->incx);			sbus_writel(1, &fbc->incy);			sbus_writel(x, &fbc->x0);			sbus_writel((x += 2 * fontwidth(p)) - 1, &fbc->x1);			sbus_writel(y, &fbc->y0);			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));				sbus_writel(val, &fbc->font);				fd1 += 2; fd2 += 2;			}		}	}	while (count) {		count--;		sbus_writel(0, &fbc->incx);		sbus_writel(1, &fbc->incy);		sbus_writel(x, &fbc->x0);		sbus_writel((x += fontwidth(p)) - 1, &fbc->x1);		sbus_writel(y, &fbc->y0);		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;				sbus_writel(val, &fbc->font);			}		} else {			fd1 = p->fontdata + (i << 1);			for (i = 0; i < fontheight(p); i++) {				u32 val = *(u16 *)fd1 << 16;				sbus_writel(val, &fbc->font);				fd1 += 2;			}		}	}	spin_unlock_irqrestore(&fb->lock, flags);}static void cg6_revc(struct display *p, int xx, int yy){	/* Not used if hw cursor */}static void cg6_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count){	struct bt_regs *bt = fb->s.cg6.bt;	unsigned long flags;	int i;                	spin_lock_irqsave(&fb->lock, flags);	sbus_writel(index << 24, &bt->addr);	for (i = index; count--; i++){		sbus_writel(fb->color_map CM(i,0) << 24,			    &bt->color_map);		sbus_writel(fb->color_map CM(i,1) << 24,			    &bt->color_map);		sbus_writel(fb->color_map CM(i,2) << 24,			    &bt->color_map);	}	spin_unlock_irqrestore(&fb->lock, flags);}static void cg6_restore_palette (struct fb_info_sbusfb *fb){	struct bt_regs *bt = fb->s.cg6.bt;	unsigned long flags;                	spin_lock_irqsave(&fb->lock, flags);	sbus_writel(0, &bt->addr);	sbus_writel(0xffffffff, &bt->color_map);	sbus_writel(0xffffffff, &bt->color_map);	sbus_writel(0xffffffff, &bt->color_map);	spin_unlock_irqrestore(&fb->lock, flags);}static struct display_switch cg6_dispsw __initdata = {	setup:		cg6_setup,	bmove:		fbcon_redraw_bmove,	clear:		cg6_clear,	putc:		cg6_putc,	putcs:		cg6_putcs,	revc:		cg6_revc, 	fontwidthmask:	FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */};static void cg6_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue){        struct bt_regs *bt = fb->s.cg6.bt;	unsigned long flags;        	spin_lock_irqsave(&fb->lock, flags);	sbus_writel(1 << 24, &bt->addr);	sbus_writel(red[0] << 24, &bt->cursor);	sbus_writel(green[0] << 24, &bt->cursor);	sbus_writel(blue[0] << 24, &bt->cursor);	sbus_writel(3 << 24, &bt->addr);	sbus_writel(red[1] << 24, &bt->cursor);	sbus_writel(green[1] << 24, &bt->cursor);	sbus_writel(blue[1] << 24, &bt->cursor);	spin_unlock_irqrestore(&fb->lock, flags);}/* Set cursor shape */static void cg6_setcurshape (struct fb_info_sbusfb *fb){	struct cg6_thc *thc = fb->s.cg6.thc;	unsigned long flags;	int i;	spin_lock_irqsave(&fb->lock, flags);	for (i = 0; i < 32; i++) {		sbus_writel(fb->cursor.bits[0][i],			    &thc->thc_cursmask [i]);		sbus_writel(fb->cursor.bits[1][i],			    &thc->thc_cursbits [i]);	}	spin_unlock_irqrestore(&fb->lock, flags);}/* Load cursor information */static void cg6_setcursor (struct fb_info_sbusfb *fb){	unsigned int v;	unsigned long flags;	struct cg_cursor *c = &fb->cursor;	spin_lock_irqsave(&fb->lock, flags);	if (c->enable)		v = ((c->cpos.fbx - c->chot.fbx) << 16)		    |((c->cpos.fby - c->chot.fby) & 0xffff);	else		/* Magic constant to turn off the cursor */		v = ((65536-32) << 16) | (65536-32);	sbus_writel(v, &fb->s.cg6.thc->thc_cursxy);	spin_unlock_irqrestore(&fb->lock, flags);}static void cg6_blank (struct fb_info_sbusfb *fb){	unsigned long flags;	u32 tmp;	spin_lock_irqsave(&fb->lock, flags);	tmp = sbus_readl(&fb->s.cg6.thc->thc_misc);	tmp &= ~CG6_THC_MISC_VIDEO;	sbus_writel(tmp, &fb->s.cg6.thc->thc_misc);	spin_unlock_irqrestore(&fb->lock, flags);}static void cg6_unblank (struct fb_info_sbusfb *fb){	unsigned long flags;	u32 tmp;	spin_lock_irqsave(&fb->lock, flags);	tmp = sbus_readl(&fb->s.cg6.thc->thc_misc);	tmp |= CG6_THC_MISC_VIDEO;	sbus_writel(tmp, &fb->s.cg6.thc->thc_misc);	spin_unlock_irqrestore(&fb->lock, flags);}static void cg6_reset (struct fb_info_sbusfb *fb){	unsigned int rev, conf;	struct cg6_tec *tec = fb->s.cg6.tec;	struct cg6_fbc *fbc = fb->s.cg6.fbc;	unsigned long flags;	u32 mode, tmp;	int i;		spin_lock_irqsave(&fb->lock, flags);	/* Turn off stuff in the Transform Engine. */	sbus_writel(0, &tec->tec_matrix);	sbus_writel(0, &tec->tec_clip);	sbus_writel(0, &tec->tec_vdc);	/* Take care of bugs in old revisions. */	rev = (sbus_readl(fb->s.cg6.fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK;	if (rev < 5) {		conf = (sbus_readl(fb->s.cg6.fhc) & CG6_FHC_RES_MASK) |			CG6_FHC_CPU_68020 | CG6_FHC_TEST |			(11 << CG6_FHC_TEST_X_SHIFT) |			(11 << CG6_FHC_TEST_Y_SHIFT);		if (rev < 2)			conf |= CG6_FHC_DST_DISABLE;		sbus_writel(conf, fb->s.cg6.fhc);	}	/* Set things in the FBC. Bad things appear to happen if we do	 * back to back store/loads on the mode register, so copy it	 * out instead. */	mode = sbus_readl(&fbc->mode);	do {		i = sbus_readl(&fbc->s);	} while (i & 0x10000000);	mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |		       CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK |		       CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK |		       CG6_FBC_BDISP_MASK);	mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 |		      CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE |		      CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 |		      CG6_FBC_BDISP_0);	sbus_writel(mode, &fbc->mode);	sbus_writel(0, &fbc->clip);	sbus_writel(0, &fbc->offx);	sbus_writel(0, &fbc->offy);	sbus_writel(0, &fbc->clipminx);	sbus_writel(0, &fbc->clipminy);	sbus_writel(fb->type.fb_width - 1, &fbc->clipmaxx);	sbus_writel(fb->type.fb_height - 1, &fbc->clipmaxy);	/* Enable cursor in Brooktree DAC. */	sbus_writel(0x06 << 24, &fb->s.cg6.bt->addr);	tmp = sbus_readl(&fb->s.cg6.bt->control);	tmp |= 0x03 << 24;	sbus_writel(tmp, &fb->s.cg6.bt->control);	spin_unlock_irqrestore(&fb->lock, flags);}static void cg6_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin){	p->screen_base += (y_margin - fb->y_margin) *		p->line_length + (x_margin - fb->x_margin);}static int __init cg6_rasterimg (struct fb_info *info, int start){	struct fb_info_sbusfb *fb = sbusfbinfo(info);	register struct cg6_fbc *fbc = fb->s.cg6.fbc;	int i;		do {		i = sbus_readl(&fbc->s);	} while (i & 0x10000000);	return 0;}static char idstring[70] __initdata = { 0 };char __init *cgsixfb_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 sbus_dev *sdev = fb->sbdp;	unsigned long phys = sdev->reg_addrs[0].phys_addr;	u32 conf;	char *p;	char *cardtype;	struct bt_regs *bt;	struct fb_ops *fbops;	fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);	if (fbops == NULL)		return NULL;		*fbops = *fb->info.fbops;	fbops->fb_rasterimg = cg6_rasterimg;	fb->info.fbops = fbops;		if (prom_getbool (fb->prom_node, "dblbuf")) {		type->fb_size *= 4;		fix->smem_len *= 4;	}	fix->line_length = fb->var.xres_virtual;	fix->accel = FB_ACCEL_SUN_CGSIX;		var->accel_flags = FB_ACCELF_TEXT;		disp->scrollmode = SCROLL_YREDRAW;	if (!disp->screen_base) {		disp->screen_base = (char *)			sbus_ioremap(&sdev->resource[0], CG6_RAM_OFFSET,				     type->fb_size, "cgsix ram");	}	disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;	fb->s.cg6.fbc = (struct cg6_fbc *)		sbus_ioremap(&sdev->resource[0], CG6_FBC_OFFSET,			     4096, "cgsix fbc");	fb->s.cg6.tec = (struct cg6_tec *)		sbus_ioremap(&sdev->resource[0], CG6_TEC_OFFSET,			     sizeof(struct cg6_tec), "cgsix tec");	fb->s.cg6.thc = (struct cg6_thc *)		sbus_ioremap(&sdev->resource[0], CG6_THC_OFFSET,			     sizeof(struct cg6_thc), "cgsix thc");	fb->s.cg6.bt = bt = (struct bt_regs *)		sbus_ioremap(&sdev->resource[0], CG6_BROOKTREE_OFFSET,			     sizeof(struct bt_regs), "cgsix dac");	fb->s.cg6.fhc = (u32 *)		sbus_ioremap(&sdev->resource[0], CG6_FHC_OFFSET,			     sizeof(u32), "cgsix fhc");#if 0	prom_printf("CG6: RES[%016lx:%016lx:%016lx]\n",		    sdev->resource[0].start,		    sdev->resource[0].end,		    sdev->resource[0].flags);	prom_printf("CG6: fbc(%p) tec(%p) thc(%p) bt(%p) fhc(%p)\n",		    fb->s.cg6.fbc,		    fb->s.cg6.tec,		    fb->s.cg6.thc,		    fb->s.cg6.bt,		    fb->s.cg6.fhc);	prom_halt();#endif	fb->dispsw = cg6_dispsw;	fb->margins = cg6_margins;	fb->loadcmap = cg6_loadcmap;	fb->setcursor = cg6_setcursor;	fb->setcursormap = cg6_setcursormap;	fb->setcurshape = cg6_setcurshape;	fb->restore_palette = cg6_restore_palette;	fb->fill = cg6_fill;	fb->blank = cg6_blank;	fb->unblank = cg6_unblank;	fb->reset = cg6_reset;		fb->physbase = phys;	fb->mmap_map = cg6_mmap_map;		/* Initialize Brooktree DAC */	sbus_writel(0x04 << 24, &bt->addr);         /* color planes */	sbus_writel(0xff << 24, &bt->control);	sbus_writel(0x05 << 24, &bt->addr);	sbus_writel(0x00 << 24, &bt->control);	sbus_writel(0x06 << 24, &bt->addr);         /* overlay plane */	sbus_writel(0x73 << 24, &bt->control);	sbus_writel(0x07 << 24, &bt->addr);	sbus_writel(0x00 << 24, &bt->control);		conf = sbus_readl(fb->s.cg6.fhc);	switch(conf & CG6_FHC_CPU_MASK) {	case CG6_FHC_CPU_SPARC: p = "sparc"; break;	case CG6_FHC_CPU_68020: p = "68020"; break;	default: p = "i386"; break;	}	if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) {		if (fix->smem_len <= 0x100000) {			cardtype = "TGX";		} else {			cardtype = "TGX+";		}	} else {		if (fix->smem_len <= 0x100000) {			cardtype = "GX";		} else {			cardtype = "GX+";		}	}	                                                                        	sprintf(idstring, #ifdef __sparc_v9__		    "cgsix at %016lx TEC Rev %x CPU %s Rev %x [%s]", phys,#else			    "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x [%s]",		    fb->iospace, phys, #endif		    ((sbus_readl(&fb->s.cg6.thc->thc_misc) >> CG6_THC_MISC_REV_SHIFT) &		     CG6_THC_MISC_REV_MASK),		    p, (conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK, cardtype);	sprintf(fb->info.modename, "CGsix [%s]", cardtype);	sprintf(fix->id, "CGsix [%s]", cardtype);		    	cg6_reset(fb);		    	return idstring;}

⌨️ 快捷键说明

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