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

📄 ep93xxfb.c

📁 linux下ep9315的LCD驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	outl( pal, (COLOR_LUT+(regno<<2)) );	cont = inl(LUTCONT);	if ((cont&LUTCONT_STAT && cont&LUTCONT_RAM1) ||	    (!(cont&LUTCONT_STAT) && !(cont&LUTCONT_RAM1))) {		// LUT switch is no longer pending		// We do not know if write to LUT above really went		// to currently active LUT.  So need to make sure that		// data gets into inactive LUT and switch LUTs.		//		// But currently inactive LUT may be out of date		// in more entries than just last write.		// Need to update currently inactive LUT for all writes		// which went to currently active LUT.		// Fully update the LUT now, which is a simpler policy		// than trying to track writes and do partial update of LUT.		// (Worstcase impact: we update palette every frame)		for (i=0; i< 256; i++)	// Update inactive LUT			outl( master_palette[i], (COLOR_LUT+(i<<2)) );		// Switch active LUTs next frame		outl( cont ^ LUTCONT_RAM1, LUTCONT );	}}static inline voidep93xxfb_palette_read(u_int regno, u_int *red, u_int *green,		      u_int *blue, u_int *trans){	// Only supports color LUT, not gray LUT	unsigned int pal;	// Read only needs to access master palette, not hw palettes.	pal = master_palette[regno];	//TBD LCD mode may change LUT from R/G/B order to B/G/R order	*red = (pal >> 8) & 0xFF00;	*green = pal & 0xFF00;	*blue = (pal << 8) & 0xFF00;	*trans  = 0;}//-----------------------------------------------------------------------------//	Helper functions for fb driver//-----------------------------------------------------------------------------static intep93xxfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,		   u_int *trans, struct fb_info *info){	if (regno >= mypar.palette_size)		return 1;	ep93xxfb_palette_read(regno, red, green, blue, trans);	return 0;}static inline u_intchan_to_field(u_int chan, struct fb_bitfield *bf){	chan &= 0xffff;	chan >>= 16 - bf->length;	return chan << bf->offset;}static intep93xxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,		   u_int trans, struct fb_info *info){	u_int val;	if (regno >= mypar.palette_size)		return 1;	switch (info->disp->visual) {	case FB_VISUAL_TRUECOLOR:		if (regno < 16) {			u16 *pal = info->pseudo_palette;			val  = chan_to_field(red, &info->var.red);			val |= chan_to_field(green, &info->var.green);			val |= chan_to_field(blue, &info->var.blue);				pal[regno] = val;		}		break;	case FB_VISUAL_PSEUDOCOLOR:		ep93xxfb_palette_write(regno, red, green, blue, trans);		break;	}	return 0;}//TBD Warning: fbmem.c ioctl could result in any of the helper functions being//TBD called with con=-1, which happens when info->display_fg == NULL,//TBD which presumably is only during initialization of fbcon.//TBD Is there any other condition under which con=-1?//TBD Maybe we do not even need to support it!static intep93xxfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,		          struct fb_info *info){	int err = 0;	//TBD does not expect call with con=-1 if currcon!=-1	if (con == -1)		DPRINTK("get_cmap called with con=-1\n");	DPRINTK("mypar.visual=%d\n", mypar.visual);	if (con == mypar.currcon)		err = fb_get_cmap(cmap, kspc, ep93xxfb_getcolreg, info);	else if (fb_display[con].cmap.len)		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);	else		fb_copy_cmap(fb_default_cmap(mypar.palette_size),			     cmap, kspc ? 0 : 2);	return err;}static intep93xxfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,		  struct fb_info *info){	int err = 0;	//	// What kind of request is this???	//	if (con == -1) {		DPRINTK("ERROR set_cmap called with con=-1\n");		return(-1);	}	DPRINTK("mypar.visual=%d\n", mypar.visual);	if (!fb_display[con].cmap.len)		err = fb_alloc_cmap(&fb_display[con].cmap, mypar.palette_size,				    0);	if (!err) {		if (con == mypar.currcon)			err = fb_set_cmap(cmap, kspc, ep93xxfb_setcolreg,					  info);		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);	}	return err;}static unsigned long cursor_data[64][4];static voidep93xxfb_cursor(struct ep93xx_cursor *cursor){	unsigned long data[64 * 4];	long i, x, y, save;	if (cursor->flags & CURSOR_OFF)		outl(inl(CURSORXYLOC) & ~0x00008000, CURSORXYLOC);	if (cursor->flags & CURSOR_SETSHAPE) {		copy_from_user(data, cursor->data,			       cursor->width * cursor->height / 4);		save = inl(CURSORXYLOC);		outl(save & ~0x00008000, CURSORXYLOC);		for (y = 0, i = 0; y < cursor->height; y++) {			for (x = 0; x < cursor->width; x += 16)				cursor_data[y][x] = data[i++];		}		outl(virt_to_phys(cursor_data), CURSOR_ADR_START);		outl(virt_to_phys(cursor_data), CURSOR_ADR_RESET);		outl(0x00000300 | ((cursor->height - 1) << 2) |		     ((cursor->width - 1) >> 4), CURSORSIZE);		outl(save, CURSORXYLOC);	}	if (cursor->flags & CURSOR_SETCOLOR) {		outl(cursor->color1, CURSORCOLOR1);		outl(cursor->color2, CURSORCOLOR2);		outl(cursor->blinkcolor1, CURSORBLINK1);		outl(cursor->blinkcolor2, CURSORBLINK2);	}	if (cursor->flags & CURSOR_BLINK) {		if (cursor->blinkrate)			outl(0x00000100 | cursor->blinkrate, CURSORBLINK);		else			outl(0x000000ff, CURSORBLINK);	}	if (cursor->flags & CURSOR_MOVE) {		x = (inl(HACTIVESTRTSTOP) & 0x000003ff) - cursor->dx - 2;		y = (inl(VACTIVESTRTSTOP) & 0x000003ff) - cursor->dy;		outl((inl(CURSORXYLOC) & 0x8000) | (y << 16) | x, CURSORXYLOC);	}	if (cursor->flags & CURSOR_ON)		outl(inl(CURSORXYLOC) | 0x00008000, CURSORXYLOC);}#ifdef CONFIG_EP93XX_GRAPHICS#ifdef CONFIG_FB_EP93XX_8BPP#define BITS_PER_PIXEL 8#define BYTES_PER_PIXEL 1#define PIXEL_MASK 3#define PIXEL_SHIFT 2#define PIXEL_FORMAT 0x00040000#endif#ifdef CONFIG_FB_EP93XX_16BPP_565#define BITS_PER_PIXEL 16#define BYTES_PER_PIXEL 2#define PIXEL_MASK 1#define PIXEL_SHIFT 1#define PIXEL_FORMAT 0x00080000#endif#define BYTES_PER_LINE (fb_info.var.xres * BYTES_PER_PIXEL)static DECLARE_WAIT_QUEUE_HEAD(ep93xxfb_wait_in);static voidep93xxfb_irq_handler(int i, void *blah, struct pt_regs *regs){	outl(0x00000000, BLOCKCTRL);	wake_up_interruptible(&ep93xxfb_wait_in);}static voidep93xxfb_wait(void){	DECLARE_WAITQUEUE(wait, current);	add_wait_queue(&ep93xxfb_wait_in, &wait);	current->state = TASK_INTERRUPTIBLE;	while (inl(BLOCKCTRL) & 0x00000001) {		schedule();		current->state = TASK_INTERRUPTIBLE;	}	remove_wait_queue(&ep93xxfb_wait_in, &wait);	current->state = TASK_RUNNING;}static unsigned char pucBlitBuf[4096];static intep93xxfb_blit(struct ep93xx_blit *blit){	unsigned long value = 0, size, dx1, dx2, dy1, sx1, sx2, sy1;	if ((blit->dx >= fb_info.var.xres) ||	    (blit->dy >= fb_info.var.yres) ||	    ((blit->dx + blit->width - 1) >= fb_info.var.xres) ||	    ((blit->dy + blit->height - 1) >= fb_info.var.yres))		return -EFAULT;	value = blit->flags & (BLIT_TRANSPARENT | BLIT_MASK_MASK |			       BLIT_DEST_MASK | BLIT_1BPP_SOURCE);	if ((blit->flags & BLIT_SOURCE_MASK) == BLIT_SOURCE_MEMORY) {		if (blit->flags & BLIT_1BPP_SOURCE) {			size = blit->swidth * blit->height / 8;			if (size <= 4096)				copy_from_user(pucBlitBuf, blit->data, size);			else {				for (size = blit->height; size; ) {					blit->height = 32768 / blit->swidth;					if (blit->height > size)						blit->height = size;					ep93xxfb_blit(blit);					blit->dy += blit->height;					blit->data += blit->swidth *						      blit->height / 8;					size -= blit->height;				}				return 0;			}			if (blit->flags & BLIT_TRANSPARENT)				value ^= 0x00004000;			outl(0x00000007, SRCPIXELSTRT);			outl(blit->swidth >> 5, SRCLINELENGTH);			outl((blit->width - 1) >> 5, BLKSRCWIDTH);			outl(blit->bgcolor, BACKGROUND);		} else {			size = blit->swidth * blit->height * BYTES_PER_PIXEL;			if (size <= 4096)				copy_from_user(pucBlitBuf, blit->data, size);			else {				for (size = blit->height; size; ) {					blit->height = 4096 / BYTES_PER_PIXEL /						       blit->swidth;					if (blit->height > size)						blit->height = size;					ep93xxfb_blit(blit);					blit->dy += blit->height;					blit->data += blit->swidth *						      blit->height *						      BYTES_PER_PIXEL;					size -= blit->height;				}				return 0;			}			outl(0x00000000, SRCPIXELSTRT);			outl(blit->swidth >> PIXEL_SHIFT, SRCLINELENGTH);			outl((blit->width - 1) >> PIXEL_SHIFT, BLKSRCWIDTH);		}		outl(virt_to_phys(pucBlitBuf), BLKSRCSTRT);		dx1 = blit->dx;		dy1 = blit->dy;		dx2 = blit->dx + blit->width - 1;	} else {		if ((blit->sx >= fb_info.var.xres) ||		    (blit->sy >= fb_info.var.yres) ||		    ((blit->sx + blit->width - 1) >= fb_info.var.xres) ||		    ((blit->sy + blit->height - 1) >= fb_info.var.yres))			return -EFAULT;		if ((blit->dy == blit->sy) && (blit->dx == blit->sx))			return 0;		if ((blit->dy == blit->sy) &&		    (blit->dx > blit->sx) &&		    (blit->dx < (blit->sx + blit->width - 1))) {			dx1 = blit->dx + blit->width - 1;			dx2 = blit->dx;			sx1 = blit->sx + blit->width - 1;			sx2 = blit->sx;			value |= 0x000000a0;		} else {			dx1 = blit->dx;			dx2 = blit->dx + blit->width - 1;			sx1 = blit->sx;			sx2 = blit->sx + blit->width - 1;		}		if (blit->dy <= blit->sy) {			dy1 = blit->dy;			sy1 = blit->sy;		} else {			dy1 = blit->dy + blit->height - 1;			sy1 = blit->sy + blit->height - 1;			value |= 0x00000140;		}		outl(((sx1 & PIXEL_MASK) * BITS_PER_PIXEL) |		     (((sx2 & PIXEL_MASK) * BITS_PER_PIXEL) << 16),		     SRCPIXELSTRT);		outl(inl(VIDSCRNPAGE) + (sy1 * BYTES_PER_LINE) +		     ((sx1 * BYTES_PER_PIXEL) & ~PIXEL_MASK), BLKSRCSTRT);		outl(BYTES_PER_LINE / 4, SRCLINELENGTH);		if (sx1 < sx2)			outl((sx2 >> PIXEL_SHIFT) - (sx1 >> PIXEL_SHIFT),			     BLKSRCWIDTH);		else			outl((sx1 >> PIXEL_SHIFT) - (sx2 >> PIXEL_SHIFT),			     BLKSRCWIDTH);	}	outl(((dx1 & PIXEL_MASK) * BITS_PER_PIXEL) |	     (((dx2 & PIXEL_MASK) * BITS_PER_PIXEL) << 16), DESTPIXELSTRT);	outl(inl(VIDSCRNPAGE) + (dy1 * BYTES_PER_LINE) +	     ((dx1 * BYTES_PER_PIXEL) & ~PIXEL_MASK), BLKDSTSTRT);	outl(BYTES_PER_LINE / 4, DESTLINELENGTH);	if (dx1 < dx2)		outl((dx2 >> PIXEL_SHIFT) - (dx1 >> PIXEL_SHIFT),		     BLKDESTWIDTH);	else		outl((dx1 >> PIXEL_SHIFT) - (dx2 >> PIXEL_SHIFT),		     BLKDESTWIDTH);	outl(blit->height - 1, BLKDESTHEIGHT);	outl(blit->fgcolor, BLOCKMASK);	outl(blit->transcolor, TRANSPATTRN);	outl(value | PIXEL_FORMAT | 0x00000003, BLOCKCTRL);	ep93xxfb_wait();	return 0;}static intep93xxfb_fill(struct ep93xx_fill *fill){	if ((fill->dx >= fb_info.var.xres) ||	    (fill->dy >= fb_info.var.yres))		return -EFAULT;	if ((fill->dx + fill->width - 1) >= fb_info.var.xres)		fill->width = fb_info.var.xres - fill->dx;	if ((fill->dy + fill->height - 1) >= fb_info.var.yres)		fill->height = fb_info.var.yres - fill->dy;	outl(mypar.p_screen_base + (fill->dy * BYTES_PER_LINE) +	     ((fill->dx * BYTES_PER_PIXEL) & ~PIXEL_MASK), BLKDSTSTRT);	outl(((fill->dx & PIXEL_MASK) * BITS_PER_PIXEL) |	     ((((fill->dx + fill->width - 1) & PIXEL_MASK) *	       BITS_PER_PIXEL) << 16), DESTPIXELSTRT);	outl(BYTES_PER_LINE / 4, DESTLINELENGTH);	outl(((fill->dx + fill->width - 1) >> PIXEL_SHIFT) -	     (fill->dx >> PIXEL_SHIFT), BLKDESTWIDTH);	outl(fill->height - 1, BLKDESTHEIGHT);	outl(fill->color, BLOCKMASK);	outl(PIXEL_FORMAT | 0x0000000b, BLOCKCTRL);	ep93xxfb_wait();	return 0;}static unsigned longisqrt(unsigned long a){	unsigned long rem = 0;	unsigned long root = 0;	int i;	for (i = 0; i < 16; i++) {		root <<= 1;		rem = ((rem << 2) + (a >> 30));		a <<= 2;		root++;		if (root <= rem) {			rem -= root;			root++;		} else			root--;	}	return root >> 1;}static intep93xxfb_line(struct ep93xx_line *line){	unsigned long value = 0;	long dx, dy, count, xinc, yinc, xval, yval, incr;	if ((line->x1 >= fb_info.var.xres) ||	    (line->x2 >= fb_info.var.xres) ||	    (line->y1 >= fb_info.var.yres) ||	    (line->y2 >= fb_info.var.yres))		return -EFAULT;	dx = line->x2 - line->x1;	if (dx < 0) {		value |= 0x00000020;		dx *= -1;	}	dy = line->y2 - line->y1;	if (dy < 0) {		value |= 0x00000040;		dy *= -1;

⌨️ 快捷键说明

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