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

📄 pm2fb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (p->video & PM2F_DATA_64_ENABLE) {		v.xres=v.xres<<1;		v.right_margin=v.right_margin<<1;		v.hsync_len=v.hsync_len<<1;		v.left_margin=v.left_margin<<1;	}	switch (p->depth) {		case 8:			v.red.length=v.green.length=v.blue.length=8;			v.xres=v.xres<<2;			v.right_margin=v.right_margin<<2;			v.hsync_len=v.hsync_len<<2;			v.left_margin=v.left_margin<<2;			break;		case 16:			v.red.offset=11;			v.red.length=5;			v.green.offset=5;			v.green.length=6;			v.blue.length=5;			v.xres=v.xres<<1;			v.right_margin=v.right_margin<<1;			v.hsync_len=v.hsync_len<<1;			v.left_margin=v.left_margin<<1;			break;		case 32:			v.transp.offset=24;			v.red.offset=16;			v.green.offset=8;			v.red.length=v.green.length=v.blue.length=							v.transp.length=8;			break;		case 24:			v.blue.offset=16;			v.green.offset=8;			v.red.length=v.green.length=v.blue.length=8;			v.xres=(v.xres<<2)/3;			v.right_margin=(v.right_margin<<2)/3;			v.hsync_len=(v.hsync_len<<2)/3;			v.left_margin=(v.left_margin<<2)/3;			break;	}	base=from3264(p->base, p->depth, 1);	v.xoffset=base%v.xres;	v.yoffset=base/v.xres;	v.height=v.width=-1;	v.pixclock=KHZ2PICOS(p->pixclock);	if ((p->video & PM2F_HSYNC_MASK)==PM2F_HSYNC_ACT_HIGH)		v.sync|=FB_SYNC_HOR_HIGH_ACT;	if ((p->video & PM2F_VSYNC_MASK)==PM2F_VSYNC_ACT_HIGH)		v.sync|=FB_SYNC_VERT_HIGH_ACT;	if (p->video & PM2F_LINE_DOUBLE)		v.vmode=FB_VMODE_DOUBLE;	*var=v;	return 0;}static void set_user_mode(struct pm2fb_info* i) {	if (pm2fb_options.flags & OPTF_YPAN) {		int h = i->current_par.height;		i->current_par.height=i->regions.fb_size/			(i->current_par.width*i->current_par.depth/8);		i->current_par.height=MIN(i->current_par.height,2047);		i->current_par.height=MAX(i->current_par.height,h);	}}static void pm2fb_get_par(void* par, struct fb_info_gen* info) {	struct pm2fb_info* i=(struct pm2fb_info* )info;		if (!i->current_par_valid) {		set_user_mode(i);		pm2fb_reset(i);		set_screen(i, &i->current_par);		i->current_par_valid=1;	}	*((struct pm2fb_par* )par)=i->current_par;}static void pm2fb_set_par(const void* par, struct fb_info_gen* info) {	struct pm2fb_info* i=(struct pm2fb_info* )info;	struct pm2fb_par* p;	p=(struct pm2fb_par* )par;	if (i->current_par_valid) {		i->current_par.base=p->base;		if (!memcmp(p, &i->current_par, sizeof(struct pm2fb_par))) {			WAIT_FIFO(i, 1);			pm2_WR(i, PM2R_SCREEN_BASE, p->base);			return;		}	}	set_screen(i, p);	i->current_par=*p;	i->current_par_valid=1;#ifdef PM2FB_HW_CURSOR		if (i->cursor) {		pm2v_set_cursor_color(i, cursor_color_map, cursor_color_map, cursor_color_map);		pm2v_set_cursor_shape(i);	}#endif}static int pm2fb_getcolreg(unsigned regno,			unsigned* red, unsigned* green, unsigned* blue,				unsigned* transp, struct fb_info* info) {	struct pm2fb_info* i=(struct pm2fb_info* )info;	if (regno<256) {		*red=i->palette[regno].red<<8|i->palette[regno].red;		*green=i->palette[regno].green<<8|i->palette[regno].green;		*blue=i->palette[regno].blue<<8|i->palette[regno].blue;		*transp=i->palette[regno].transp<<8|i->palette[regno].transp;	}	return regno>255;}static int pm2fb_setcolreg(unsigned regno,			unsigned red, unsigned green, unsigned blue,				unsigned transp, struct fb_info* info) {	struct pm2fb_info* i=(struct pm2fb_info* )info;	if (regno<16) {		switch (i->current_par.depth) {#ifdef FBCON_HAS_CFB8			case 8:				break;#endif#ifdef FBCON_HAS_CFB16			case 16:				i->cmap.cmap16[regno]=					((u32 )red & 0xf800) |					(((u32 )green & 0xfc00)>>5) |					(((u32 )blue & 0xf800)>>11);				break;#endif#ifdef FBCON_HAS_CFB24			case 24:				i->cmap.cmap24[regno]=					(((u32 )blue & 0xff00) << 8) |					((u32 )green & 0xff00) |					(((u32 )red & 0xff00) >> 8);				break;#endif#ifdef FBCON_HAS_CFB32			case 32:	   			i->cmap.cmap32[regno]=					(((u32 )transp & 0xff00) << 16) |		    			(((u32 )red & 0xff00) << 8) |					(((u32 )green & 0xff00)) |			 		(((u32 )blue & 0xff00) >> 8);				break;#endif			default:				DPRINTK("bad depth %u\n",						i->current_par.depth);				break;		}	}	if (regno<256) {		i->palette[regno].red=red >> 8;		i->palette[regno].green=green >> 8;		i->palette[regno].blue=blue >> 8;		i->palette[regno].transp=transp >> 8;		if (i->current_par.depth==8)			set_color(i, regno, red>>8, green>>8, blue>>8);	}	return regno>255;}static void pm2fb_set_disp(const void* par, struct display* disp,						   struct fb_info_gen* info) {	struct pm2fb_info* i=(struct pm2fb_info* )info;	unsigned long flags;	unsigned long depth;	save_flags(flags);	cli();	disp->screen_base = i->regions.v_fb;	switch (depth=((struct pm2fb_par* )par)->depth) {#ifdef FBCON_HAS_CFB8		case 8:			disp->dispsw=&pm2_cfb8;			break;#endif#ifdef FBCON_HAS_CFB16		case 16:			disp->dispsw=&pm2_cfb16;			disp->dispsw_data=i->cmap.cmap16;			break;#endif#ifdef FBCON_HAS_CFB24		case 24:			disp->dispsw=&pm2_cfb24;			disp->dispsw_data=i->cmap.cmap24;			break;#endif#ifdef FBCON_HAS_CFB32		case 32:			disp->dispsw=&pm2_cfb32;			disp->dispsw_data=i->cmap.cmap32;			break;#endif		default:			disp->dispsw=&fbcon_dummy;			break;	}	restore_flags(flags);}#ifdef PM2FB_HW_CURSOR/*************************************************************************** * Hardware cursor support ***************************************************************************/ static u8 cursor_bits_lookup[16] = {	0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55};static u8 cursor_mask_lookup[16] = {	0x00, 0x80, 0x20, 0xa0, 0x08, 0x88, 0x28, 0xa8,	0x02, 0x82, 0x22, 0xa2, 0x0a, 0x8a, 0x2a, 0xaa};static void pm2v_set_cursor_color(struct pm2fb_info *fb, u8 *red, u8 *green, u8 *blue){	struct pm2_cursor *c = fb->cursor;	int i;	for (i = 0; i < 2; i++) {		c->color[3*i] = red[i];		c->color[3*i+1] = green[i];		c->color[3*i+2] = blue[i];	}	WAIT_FIFO(fb, 14);	pm2_WR(fb, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CURSOR_PALETTE >> 8);	for (i = 0; i < 6; i++)		pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PALETTE+i, c->color[i]);	pm2_WR(fb, PM2VR_RD_INDEX_HIGH, 0);}static void pm2v_set_cursor_shape(struct pm2fb_info *fb){	struct pm2_cursor *c = fb->cursor;	u8 m, b;	int i, x, y;	WAIT_FIFO(fb, 1);	pm2_WR(fb, PM2VR_RD_INDEX_HIGH, PM2VI_RD_CURSOR_PATTERN >> 8);	for (y = 0, i = 0; y < c->size.y; y++) {		WAIT_FIFO(fb, 32);		for (x = 0; x < c->size.x >> 3; x++) {			m = c->mask[x][y];			b = c->bits[x][y];			pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i,				     cursor_mask_lookup[m >> 4] |				     cursor_bits_lookup[(b & m) >> 4]);			pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i + 1,				     cursor_mask_lookup[m & 0x0f] |				     cursor_bits_lookup[(b & m) & 0x0f]);			i+=2;		}		for ( ; x < 8; x++) {			pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i, 0);			pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i + 1, 0);			i+=2;		}	}	for (; y < 64; y++) {		WAIT_FIFO(fb, 32);		for (x = 0; x < 8; x++) {			pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i, 0);			pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_PATTERN + i + 1, 0);			i+=2;		}	}	WAIT_FIFO(fb, 1);	pm2_WR(fb, PM2VR_RD_INDEX_HIGH, 0);}static void pm2v_set_cursor(struct pm2fb_info *fb, int on){	struct pm2_cursor *c = fb->cursor;	int x = c->pos.x;	if (!on) x = 4000;	WAIT_FIFO(fb, 14);	pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_X_LOW, x & 0xff);	pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_X_HIGH, (x >> 8) & 0x0f);	pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_Y_LOW, c->pos.y & 0xff);	pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_Y_HIGH, (c->pos.y >> 8) & 0x0f);	pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_X_HOT, c->hot.x & 0x3f);	pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_Y_HOT, c->hot.y & 0x3f);	pm2v_RDAC_WR(fb, PM2VI_RD_CURSOR_MODE, 0x11);}static void pm2_cursor_timer_handler(unsigned long dev_addr){	struct pm2fb_info *fb = (struct pm2fb_info *)dev_addr;	if (!fb->cursor->enable)		goto out;	if (fb->cursor->vbl_cnt && --fb->cursor->vbl_cnt == 0) {		fb->cursor->on ^= 1;		pm2v_set_cursor(fb, fb->cursor->on);		fb->cursor->vbl_cnt = fb->cursor->blink_rate;	}out:	fb->cursor->timer->expires = jiffies + (HZ / 50);	add_timer(fb->cursor->timer);}static void pm2fb_cursor(struct display *p, int mode, int x, int y){	struct pm2fb_info *fb = (struct pm2fb_info *)p->fb_info;	struct pm2_cursor *c = fb->cursor;	if (!c) return;	x *= fontwidth(p);	y *= fontheight(p);	if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable)		return;	c->enable = 0;	if (c->on)		pm2v_set_cursor(fb, 0);	c->pos.x = x;	c->pos.y = y;	switch (mode) {	case CM_ERASE:		c->on = 0;		break;	case CM_DRAW:	case CM_MOVE:		if (c->on)			pm2v_set_cursor(fb, 1);		else			c->vbl_cnt = CURSOR_DRAW_DELAY;		c->enable = 1;		break;	}}static struct pm2_cursor * __init pm2_init_cursor(struct pm2fb_info *fb){	struct pm2_cursor *cursor;	if (fb->type != PM2_TYPE_PERMEDIA2V)		return 0; /* FIXME: Support hw cursor everywhere */	cursor = kmalloc(sizeof(struct pm2_cursor), GFP_ATOMIC);	if (!cursor)		return 0;	memset(cursor, 0, sizeof(*cursor));	cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL);	if (!cursor->timer) {		kfree(cursor);		return 0;	}	memset(cursor->timer, 0, sizeof(*cursor->timer));	cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;	if (curblink) {		init_timer(cursor->timer);		cursor->timer->expires = jiffies + (HZ / 50);		cursor->timer->data = (unsigned long)fb;		cursor->timer->function = pm2_cursor_timer_handler;		add_timer(cursor->timer);	}	return cursor;}static int pm2fb_set_font(struct display *d, int width, int height){	struct pm2fb_info *fb = (struct pm2fb_info *)d->fb_info;	struct pm2_cursor *c = fb->cursor;	int i, j;	if (c) {		if (!width || !height) {			width = 8;			height = 16;		}		c->hot.x = 0;		c->hot.y = 0;		c->size.x = width;		c->size.y = height;		memset(c->bits, 0xff, sizeof(c->bits));		memset(c->mask, 0, sizeof(c->mask));		for (i = 0, j = width; j >= 0; j -= 8, i++) {			c->mask[i][height-2] = (j >= 8) ? 0xff : (0xff << (8 - j));			c->mask[i][height-1] = (j >= 8) ? 0xff : (0xff << (8 - j));		}		pm2v_set_cursor_color(fb, cursor_color_map, cursor_color_map, cursor_color_map);		pm2v_set_cursor_shape(fb);	}	return 1;}#endif /* PM2FB_HW_CURSOR *//*************************************************************************** * Begin of public functions ***************************************************************************/#ifdef MODULEstatic void pm2fb_cleanup(void) {	struct pm2fb_info* i = &fb_info;	unregister_framebuffer((struct fb_info *)i);	pm2fb_reset(i);	UNMAP(i->regions.v_fb, i->regions.fb_size);	release_mem_region(i->regions.p_fb, i->regions.fb_size);	UNMAP(i->regions.v_regs, PM2_REGS_SIZE);	release_mem_region(i->regions.p_regs, PM2_REGS_SIZE);	if (board_table[i->board].cleanup)		board_table[i->board].cleanup(i);}#endif /* MODULE */int __init pm2fb_init(void){	MOD_INC_USE_COUNT;	memset(&fb_info, 0, sizeof(fb_info));	memcpy(&fb_info.current_par, &pm2fb_options.user_mode, sizeof(fb_info.current_par));	if (!pm2fb_conf(&fb_info)) {		MOD_DEC_USE_COUNT;		return -ENXIO;	}	pm2fb_reset(&fb_info);	fb_info.disp.scrollmode=SCROLL_YNOMOVE;	fb_info.gen.parsize=sizeof(struct pm2fb_par);	fb_info.gen.fbhw=&pm2fb_hwswitch;	strcpy(fb_info.gen.info.modename, permedia2_name);	fb_info.gen.info.flags=FBINFO_FLAG_DEFAULT;	fb_info.gen.info.fbops=&pm2fb_ops;	fb_info.gen.info.disp=&fb_info.disp;	strcpy(fb_info.gen.info.fontname, pm2fb_options.font);	fb_info.gen.info.switch_con=&fbgen_switch;	fb_info.gen.info.updatevar=&fbgen_update_var;	fb_info.gen.info.blank=&fbgen_blank;	fbgen_get_var(&fb_info.disp.var, -1, &fb_info.gen.info);	fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen);	fbgen_set_disp(-1, &fb_info.gen);	fbgen_install_cmap(0, &fb_info.gen);	if (register_framebuffer(&fb_info.gen.info)<0) {		printk(KERN_ERR "pm2fb: unable to register.\n");		MOD_DEC_USE_COUNT;		return -EINVAL;	}	printk(KERN_INFO "fb%d: %s (%s), using %uK of video memory.\n",				GET_FB_IDX(fb_info.gen.info.node),				board_table[fb_info.board].name,				permedia2_name,				(u32 )(fb_info.regions.fb_size>>10));	return 0;}static void __init pm2fb_mode_setup(char* options){	int i;	for (i=0; user_mode[i].name[0] &&		strcmp(options, user_mode[i].name); i++);	if (user_mode[i].name[0]) {		memcpy(&pm2fb_options.user_mode, &user_mode[i].par,					sizeof(pm2fb_options.user_mode));		pm2fb_options.flags |= OPTF_USER;	}}static void __init pm2fb_font_setup(char* options){	strncpy(pm2fb_options.font, options, sizeof(pm2fb_options.font));	pm2fb_options.font[sizeof(pm2fb_options.font)-1]='\0';}int __init pm2fb_setup(char* options){	char* next;	while (options) {		if ((next=strchr(options, ',')))			*(next++)='\0';		if (!strncmp(options, "font:", 5))			pm2fb_font_setup(options+5);		else if (!strncmp(options, "mode:", 5))			pm2fb_mode_setup(options+5);		else if (!strcmp(options, "ypan"))			pm2fb_options.flags |= OPTF_YPAN;		else if (!strcmp(options, "oldmem"))			pm2fb_options.flags |= OPTF_OLD_MEM;		else if (!strcmp(options, "virtual"))			pm2fb_options.flags |= OPTF_VIRTUAL;		else if (!strcmp(options, "noblink"))			curblink = 0;		options=next;	}	return 0;}/*************************************************************************** * Begin of module functions ***************************************************************************/#ifdef MODULEMODULE_LICENSE("GPL");static char *mode = NULL;MODULE_PARM(mode, "s");int __init init_module(void) {	if (mode) pm2fb_mode_setup(mode);	return pm2fb_init();}void cleanup_module(void) {	pm2fb_cleanup();}#endif /* MODULE *//*************************************************************************** * That's all folks! ***************************************************************************/

⌨️ 快捷键说明

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