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

📄 epson1356fb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 5 页
字号:
static inte1356_calc_pixclock(const struct fb_info_e1356 *info,		    pixclock_info_t* ipclk){	int src_sel=-1, flicker_mult=0;	pixclock_info_t test, ret;    	if (ipclk->pixclk > info->max_pixclock)		return -ENXIO;	test.pixclk_d = ipclk->pixclk_d;	ret.error = 100;		if (IS_TV(info->fix.disp_type) &&	    (info->fix.tv_filt & TV_FILT_FLICKER))		flicker_mult = 0x80;		test.clksrc = info->fix.busclk;	if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&	    abs(test.error) < abs(ret.error)) {		ret = test;		src_sel = 0x01;	}	test.clksrc = info->fix.mclk;	if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&	    abs(test.error) < abs(ret.error)) {		ret = test;		src_sel = 0x03;	}	test.clksrc = info->fix.clki;	if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&	    abs(test.error) < abs(ret.error)) {		ret = test;		src_sel = 0x00;	}	test.clksrc = info->fix.clki2;	if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 &&	    abs(test.error) < abs(ret.error)) {		ret = test;		src_sel = 0x02;	}	if (ret.error > MAX_PCLK_ERROR_LOWER ||	    ret.error < MAX_PCLK_ERROR_HIGHER)		return -ENXIO;    	ret.pixclk_bits = flicker_mult | ((ret.divisor-1)<<4) | src_sel;	*ipclk = ret;	return 0;}static inline inte1356_engine_wait_complete(reg_bitblt_t* bltreg){	return e1356_wait_bitclr(&bltreg->ctrl0, 0x80, 5000);}static inline inte1356_engine_wait_busy(reg_bitblt_t* bltreg){	return e1356_wait_bitset(&bltreg->ctrl0, 0x80, 5000);}static voide1356fb_engine_init(const struct e1356fb_par* par,		    struct fb_info_e1356* info){	reg_bitblt_t* bltreg = info->reg.bitblt;    	e1356_engine_wait_complete(bltreg);	writeb(0, &bltreg->ctrl0);	writeb(0, &bltreg->ctrl1);	writeb(0, &bltreg->rop_code);	writeb(0, &bltreg->operation);	writeb(0, &bltreg->src_start_addr0);	writeb(0, &bltreg->src_start_addr1);	writeb(0, &bltreg->src_start_addr2);	writeb(0, &bltreg->dest_start_addr0);	writeb(0, &bltreg->dest_start_addr1);	writeb(0, &bltreg->dest_start_addr2);	writew(0, &bltreg->mem_addr_offset0);	writew(0, &bltreg->width0);	writew(0, &bltreg->height0);	writew(0, &bltreg->bg_color0);	writew(0, &bltreg->fg_color0);}static void doBlt_Write(const struct e1356fb_par* par,			struct fb_info_e1356* info,			blt_info_t* blt){	reg_bitblt_t* bltreg = info->reg.bitblt;	int nWords, nTotalWords;	u32 srcphase, dstAddr;	u16* w16;	u32 stride = par->width_virt * par->Bpp;	dstAddr = blt->dst_x * par->Bpp + blt->dst_y * stride;	srcphase = (u32)blt->src & 1;    	if (blt->attribute & BLT_ATTR_TRANSPARENT)		writew(blt->bg_color, &bltreg->bg_color0);	else		writeb(blt->rop, &bltreg->rop_code);    	writeb(blt->operation, &bltreg->operation);	writeb((u8)srcphase, &bltreg->src_start_addr0);	writew(stride/2, &bltreg->mem_addr_offset0);	writeb(dstAddr, &bltreg->dest_start_addr0);	writeb(dstAddr>>8, &bltreg->dest_start_addr1);	writeb(dstAddr>>16, &bltreg->dest_start_addr2);	writew(blt->dst_width-1, &bltreg->width0);	writew(blt->dst_height-1, &bltreg->height0);	// program color format operation	writeb(par->bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1);	// start it up	writeb(0x80, &bltreg->ctrl0);	// wait for it to actually start	e1356_engine_wait_busy(bltreg);	// calculate the number of 16 bit words per one blt line	nWords = srcphase + ((blt->dst_width - srcphase)*par->Bpp + 1) / 2;	nTotalWords = nWords*blt->dst_height;	w16 = (u16*)((u32)blt->src & 0xfffffffe);   // Word aligned	while (nTotalWords > 0) {		int j, nFIFO;		u8 ctrl0;		// read the FIFO status		ctrl0 = readb(&bltreg->ctrl0);		if ((ctrl0 & 0x30) == 0x20)			// FIFO is at least half full, but not full			nFIFO = 1;		else if ((ctrl0 & 0x40) == 0)			// FIFO is empty			nFIFO = 16;		else			// FIFO is full			continue;		for (j = 0; j < nFIFO && nTotalWords > 0; j++,nTotalWords--)			writew(*w16++, info->reg.bitblt_data);	}	e1356_engine_wait_complete(bltreg);}static voiddoBlt_SolidFill(const struct e1356fb_par* par,		struct fb_info_e1356* info,		blt_info_t* blt){	reg_bitblt_t* bltreg = info->reg.bitblt;	u32 width = blt->dst_width, height = blt->dst_height;	u32 stride = par->width_virt * par->Bpp;	u32 dest_addr = (blt->dst_y * stride) + (blt->dst_x * par->Bpp);	if (width == 0 || height == 0)		return;	// program dest address	writeb(dest_addr & 0x00ff, &bltreg->dest_start_addr0);	writeb((dest_addr>>8) & 0x00ff, &bltreg->dest_start_addr1);	writeb((dest_addr>>16) & 0x00ff, &bltreg->dest_start_addr2);	// program width and height of solid-fill blit	writew(width-1, &bltreg->width0);	writew(height-1, &bltreg->height0);	// program color of fill	writew(blt->fg_color, &bltreg->fg_color0);	// select solid-fill BLIT	writeb(BLT_SOLID_FILL, &bltreg->operation);	// program color format operation	writeb(par->bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1);	// program BLIT memory offset	writew(stride/2, &bltreg->mem_addr_offset0);	// start it up (self completes)	writeb(0x80, &bltreg->ctrl0);	e1356_engine_wait_complete(bltreg);}static voiddoBlt_Move(const struct e1356fb_par* par,	   struct fb_info_e1356* info,	   blt_info_t* blt){	reg_bitblt_t* bltreg = info->reg.bitblt;	int neg_dir=0;	u32 dest_addr, src_addr;	u32 bpp = par->bpp;	u32 stride = par->width_virt * par->Bpp; // virt line length in bytes	u32 srcx = blt->src_x, srcy = blt->src_y;	u32 dstx = blt->dst_x, dsty = blt->dst_y;	u32 width = blt->dst_width, height = blt->dst_height;    	if (width == 0 || height == 0)		return;   	src_addr = srcx*par->Bpp + srcy*stride;	dest_addr = dstx*par->Bpp + dsty*stride;	/*	 * See if regions overlap and dest region is beyond source region.	 * If so, we need to do a move BLT in negative direction. Only applies	 * if the BLT is not transparent.	 */	if (!(blt->attribute & BLT_ATTR_TRANSPARENT)) {		if ((srcx + width  > dstx) && (srcx < dstx + width) &&		    (srcy + height > dsty) && (srcy < dsty + height) &&		    (dest_addr > src_addr)) {			neg_dir = 1;			// negative direction : get the coords of lower right corner			src_addr += stride * (height-1) + par->Bpp * (width-1);			dest_addr += stride * (height-1) + par->Bpp * (width-1);		}	}    	// program BLIT memory offset	writew(stride/2, &bltreg->mem_addr_offset0);	// program src and dest addresses	writeb(src_addr & 0x00ff, &bltreg->src_start_addr0);	writeb((src_addr>>8) & 0x00ff, &bltreg->src_start_addr1);	writeb((src_addr>>16) & 0x00ff, &bltreg->src_start_addr2);	writeb(dest_addr & 0x00ff, &bltreg->dest_start_addr0);	writeb((dest_addr>>8) & 0x00ff, &bltreg->dest_start_addr1);	writeb((dest_addr>>16) & 0x00ff, &bltreg->dest_start_addr2);	// program width and height of blit	writew(width-1, &bltreg->width0);	writew(height-1, &bltreg->height0);	// program color format operation	writeb(bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1);	// set the blt type	if (blt->attribute & BLT_ATTR_TRANSPARENT) {		writew(blt->bg_color, &bltreg->bg_color0);		writeb(BLT_MOVE_POS_TRANSP, &bltreg->operation); 	} else {		writeb(blt->rop, &bltreg->rop_code);		// select pos/neg move BLIT		writeb(neg_dir ? BLT_MOVE_NEG_ROP : BLT_MOVE_POS_ROP,		       &bltreg->operation); 	}	// start it up (self completes)	writeb(0x80, &bltreg->ctrl0);	e1356_engine_wait_complete(bltreg);}static void doBlt_ColorExpand(const struct e1356fb_par* par,			      struct fb_info_e1356* info,			      blt_info_t* blt){	reg_bitblt_t* bltreg = info->reg.bitblt;	int i, j, nWords, Sx, Sy;	u32 dstAddr;	u16* wpt, *wpt1;	u32 stride = par->width_virt * par->Bpp;	if (blt->dst_width == 0 || blt->dst_height == 0)		return;	Sx = blt->src_x;	Sy = blt->src_y;	writeb((7 - Sx%8), &bltreg->rop_code);	writeb(blt->operation, &bltreg->operation);	writeb((u8)(Sx & 1), &bltreg->src_start_addr0);	dstAddr = blt->dst_x*par->Bpp + blt->dst_y * stride;	writeb(dstAddr, &bltreg->dest_start_addr0);	writeb(dstAddr>>8, &bltreg->dest_start_addr1);	writeb(dstAddr>>16, &bltreg->dest_start_addr2);	// program color format operation	writeb(par->bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1);	writew(stride/2, &bltreg->mem_addr_offset0);	writew(blt->dst_width-1, &bltreg->width0);	writew(blt->dst_height-1, &bltreg->height0);	writew(blt->bg_color, &bltreg->bg_color0);	writew(blt->fg_color, &bltreg->fg_color0);	// start it up	writeb(0x80, &bltreg->ctrl0);	// wait for it to actually start	e1356_engine_wait_busy(bltreg);	// calculate the number of 16 bit words per one blt line	nWords = (Sx%16 + blt->dst_width + 15)/16;	wpt = blt->src + (Sy*blt->srcstride + Sx/16)/2;	for (i = 0; i < blt->dst_height; i++) {		wpt1 = wpt;		for (j = 0; j < nWords; j++) {			// loop until FIFO becomes empty...			e1356_wait_bitclr(&bltreg->ctrl0, 0x40, 10000);			writew(*wpt1++, info->reg.bitblt_data);		}			wpt += blt->srcstride/2;	}	e1356_engine_wait_complete(bltreg);}/* * The BitBLT operation dispatcher */static intdoBlt(const struct e1356fb_par* par,      struct fb_info_e1356* info,      blt_info_t* blt){	/*	 * Make sure we're not reentering in the middle of an	 * active BitBLT operation. ALWAYS call this dispatcher	 * and not one of the above BLT routines directly, or you	 * run the risk of overlapping BLT operations, which can	 * cause complete system hangs.     */	if (readb(&info->reg.bitblt->ctrl0) & 0x80)		return -ENXIO;    	switch (blt->operation) {	case BLT_MOVE_POS_ROP:	case BLT_MOVE_NEG_ROP:	case BLT_MOVE_POS_TRANSP:		doBlt_Move(par, info, blt);		break;	case BLT_COLOR_EXP:	case BLT_COLOR_EXP_TRANSP:		doBlt_ColorExpand(par, info, blt);		break;	case BLT_SOLID_FILL:		doBlt_SolidFill(par, info, blt);		break;	case BLT_WRITE_ROP:	case BLT_WRITE_TRANSP:		doBlt_Write(par, info, blt);		break;	case BLT_READ:	case BLT_PAT_FILL_ROP:	case BLT_PAT_FILL_TRANSP:	case BLT_MOVE_COLOR_EXP:	case BLT_MOVE_COLOR_EXP_TRANSP:		DPRINTK("BitBLT operation 0x%02x not implemented yet\n",			blt->operation);		return -ENXIO;	default:		DPRINTK("Unknown BitBLT operation 0x%02x\n", blt->operation);		return -ENXIO;	}    	return 0;}// Initializes blt->src and blt->srcstridestatic void fill_putcs_buffer(struct display *p,			      blt_info_t* blt,			      const unsigned short* str,			      int count){   	int row, i, j;	u8* b1, *b2;	u32 fw = fontwidth(p);	u32 fwb = (fw + 7) >> 3;	u32 fh = fontheight(p);	int bytesPerChar = fwb * fh;	if (count*bytesPerChar > PAGE_SIZE) {		// Truncate the string if it overflows putcs_buffer, which is		// one page in size.		count = PAGE_SIZE/bytesPerChar - 1;	}	blt->srcstride = (fwb*count + 1) & ~1; //round up to be even		b1 = (u8*)blt->src;	for (row = 0; row < fh; row++) {		b2 = b1;		for (i = 0; i < count; i++) {			for (j=0; j<fwb; j++)				*b2++ = p->fontdata[(str[i] & p->charmask) *						   bytesPerChar +						   row*fwb + j];		}		b1 += blt->srcstride;	}}/* * Set the color of a palette entry in 8bpp mode  */static inline voiddo_setpalentry(reg_lut_t* lut, unsigned regno,	       u8 r, u8 g, u8 b){	writeb(0x00, &lut->mode);	writeb((u8)regno, &lut->addr);	writeb(r&0xf0, &lut->data);	writeb(g&0xf0, &lut->data);	writeb(b&0xf0, &lut->data);}   static voiddo_pan_var(struct fb_var_screeninfo* var, struct fb_info_e1356* info){	u32 pixel_start, start_addr;	u8 pixel_pan;	struct e1356fb_par* par = &info->current_par;	reg_misc_t* misc = info->reg.misc;	reg_dispmode_t* dispmode = (IS_PANEL(info->fix.disp_type)) ?		info->reg.lcd_mode : info->reg.crttv_mode;		pixel_start = var->yoffset * par->width_virt + var->xoffset;	start_addr = (pixel_start * par->Bpp) / 2;	pixel_pan = (par->bpp == 8) ? (u8)(pixel_start & 1) : 0;    	if (readb(&misc->disp_mode) != 0) {		reg_dispcfg_t* dispcfg = (IS_PANEL(info->fix.disp_type)) ?			info->reg.lcd_cfg : info->reg.crttv_cfg;		// wait for the end of the current VNDP		e1356_wait_bitclr(&dispcfg->vndp, 0x80, 5000);		// now wait for the start of a new VNDP		e1356_wait_bitset(&dispcfg->vndp, 0x80, 5000);	}    	writeb((u8)(start_addr & 0xff), &dispmode->start_addr0);	writeb((u8)((start_addr>>8) & 0xff), &dispmode->start_addr1);	writeb((u8)((start_addr>>16) & 0xff), &dispmode->start_addr2);	writeb(pixel_pan, &dispmode->pixel_panning);}/* * Invert the hardware cursor image (timerfunc)   */static voiddo_flashcursor(unsigned long ptr){	u8 curs_ctrl;	struct fb_info_e1356* info = (struct fb_info_e1356 *)ptr;	reg_inkcurs_t* inkcurs = (IS_PANEL(info->fix.disp_type)) ?		info->reg.lcd_inkcurs : info->reg.crttv_inkcurs;	spin_lock(&info->cursor.lock);	// toggle cursor enable bit	curs_ctrl = readb(&inkcurs->ctrl);	writeb((curs_ctrl ^ 0x01) & 0x01, &inkcurs->ctrl);	info->cursor.timer.expires = jiffies+HZ/2;	add_timer(&info->cursor.timer);	spin_unlock(&info->cursor.lock);

⌨️ 快捷键说明

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