au1200fb.c

来自「Linux环境下视频显示卡设备的驱动程序源代码」· C语言 代码 · 共 1,922 行 · 第 1/4 页

C
1,922
字号
		| LCD_WINCTRL2_DBM		| LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length)		| LCD_WINCTRL2_SCX_1		| LCD_WINCTRL2_SCY_1		) ;	lcd->winenable |= win->w[plane].mode_winenable;	au_sync();}/* Inline helpers *//*#define panel_is_dual(panel)  ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*//*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/#define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN)/* Bitfields format supported by the controller. */static struct fb_bitfield rgb_bitfields[][4] = {  	/*     Red, 	   Green, 	 Blue, 	     Transp   */	[LCD_WINCTRL1_FRM_16BPP655 >> 25] =		{ { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },	[LCD_WINCTRL1_FRM_16BPP565 >> 25] =		{ { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },	[LCD_WINCTRL1_FRM_16BPP556 >> 25] =		{ { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } },	[LCD_WINCTRL1_FRM_16BPPI1555 >> 25] =		{ { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } },	[LCD_WINCTRL1_FRM_16BPPI5551 >> 25] =		{ { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } },	[LCD_WINCTRL1_FRM_16BPPA1555 >> 25] =		{ { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } },	[LCD_WINCTRL1_FRM_16BPPA5551 >> 25] =		{ { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } },	[LCD_WINCTRL1_FRM_24BPP >> 25] =		{ { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } },	[LCD_WINCTRL1_FRM_32BPP >> 25] =		{ { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } },};/*-------------------------------------------------------------------------*//* Helpers */static void au1200fb_update_fbinfo(struct fb_info *fbi){	/* FIX!!!! This also needs to take the window pixel format into account!!! */	/* Update var-dependent FB info */	if (panel_is_color(panel)) {		if (fbi->var.bits_per_pixel <= 8) {			/* palettized */			fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR;			fbi->fix.line_length = fbi->var.xres_virtual /				(8/fbi->var.bits_per_pixel);		} else {			/* non-palettized */			fbi->fix.visual = FB_VISUAL_TRUECOLOR;			fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8);		}	} else {		/* mono FIX!!! mono 8 and 4 bits */		fbi->fix.visual = FB_VISUAL_MONO10;		fbi->fix.line_length = fbi->var.xres_virtual / 8;	}	fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual;	print_dbg("line length: %d\n", fbi->fix.line_length);	print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel);}/*-------------------------------------------------------------------------*//* AU1200 framebuffer driver *//* fb_check_var * Validate var settings with hardware restrictions and modify it if necessary */static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,	struct fb_info *fbi){	struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;	u32 pixclock;	int screen_size, plane;	plane = fbdev->plane;	/* Make sure that the mode respect all LCD controller and	 * panel restrictions. */	var->xres = win->w[plane].xres;	var->yres = win->w[plane].yres;	/* No need for virtual resolution support */	var->xres_virtual = var->xres;	var->yres_virtual = var->yres;	var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1);	screen_size = var->xres_virtual * var->yres_virtual;	if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8);	else screen_size /= (8/var->bits_per_pixel);	if (fbdev->fb_len < screen_size)		return -EINVAL; /* Virtual screen is to big, abort */	/* FIX!!!! what are the implicaitons of ignoring this for windows ??? */	/* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel	 * clock can only be obtain by dividing this value by an even integer.	 * Fallback to a slower pixel clock if necessary. */	pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin);	pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2));	if (AU1200_LCD_MAX_CLK % pixclock) {		int diff = AU1200_LCD_MAX_CLK % pixclock;		pixclock -= diff;	}	var->pixclock = KHZ2PICOS(pixclock/1000);#if 0	if (!panel_is_active(panel)) {		int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1;		if (!panel_is_color(panel)			&& (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) {			/* STN 8bit mono panel support is up to 6MHz pixclock */			var->pixclock = KHZ2PICOS(6000);		} else if (!pcd) {			/* Other STN panel support is up to 12MHz  */			var->pixclock = KHZ2PICOS(12000);		}	}#endif	/* Set bitfield accordingly */	switch (var->bits_per_pixel) {		case 16:		{			/* 16bpp True color.			 * These must be set to MATCH WINCTRL[FORM] */			int idx;			idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;			var->red    = rgb_bitfields[idx][0];			var->green  = rgb_bitfields[idx][1];			var->blue   = rgb_bitfields[idx][2];			var->transp = rgb_bitfields[idx][3];			break;		}		case 32:		{			/* 32bpp True color.			 * These must be set to MATCH WINCTRL[FORM] */			int idx;			idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25;			var->red    = rgb_bitfields[idx][0];			var->green  = rgb_bitfields[idx][1];			var->blue   = rgb_bitfields[idx][2];			var->transp = rgb_bitfields[idx][3];			break;		}		default:			print_dbg("Unsupported depth %dbpp", var->bits_per_pixel);			return -EINVAL;	}	return 0;}/* fb_set_par * Set hardware with var settings. This will enable the controller with a * specific mode, normally validated with the fb_check_var method */static int au1200fb_fb_set_par(struct fb_info *fbi){	struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi;	au1200fb_update_fbinfo(fbi);	au1200_setmode(fbdev);	return 0;}/* fb_setcolreg * Set color in LCD palette. */static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green,	unsigned blue, unsigned transp, struct fb_info *fbi){	volatile u32 *palette = lcd->palette;	u32 value;	if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1))		return -EINVAL;	if (fbi->var.grayscale) {		/* Convert color to grayscale */		red = green = blue =			(19595 * red + 38470 * green + 7471 * blue) >> 16;	}	if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) {		/* Place color in the pseudopalette */		if (regno > 16)			return -EINVAL;		palette = (u32*) fbi->pseudo_palette;		red   >>= (16 - fbi->var.red.length);		green >>= (16 - fbi->var.green.length);		blue  >>= (16 - fbi->var.blue.length);		value = (red   << fbi->var.red.offset) 	|			(green << fbi->var.green.offset)|			(blue  << fbi->var.blue.offset);		value &= 0xFFFF;	} else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) {		/* COLOR TFT PALLETTIZED (use RGB 565) */		value = (red & 0xF800)|((green >> 5) &				0x07E0)|((blue >> 11) & 0x001F);		value &= 0xFFFF;	} else if (0 /*panel_is_color(fbdev->panel)*/) {		/* COLOR STN MODE */		value = 0x1234;		value &= 0xFFF;	} else {		/* MONOCHROME MODE */		value = (green >> 12) & 0x000F;		value &= 0xF;	}	palette[regno] = value;	return 0;}/* fb_blank * Blank the screen. Depending on the mode, the screen will be * activated with the backlight color, or desactivated */static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi){	/* Short-circuit screen blanking */	if (noblanking)		return 0;	switch (blank_mode) {	case FB_BLANK_UNBLANK:	case FB_BLANK_NORMAL:		/* printk("turn on panel\n"); */		au1200_setpanel(panel);		break;	case FB_BLANK_VSYNC_SUSPEND:	case FB_BLANK_HSYNC_SUSPEND:	case FB_BLANK_POWERDOWN:		/* printk("turn off panel\n"); */		au1200_setpanel(NULL);		break;	default:		break;	}	/* FB_BLANK_NORMAL is a soft blank */	return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 0;}/* fb_mmap * Map video memory in user space. We don't use the generic fb_mmap * method mainly to allow the use of the TLB streaming flag (CCA=6) */static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma){	unsigned int len;	unsigned long start=0, off;	struct au1200fb_device *fbdev = (struct au1200fb_device *) info;#ifdef CONFIG_PM	au1xxx_pm_access(LCD_pm_dev);#endif	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {		return -EINVAL;	}	start = fbdev->fb_phys & PAGE_MASK;	len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len);	off = vma->vm_pgoff << PAGE_SHIFT;	if ((vma->vm_end - vma->vm_start + off) > len) {		return -EINVAL;	}	off += start;	vma->vm_pgoff = off >> PAGE_SHIFT;	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);	pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */	vma->vm_flags |= VM_IO;	return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,				  vma->vm_end - vma->vm_start,				  vma->vm_page_prot);	return 0;}static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata){	unsigned int hi1, divider;	/* SCREEN_SIZE: user cannot reset size, must switch panel choice */	if (pdata->flags & SCREEN_BACKCOLOR)		lcd->backcolor = pdata->backcolor;	if (pdata->flags & SCREEN_BRIGHTNESS) {		// limit brightness pwm duty to >= 30/1600		if (pdata->brightness < 30) {			pdata->brightness = 30;		}		divider = (lcd->pwmdiv & 0x3FFFF) + 1;		hi1 = (lcd->pwmhi >> 16) + 1;		hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8);		lcd->pwmhi &= 0xFFFF;		lcd->pwmhi |= (hi1 << 16);	}	if (pdata->flags & SCREEN_COLORKEY)		lcd->colorkey = pdata->colorkey;	if (pdata->flags & SCREEN_MASK)		lcd->colorkeymsk = pdata->mask;	au_sync();}static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata){	unsigned int hi1, divider;	pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1;	pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1;	pdata->backcolor = lcd->backcolor;	pdata->colorkey = lcd->colorkey;	pdata->mask = lcd->colorkeymsk;	// brightness	hi1 = (lcd->pwmhi >> 16) + 1;	divider = (lcd->pwmdiv & 0x3FFFF) + 1;	pdata->brightness = ((hi1 << 8) / divider) - 1;	au_sync();}static void set_window(unsigned int plane,	struct au1200_lcd_window_regs_t *pdata){	unsigned int val, bpp;	/* Window control register 0 */	if (pdata->flags & WIN_POSITION) {		val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX |				LCD_WINCTRL0_OY);		val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX);		val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY);		lcd->window[plane].winctrl0 = val;	}	if (pdata->flags & WIN_ALPHA_COLOR) {		val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A);		val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A);		lcd->window[plane].winctrl0 = val;	}	if (pdata->flags & WIN_ALPHA_MODE) {		val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN);		val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN);		lcd->window[plane].winctrl0 = val;	}	/* Window control register 1 */	if (pdata->flags & WIN_PRIORITY) {		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI);		val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI);		lcd->window[plane].winctrl1 = val;	}	if (pdata->flags & WIN_CHANNEL) {		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE);		val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE);		lcd->window[plane].winctrl1 = val;	}	if (pdata->flags & WIN_BUFFER_FORMAT) {		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM);		val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM);		lcd->window[plane].winctrl1 = val;	}	if (pdata->flags & WIN_COLOR_ORDER) {		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO);		val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO);		lcd->window[plane].winctrl1 = val;	}	if (pdata->flags & WIN_PIXEL_ORDER) {		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO);		val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO);		lcd->window[plane].winctrl1 = val;	}	if (pdata->flags & WIN_SIZE) {		val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX |				LCD_WINCTRL1_SZY);		val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX);		val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY);		lcd->window[plane].winctrl1 = val;		/* program buffer line width */		bpp = winbpp(val) / 8;		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX);		val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX);		lcd->window[plane].winctrl2 = val;	}	/* Window control register 2 */	if (pdata->flags & WIN_COLORKEY_MODE) {		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE);		val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE);		lcd->window[plane].winctrl2 = val;	}	if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) {		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM);		val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM);		lcd->window[plane].winctrl2 = val;	}	if (pdata->flags & WIN_RAM_ARRAY_MODE) {		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM);		val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM);		lcd->window[plane].winctrl2 = val;	}	/* Buffer line width programmed with WIN_SIZE */	if (pdata->flags & WIN_BUFFER_SCALE) {		val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX |				LCD_WINCTRL2_SCY);		val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX);		val |= ((pdata->ysize) & LCD_WINCTRL2_SCY);		lcd->window[plane].winctrl2 = val;	}	if (pdata->flags & WIN_ENABLE) {		val = lcd->winenable;		val &= ~(1<<plane);		val |= (pdata->enable & 1) << plane;		lcd->winenable = val;	}	au_sync();}static void get_window(unsigned int plane,	struct au1200_lcd_window_regs_t *pdata){	/* Window control register 0 */	pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21;	pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10;	pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2;	pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1;	/* Window control register 1 */	pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30;	pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29;	pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25;	pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24;

⌨️ 快捷键说明

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