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

📄 au1200fb.c

📁 为AU1200芯片linux系统所设计的LCD液晶显示驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
				iodata.winsize.hsz =					(lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11;				iodata.winsize.vsz =					(lcd->window[plane].winctrl0 & LCD_WINCTRL1_SZY) >> 0;				break;			case AU1200_LCD_SET_WINSIZE:				au1200_setsize(plane, iodata.winsize.hsz, iodata.winsize.vsz);				break;			case AU1200_LCD_GET_BACKCOLOR:				iodata.backcolor.color = lcd->backcolor;				break;			case AU1200_LCD_SET_BACKCOLOR:				 lcd->backcolor = iodata.backcolor.color;				break;			case AU1200_LCD_GET_COLORKEY:				iodata.colorkey.key = lcd->colorkey;				iodata.colorkey.mask = lcd->colorkeymsk;				break;			case AU1200_LCD_SET_COLORKEY:				lcd->colorkey = iodata.colorkey.key;				lcd->colorkeymsk = iodata.colorkey.mask;				break;			case AU1200_LCD_GET_PANEL:				iodata.panel.panel = panel_index;				break;			case AU1200_LCD_SET_PANEL:				if ((iodata.panel.panel >= 0) && (iodata.panel.panel < NUM_PANELS))				{					struct panel_settings *newpanel;					panel_index = iodata.panel.panel;					newpanel = &panels[panel_index];					au1200_setpanel(newpanel);				}				break;		}		return copy_to_user((void *) arg, &iodata, sizeof(au1200_lcd_getset_t)) ? -EFAULT : 0;	}	return -EINVAL;}static struct fbgen_hwswitch au1200_switch = {	au1200_detect, 	au1200_encode_fix, 	au1200_decode_var, 	au1200_encode_var, 	au1200_get_par, 	au1200_set_par, 	au1200_getcolreg, 	au1200_setcolreg, 	au1200_pan_display, 	au1200_blank, 	au1200_set_disp};static void au1200_setpanel (struct panel_settings *newpanel){	/*	 * Perform global setup/init of LCD controller	 */	uint32 winenable;	/* Make sure all windows disabled */	winenable = lcd->winenable;	lcd->winenable = 0;	/*	 * Ensure everything is disabled before reconfiguring	 */	if (lcd->screen & LCD_SCREEN_SEN)	{		/* Wait for vertical sync period */		lcd->intstatus = LCD_INT_SS;		while ((lcd->intstatus & LCD_INT_SS) == 0)			;						lcd->screen &= ~LCD_SCREEN_SEN;	//disable the controller				do		{			lcd->intstatus = lcd->intstatus; //clear interrupts		}		while ((lcd->intstatus & LCD_INT_SD) == 0);	//wait for controller to shut down				/* Call shutdown of current panel (if up) */		/* this must occur last, because if an external clock is driving the controller, the clock cannot be turned off before first shutting down the controller. */		if (panel->device_shutdown != NULL) panel->device_shutdown();	}	panel = newpanel;		printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres);	/*	 * Setup clocking if internal LCD clock source (assumes sys_auxpll valid)	 *///	if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT))	{		uint32 sys_clksrc;		au_writel(panel->mode_auxpll, SYS_AUXPLL);		sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f; 		sys_clksrc |= panel->mode_toyclksrc;		au_writel(sys_clksrc, SYS_CLKSRC);	}	/*	 * Configure panel timings	 */	lcd->screen = panel->mode_screen;	lcd->horztiming = panel->mode_horztiming;	lcd->verttiming = panel->mode_verttiming;	lcd->clkcontrol = panel->mode_clkcontrol;	lcd->pwmdiv = panel->mode_pwmdiv;	lcd->pwmhi = panel->mode_pwmhi;	lcd->outmask = panel->mode_outmask;	lcd->fifoctrl = panel->mode_fifoctrl;	au_sync();	/* FIX!!! Check window settings to make sure still valid for new geometry */	au1200_setlocation(0, win->w[0].xpos, win->w[0].ypos);	au1200_setlocation(1, win->w[1].xpos, win->w[1].ypos);	au1200_setlocation(2, win->w[2].xpos, win->w[2].ypos);	au1200_setlocation(3, win->w[3].xpos, win->w[3].ypos);	lcd->winenable = winenable;	/*	 * Re-enable screen now that it is configured	 */	lcd->screen |= LCD_SCREEN_SEN;	au_sync();	/* Call init of panel */	if (panel->device_init != NULL) panel->device_init();#if 0#define D(X) printk("%25s: %08X\n", #X, X)	D(lcd->screen);	D(lcd->horztiming);	D(lcd->verttiming);	D(lcd->clkcontrol);	D(lcd->pwmdiv);	D(lcd->pwmhi);	D(lcd->outmask);	D(lcd->fifoctrl);	D(lcd->window[0].winctrl0);	D(lcd->window[0].winctrl1);	D(lcd->window[0].winctrl2);	D(lcd->window[0].winbuf0);	D(lcd->window[0].winbuf1);	D(lcd->window[0].winbufctrl);	D(lcd->window[1].winctrl0);	D(lcd->window[1].winctrl1);	D(lcd->window[1].winctrl2);	D(lcd->window[1].winbuf0);	D(lcd->window[1].winbuf1);	D(lcd->window[1].winbufctrl);	D(lcd->window[2].winctrl0);	D(lcd->window[2].winctrl1);	D(lcd->window[2].winctrl2);	D(lcd->window[2].winbuf0);	D(lcd->window[2].winbuf1);	D(lcd->window[2].winbufctrl);	D(lcd->window[3].winctrl0);	D(lcd->window[3].winctrl1);	D(lcd->window[3].winctrl2);	D(lcd->window[3].winbuf0);	D(lcd->window[3].winbuf1);	D(lcd->window[3].winbufctrl);	D(lcd->winenable);	D(lcd->intenable);	D(lcd->intstatus);	D(lcd->backcolor);	D(lcd->winenable);	D(lcd->colorkey);    D(lcd->colorkeymsk);	D(lcd->hwc.cursorctrl);	D(lcd->hwc.cursorpos);	D(lcd->hwc.cursorcolor0);	D(lcd->hwc.cursorcolor1);	D(lcd->hwc.cursorcolor2);	D(lcd->hwc.cursorcolor3);#endif}static int au1200_setsize (int plane, int xres, int yres){	uint32 winctrl0, winctrl1, winenable;	int xsz, ysz;	// FIX!!! x*Y can not surpass allocated memoryprintk("setsize: x %d y %d\n", xres, yres);	winctrl1 = lcd->window[plane].winctrl1;printk("org winctrl1 %08X\n", winctrl1);	winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY);	xres -= 1;	yres -= 1;	winctrl1 |= (xres << 11);	winctrl1 |= (yres << 0);printk("new winctrl1 %08X\n", winctrl1);//	winenable = lcd->winenable & (1 << plane);//	lcd->winenable &= ~(1 << plane);	lcd->window[plane].winctrl1 = winctrl1;//	lcd->winenable |= winenable;}static int au1200_setlocation (int plane, int xpos, int ypos){	uint32 winctrl0, winctrl1, winenable, fb_offset = 0;	int xsz, ysz;	/* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */	winctrl0 = lcd->window[plane].winctrl0;	winctrl1 = lcd->window[plane].winctrl1;	winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN);	winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY);	/* Check for off-screen adjustments */	xsz = win->w[plane].xres;	ysz = win->w[plane].yres;	if ((xpos + win->w[plane].xres) > panel->Xres)	{		/* Off-screen to the right */		xsz = panel->Xres - xpos; /* off by 1 ??? */		printk("off screen right\n");	}	if ((ypos + win->w[plane].yres) > panel->Yres)	{		/* Off-screen to the bottom */		ysz = panel->Yres - ypos; /* off by 1 ??? */		printk("off screen bottom\n");	}	if (xpos < 0)	{		/* Off-screen to the left */		xsz = win->w[plane].xres + xpos;		fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8);		xpos = 0;		printk("off screen left\n");	}	if (ypos < 0)	{		/* Off-screen to the top */		ysz = win->w[plane].yres + ypos;		fb_offset += ((0 - ypos) *	fb_pars[plane].line_length);		ypos = 0;		printk("off screen top\n");	}	/* record settings */	win->w[plane].xpos = xpos;	win->w[plane].ypos = ypos;	xsz -= 1;	ysz -= 1;	winctrl0 |= (xpos << 21);	winctrl0 |= (ypos << 10);	winctrl1 |= (xsz << 11);	winctrl1 |= (ysz << 0);	/* Disable the window while making changes, then restore WINEN */	winenable = lcd->winenable & (1 << plane);	lcd->winenable &= ~(1 << plane);	lcd->window[plane].winctrl0 = winctrl0;	lcd->window[plane].winctrl1 = winctrl1;	lcd->window[plane].winbuf0 =	lcd->window[plane].winbuf1 = fb_infos[plane].fb_phys + fb_offset;	lcd->window[plane].winbufctrl = 0; /* select winbuf0 */	lcd->winenable |= winenable;	return 0;}static void au1200_setmode(int plane){	/* Window/plane setup */	lcd->window[plane].winctrl1 = ( 0		| LCD_WINCTRL1_PRI_N(plane)		| win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */		) ;	au1200_setlocation(plane, win->w[plane].xpos, win->w[plane].ypos);	lcd->window[plane].winctrl2 = ( 0		| LCD_WINCTRL2_CKMODE_00		| LCD_WINCTRL2_DBM/*			| LCD_WINCTRL2_RAM */		| LCD_WINCTRL2_BX_N(fb_pars[plane].line_length)		| LCD_WINCTRL2_SCX_1		| LCD_WINCTRL2_SCY_1		) ;	lcd->winenable |= win->w[plane].mode_winenable;	au_sync();}static unsigned longau1200fb_alloc_fbmem (unsigned long size){	/* __get_free_pages() fulfills a max request of 2MB */	/* do multiple requests to obtain large contigous mem */#define MAX_GFP 0x00200000	unsigned long mem, amem, alloced = 0, allocsize;	size += 0x1000;	allocsize = (size < MAX_GFP) ? size : MAX_GFP;	/* Get first chunk */	mem = (unsigned long )		__get_free_pages(GFP_ATOMIC | GFP_DMA, get_order(allocsize));	if (mem != 0) alloced = allocsize;	/* Get remaining, contiguous chunks */	while (alloced < size)	{		amem = (unsigned long )			__get_free_pages(GFP_ATOMIC | GFP_DMA, get_order(allocsize));		if (amem != 0)			alloced += allocsize;		/* check for contiguous mem alloced */		if ((amem == 0) || (amem + allocsize) != mem)			break;		else			mem = amem;	}	return mem;}int __init au1200fb_init(void){	struct au1200fb_info *fb_info;	struct display *disp;	struct au1200fb_par *par;	unsigned long page;	int plane, bpp;    /*	* Get the panel information/display mode	*/	panel = &panels[panel_index];	win = &windows[window_index];	printk("au1200fb: Panel %d %s\n", panel_index, panel->name);	printk("au1200fb: Win %d %s\n", window_index, win->name);	/* Global setup/init */	au1200_setpanel(panel);	lcd->intenable = 0;	lcd->intstatus = ~0;	lcd->backcolor = win->mode_backcolor;	lcd->winenable = 0;	/* Setup Color Key - FIX!!! */	lcd->colorkey = win->mode_colorkey;	lcd->colorkeymsk = win->mode_colorkeymsk;	/* Setup HWCursor - FIX!!! Need to support this eventually */	lcd->hwc.cursorctrl = 0;	lcd->hwc.cursorpos = 0;	lcd->hwc.cursorcolor0 = 0;	lcd->hwc.cursorcolor1 = 0;	lcd->hwc.cursorcolor2 = 0;	lcd->hwc.cursorcolor3 = 0;	/* Register each plane as a frame buffer device */	for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane)	{		fb_info = &fb_infos[plane];		disp = &disps[plane];		par = &fb_pars[plane];		bpp = winbpp(win->w[plane].mode_winctrl1);		if (win->w[plane].xres == 0)			win->w[plane].xres = panel->Xres;		if (win->w[plane].yres == 0)			win->w[plane].yres = panel->Yres;		par->var.xres =		par->var.xres_virtual = win->w[plane].xres;		par->var.yres =		par->var.yres_virtual = win->w[plane].yres;		par->var.bits_per_pixel = bpp;		par->line_length = win->w[plane].xres * bpp / 8; /* in bytes */		/*		 * Allocate LCD framebuffer from system memory		 * Set page reserved so that mmap will work. This is necessary		 * since we'll be remapping normal memory.		 */		fb_info->fb_size = (win->w[plane].xres * win->w[plane].yres * bpp) / 8;		fb_info->fb_virt_start = au1200fb_alloc_fbmem(fb_info->fb_size);		if (!fb_info->fb_virt_start) {			printk("Unable to allocate fb memory\n");			return -ENOMEM;		}		fb_info->fb_phys = virt_to_bus((void *)fb_info->fb_virt_start);		for (page = fb_info->fb_virt_start;		     page < PAGE_ALIGN(fb_info->fb_virt_start + fb_info->fb_size); 		     page += PAGE_SIZE) {			SetPageReserved(virt_to_page(page));		}		/* Convert to kseg1 */		fb_info->fb_virt_start =			(void *)((u32)fb_info->fb_virt_start | 0xA0000000);		// FIX!!! may wish to avoid this to save startup time???		memset((void *)fb_info->fb_virt_start, 0, fb_info->fb_size);		fb_info->gen.parsize = sizeof(struct au1200fb_par);		fb_info->gen.fbhw = &au1200_switch;		strcpy(fb_info->gen.info.modename, "Au1200 LCD");		fb_info->gen.info.changevar = NULL;		fb_info->gen.info.node = -1;		fb_info->gen.info.fbops = &au1200fb_ops;		fb_info->gen.info.disp = disp;		fb_info->gen.info.switch_con = &fbgen_switch;		fb_info->gen.info.updatevar = &fbgen_update_var;		fb_info->gen.info.blank = &fbgen_blank;		fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT;		fb_info->nohwcursor = 1;		fb_info->noblanking = 1;		/* This should give a reasonable default video mode */		fbgen_get_var(&disp->var, -1, &fb_info->gen.info);		fbgen_do_set_var(&disp->var, 1, &fb_info->gen);		fbgen_set_disp(-1, &fb_info->gen);		fbgen_install_cmap(0, &fb_info->gen);		/* Turn on plane */		au1200_setmode(plane);		if (register_framebuffer(&fb_info->gen.info) < 0)			return -EINVAL;		printk(KERN_INFO "fb%d: %s plane %d @ %08X (%d x %d x %d)\n", 				GET_FB_IDX(fb_info->gen.info.node), 				fb_info->gen.info.modename, plane, fb_info->fb_phys,				win->w[plane].xres, win->w[plane].yres, bpp);	}	/* uncomment this if your driver cannot be unloaded */	/* MOD_INC_USE_COUNT; */	return 0;}void au1200fb_setup(char *options, int *ints){	char* this_opt;	int i;	int num_panels = sizeof(panels)/sizeof(struct panel_settings);	if (!options || !*options)		return;	for(this_opt=strtok(options, ","); this_opt;	    this_opt=strtok(NULL, ",")) {		if (!strncmp(this_opt, "panel:", 6)) {#if defined(CONFIG_MIPS_PB1200) || defined(CONFIG_MIPS_DB1200)			/* Read Pb1200 Rotary Switch S11 to obtain default panel */#ifdef CONFIG_MIPS_PB1200			if (!strncmp(this_opt+6, "s11", 3))#endif#ifdef CONFIG_MIPS_DB1200			if (!strncmp(this_opt+6, "s7", 3))#endif			{				BCSR *bcsr = (BCSR *)BCSR_KSEG1_ADDR;				int p;				p = bcsr->switches;				p >>= 8;				p &= 0x0F;				if (p >= num_panels) p = 0;				panel_index = p;			}			else#elif defined(CONFIG_MIPS_FICMMP)	au1xxx_gpio_tristate(6);		if(au1xxx_gpio_read(12) == 0)		panel_index = 8;	else		panel_index = 7;#endif			/* Get the panel name, everything else if fixed */			for (i=0; i<num_panels; i++) {				if (!strncmp(this_opt+6, panels[i].name, 							strlen(this_opt))) {					panel_index = i;					break;				}			}		}		else if (!strncmp(this_opt, "nohwcursor", 10)) {			printk("nohwcursor\n");			fb_infos[0].nohwcursor = 1;		}	}		panel_index = 3; // Tengfei@ Debug	printk("au1200fb: Panel %d %s\n", panel_index,		panels[panel_index].name);}#ifdef MODULEMODULE_LICENSE("GPL");MODULE_DESCRIPTION("Au1200 LCD framebuffer driver");void au1200fb_cleanup(struct fb_info *info){	unregister_framebuffer(info);}module_init(au1200fb_init);module_exit(au1200fb_cleanup);#endif /* MODULE */

⌨️ 快捷键说明

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