omapfb_main.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,875 行 · 第 1/4 页

C
1,875
字号
}/* Normal image blit */static void omapfb_imageblit(struct fb_info *fbi, const struct fb_image *image){	do_imageblit(fbi, image, 0);}/* Transparent image blit, using image->bg_color as the color key */static void omapfb_transparent_blit(struct fb_info *fbi,				    const struct fb_image *image){	do_imageblit(fbi, image, COPY_MODE_TRANSPARENT);}/* Set fb_info.fix fields and also updates fbdev. * When calling this fb_info.var must be set up already. */static void set_fb_fix(struct omapfb_device *fbdev){	struct fb_info		 *fbi = fbdev->fb_info;	struct fb_fix_screeninfo *fix = &fbi->fix;	struct fb_var_screeninfo *var = &fbi->var;	struct fb_ops		 *fbops = fbi->fbops;	int frame_size;	strncpy(fix->id, OMAPFB_DRIVER, sizeof(fix->id));	fix->type		= FB_TYPE_PACKED_PIXELS;	switch (var->bits_per_pixel) {	case 16:		fix->visual = FB_VISUAL_TRUECOLOR;		break;	case 1:	case 2:	case 4:	case 8:		fix->visual = FB_VISUAL_PSEUDOCOLOR;		break;	}	fix->accel		= FB_ACCEL_OMAP1610;	fix->line_length	= var->xres_virtual * var->bits_per_pixel / 8;	fix->smem_len		= fbdev->lcddma_mem_size - fbdev->frame0_org;	fix->smem_start 	= fbdev->lcddma_handle + fbdev->frame0_org;	if (var->accel_flags == FB_ACCELF_TEXT && var->bits_per_pixel >= 8) {		fbops->fb_fillrect = omapfb_fillrect;		fbops->fb_copyarea = omapfb_copyarea;		fbops->fb_imageblit = omapfb_imageblit;	} else {		fbops->fb_fillrect = cfb_fillrect;		fbops->fb_copyarea = cfb_copyarea;		fbops->fb_imageblit = cfb_imageblit;	}	/* Set the second frame buffer offset for flipping if there is	 * room for it. */	frame_size = fix->line_length * var->yres +		     var->xres * var->bits_per_pixel / 8;	fbdev->frame1_org = fbdev->frame0_org + frame_size;	if (fbdev->frame1_org > fbdev->lcddma_mem_size)		fbdev->frame1_org = 0;	fbdev->vis_frame_org = fbdev->src_frame_org = fbdev->dst_frame_org =		fbdev->frame0_org;	fbdev->view_org = var->yoffset * fix->line_length +			  var->xoffset * var->bits_per_pixel / 8;}/* Check the values in var against our capabilities and in case of out of * bound values try to adjust them. */static int set_fb_var(struct omapfb_device *fbdev,		      struct fb_var_screeninfo *var){	int		bpp;	unsigned long	max_frame_size;	unsigned long	line_size;	bpp = var->bits_per_pixel = fbdev->panel->video_mode->bpp;	if (bpp != 16)		/* Not yet supported */		return -1;	switch (var->rotate) {	case 0:	case 180:		var->xres = fbdev->panel->video_mode->x_res;		var->yres = fbdev->panel->video_mode->y_res;		break;	case 90:	case 270:		var->xres = fbdev->panel->video_mode->y_res;		var->yres = fbdev->panel->video_mode->x_res;		break;	default:		return -1;	}	if (var->xres_virtual < var->xres)		var->xres_virtual = var->xres;	if (var->yres_virtual < var->yres)		var->yres_virtual = var->yres;	max_frame_size = fbdev->lcddma_mem_size - fbdev->frame0_org;	line_size = var->xres_virtual * bpp / 8;	if (line_size * var->yres_virtual > max_frame_size) {		/* Try to keep yres_virtual first */		line_size = max_frame_size / var->yres_virtual;		var->xres_virtual = line_size * 8 / bpp;		if (var->xres_virtual < var->xres) {			/* Still doesn't fit. Shrink yres_virtual too */			var->xres_virtual = var->xres;			line_size = var->xres * bpp / 8;			var->yres_virtual = max_frame_size / line_size;		}	}	if (var->xres + var->xoffset > var->xres_virtual)		var->xoffset = var->xres_virtual - var->xres;	if (var->yres + var->yoffset > var->yres_virtual)		var->yoffset = var->yres_virtual - var->yres;	line_size = var->xres * bpp / 8;	var->red.offset	 = 11; var->red.length	 = 5; var->red.msb_right   = 0;	var->green.offset= 5;  var->green.length = 6; var->green.msb_right = 0;	var->blue.offset = 0;  var->blue.length  = 5; var->blue.msb_right  = 0;	var->height		= -1;	var->width		= -1;	var->grayscale		= 0;	var->nonstd		= 0;	/* TODO: video timing params, sync */	var->pixclock		= -1;	var->left_margin	= -1;	var->right_margin	= -1;	var->upper_margin	= -1;	var->lower_margin	= -1;	var->hsync_len		= -1;	var->vsync_len		= -1;	var->vmode		= FB_VMODE_NONINTERLACED;	var->sync		= 0;	return 0;}static struct fb_var_screeninfo new_var;/* Set rotation (0, 90, 180, 270 degree), and switch to the new mode. */static void omapfb_rotate(struct fb_info *fbi, int rotate){	struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;	DBGENTER(1);	if (cpu_is_omap1510() && rotate != fbdev->fb_info->var.rotate) {		memcpy(&new_var, &fbi->var, sizeof(new_var));		new_var.rotate = rotate;		if (set_fb_var(fbdev, &new_var) == 0 &&		    memcmp(&new_var, &fbi->var, sizeof(new_var))) {			memcpy(&fbi->var, &new_var, sizeof(new_var));			set_fb_fix(fbdev);			ctrl_change_mode(fbdev);		}	}	DBGLEAVE(1);}/* Set new x,y offsets in the virtual display for the visible area and switch * to the new mode. */static int omapfb_pan_display(struct fb_var_screeninfo *var,			       struct fb_info *fbi){	struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;	int r = 0;	DBGENTER(1);	if (var->xoffset != fbi->var.xoffset ||	    var->yoffset != fbi->var.yoffset) {		memcpy(&new_var, &fbi->var, sizeof(new_var));		new_var.xoffset = var->xoffset;		new_var.yoffset = var->yoffset;		if (set_fb_var(fbdev, &new_var))			r = -EINVAL;		else {			memcpy(&fbi->var, &new_var, sizeof(new_var));			set_fb_fix(fbdev);			ctrl_change_mode(fbdev);		}	}	DBGLEAVE(1);	return r;}/* Set mirror to vertical axis and switch to the new mode. */static int omapfb_mirror(struct fb_info *fbi, int mirror){	struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;	int r = 0;	DBGENTER(1);	mirror = mirror ? 1 : 0;	if (cpu_is_omap1510())		r = -EINVAL;	else if (mirror != fbdev->mirror) {		fbdev->mirror = mirror;		ctrl_change_mode(fbdev);	}	DBGLEAVE(1);	return r;}/* Set x,y scale and switch to the new mode */static int omapfb_scale(struct fb_info *fbi,		      unsigned int xscale, unsigned int yscale){	struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;	int r = 0;	DBGENTER(1);	if (cpu_is_omap1510())		r = -EINVAL;	else if (xscale != fbdev->xscale || yscale != fbdev->yscale) {		if (fbi->var.xres * xscale > fbi->var.xres_virtual ||		    fbi->var.yres * yscale > fbi->var.yres_virtual)			r = -EINVAL;		else {			fbdev->xscale = xscale;			fbdev->yscale = yscale;			ctrl_change_mode(fbdev);		}	}	DBGLEAVE(1);	return r;}/* Check values in var, try to adjust them in case of out of bound values if * possible, or return error. */static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi){	struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;	int r;	DBGENTER(1);	r = set_fb_var(fbdev, var);	DBGLEAVE(1);	return r;}/* Switch to a new mode. The parameters for it has been check already by * omapfb_check_var. */static int omapfb_set_par(struct fb_info *fbi){	struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;	DBGENTER(1);	set_fb_fix(fbdev);	ctrl_change_mode(fbdev);	DBGLEAVE(1);	return 0;}/* Frame flipping support. Assign the primary or the secondary frame to the * visible frame, as well as the source and destination frames for graphics * operations like rectangle fill and area copy. Flipping is only possible * if we have enough video memory for the secondary frame. */static int omapfb_select_frame(struct fb_info *fbi, unsigned int vis_idx,			       unsigned int src_idx, unsigned int dst_idx){	struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;	if ((vis_idx | src_idx | dst_idx) & ~1)		return -EINVAL;	if (((vis_idx | src_idx | dst_idx) & 1) && !fbdev->frame1_org)		return -EINVAL;	fbdev->vis_frame_org = vis_idx ? fbdev->frame1_org : fbdev->frame0_org;	fbdev->src_frame_org = src_idx ? fbdev->frame1_org : fbdev->frame0_org;	fbdev->dst_frame_org = dst_idx ? fbdev->frame1_org : fbdev->frame0_org;	ctrl_change_mode(fbdev);	return 0;}/* Get the address of the primary and secondary frames */static int omapfb_get_frame_offset(struct fb_info *fbi,				   struct fb_frame_offset *fb_offset){	struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;	if (fb_offset->idx > 1)		return -EINVAL;	if (fb_offset->idx == 1 && !fbdev->frame1_org)		return -EINVAL;	fb_offset->offset = fb_offset->idx ? fbdev->frame1_org :		fbdev->frame0_org;	return 0;}static int omapfb_activate(struct omapfb_device *fbdev);/* If late_activate option is set, start the image transfer now. */static int omapfb_late_activate(struct fb_info *fbi){	struct omapfb_device *fbdev = (struct omapfb_device *)fbi->par;	if (!late_activate) {		PRNERR("late_activate option is not set");		return -EINVAL;	}	if (fbdev->state != OMAPFB_DEACTIVATED) {		PRNERR("device is already active or in wrong state");		return -EINVAL;	}	omapfb_activate(fbdev);	/* call this in case some has changed meanwhile the fb params */	ctrl_change_mode(fbdev);	return 0;}/* Ioctl interface. Part of the kernel mode frame buffer API is duplicated * here to be accessible by user mode code. In addition transparent copy * graphics transformations, frame flipping support is provided through this * interface. */static int omapfb_ioctl(struct inode *inode, struct file *file,			unsigned int cmd, unsigned long arg,			struct fb_info *fbi){	struct omapfb_device	*fbdev = (struct omapfb_device *)fbi->par;	struct fb_ops		*ops = fbi->fbops;	union {		struct fb_fillrect	rect;		struct fb_copyarea	area;		struct fb_image		image;		struct fb_scale		scale;		struct fb_frame_offset	frame_offset;		unsigned int		frame_idx;		unsigned int		mirror;	} p;	int			r = 0;	DBGENTER(2);	BUG_ON(!ops);	DBGPRINT(2, "cmd=%010x\n", cmd);	switch (cmd)	{	case OMAPFB_FILLRECT:		if (copy_from_user(&p.rect, (void *)arg, sizeof(p.rect)))			r = -EFAULT;		else			ops->fb_fillrect(fbi, &p.rect);		break;	case OMAPFB_COPYAREA:		if (copy_from_user(&p.area, (void *)arg, sizeof(p.area)))			r = -EFAULT;		else			ops->fb_copyarea(fbi, &p.area);		break;	case OMAPFB_IMAGEBLIT:		if (copy_from_user(&p.image, (void *)arg, sizeof(p.image)))			r = -EFAULT;		else			ops->fb_imageblit(fbi, &p.image);		break;	case OMAPFB_TRANSPARENT_BLIT:		if (copy_from_user(&p.image, (void *)arg, sizeof(p.image)))			r = -EFAULT;		else			omapfb_transparent_blit(fbi, &p.image);		break;	case OMAPFB_MIRROR:		if (get_user(p.mirror, (int *)arg))			r = -EFAULT;		else			omapfb_mirror(fbi, p.mirror);		break;	case OMAPFB_SCALE:		if (copy_from_user(&p.scale, (void *)arg, sizeof(p.scale)))			r = -EFAULT;		else			r = omapfb_scale(fbi, p.scale.xscale, p.scale.yscale);		break;	case OMAPFB_SELECT_VIS_FRAME:		if (get_user(p.frame_idx, (int *)arg))			r = -EFAULT;		else			r = omapfb_select_frame(fbi, p.frame_idx,						fbdev->src_frame_org,						fbdev->dst_frame_org);		break;	case OMAPFB_SELECT_SRC_FRAME:		if (get_user(p.frame_idx, (int *)arg))			r = - EFAULT;		else			r = omapfb_select_frame(fbi, fbdev->vis_frame_org,						p.frame_idx,						fbdev->dst_frame_org);		break;	case OMAPFB_SELECT_DST_FRAME:		if (get_user(p.frame_idx, (int *)arg))			r = -EFAULT;		else			r = omapfb_select_frame(fbi, fbdev->vis_frame_org,						fbdev->src_frame_org,						p.frame_idx);		break;	case OMAPFB_GET_FRAME_OFFSET:		if (copy_from_user(&p.frame_offset, (void *)arg,				   sizeof(p.frame_offset)))			r = -EFAULT;		else {			r = omapfb_get_frame_offset(fbi, &p.frame_offset);			if (copy_to_user((void *)arg, &p.frame_offset,					 sizeof(p.frame_offset)))				r = -EFAULT;		}		break;	case OMAPFB_SYNC_GFX:		gfxdma_sync(&fbdev->gfx);		break;	case OMAPFB_VSYNC:		break;	case OMAPFB_LATE_ACTIVATE:		r = omapfb_late_activate(fbi);		break;	default:		r = -EINVAL;	}	DBGLEAVE(2);	return r;}/* Callback table for the frame buffer framework. Some of these pointers * will be changed according to the current setting of fb_info->accel_flags. */static struct fb_ops omapfb_ops = {	.owner		= THIS_MODULE,	.fb_open        = omapfb_open,	.fb_release     = omapfb_release,	.fb_setcolreg	= omapfb_setcolreg,	.fb_fillrect	= cfb_fillrect,	.fb_copyarea	= cfb_copyarea,	.fb_imageblit	= cfb_imageblit,	.fb_cursor	= soft_cursor,	.fb_blank       = omapfb_blank,	.fb_ioctl	= omapfb_ioctl,	.fb_check_var	= omapfb_check_var,	.fb_set_par	= omapfb_set_par,	.fb_rotate	= omapfb_rotate,	.fb_pan_display = omapfb_pan_display,};/*

⌨️ 快捷键说明

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