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

📄 omapfb_main.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	bpp = var->bits_per_pixel;	if (plane->color_mode == OMAPFB_COLOR_RGB444)		bpp = 16;	switch (var->rotate) {	case 0:	case 180:		xres_min = OMAPFB_PLANE_XRES_MIN;		xres_max = panel->x_res;		yres_min = OMAPFB_PLANE_YRES_MIN;		yres_max = panel->y_res;		if (cpu_is_omap15xx()) {			var->xres = panel->x_res;			var->yres = panel->y_res;		}		break;	case 90:	case 270:		xres_min = OMAPFB_PLANE_YRES_MIN;		xres_max = panel->y_res;		yres_min = OMAPFB_PLANE_XRES_MIN;		yres_max = panel->x_res;		if (cpu_is_omap15xx()) {			var->xres = panel->y_res;			var->yres = panel->x_res;		}		break;	default:		return -EINVAL;	}	if (var->xres < xres_min)		var->xres = xres_min;	if (var->yres < yres_min)		var->yres = yres_min;	if (var->xres > xres_max)		var->xres = xres_max;	if (var->yres > yres_max)		var->yres = yres_max;	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->mem_desc.region[plane->idx].size;	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;		}		/* Recheck this, as the virtual size changed. */		if (var->xres_virtual < var->xres)			var->xres = var->xres_virtual;		if (var->yres_virtual < var->yres)			var->yres = var->yres_virtual;		if (var->xres < xres_min || var->yres < yres_min)			return -EINVAL;	}	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;	if (plane->color_mode == OMAPFB_COLOR_RGB444) {		var->red.offset	  = 8; var->red.length	 = 4;						var->red.msb_right   = 0;		var->green.offset = 4; var->green.length = 4;						var->green.msb_right = 0;		var->blue.offset  = 0; var->blue.length  = 4;						var->blue.msb_right  = 0;	} else {		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;	/* pixclock in ps, the rest in pixclock */	var->pixclock		= 10000000 / (panel->pixel_clock / 100);	var->left_margin	= panel->hfp;	var->right_margin	= panel->hbp;	var->upper_margin	= panel->vfp;	var->lower_margin	= panel->vbp;	var->hsync_len		= panel->hsw;	var->vsync_len		= panel->vsw;	/* TODO: get these from panel->config */	var->vmode		= FB_VMODE_NONINTERLACED;	var->sync		= 0;	return 0;}/* 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_plane_struct *plane = fbi->par;	struct omapfb_device *fbdev = plane->fbdev;	omapfb_rqueue_lock(fbdev);	if (cpu_is_omap15xx() && rotate != fbi->var.rotate) {		struct fb_var_screeninfo *new_var = &fbdev->new_var;		memcpy(new_var, &fbi->var, sizeof(*new_var));		new_var->rotate = rotate;		if (set_fb_var(fbi, new_var) == 0 &&		    memcmp(new_var, &fbi->var, sizeof(*new_var))) {			memcpy(&fbi->var, new_var, sizeof(*new_var));			ctrl_change_mode(fbi);		}	}	omapfb_rqueue_unlock(fbdev);}/* * 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_plane_struct *plane = fbi->par;	struct omapfb_device *fbdev = plane->fbdev;	int r = 0;	omapfb_rqueue_lock(fbdev);	if (var->xoffset != fbi->var.xoffset ||	    var->yoffset != fbi->var.yoffset) {		struct fb_var_screeninfo *new_var = &fbdev->new_var;		memcpy(new_var, &fbi->var, sizeof(*new_var));		new_var->xoffset = var->xoffset;		new_var->yoffset = var->yoffset;		if (set_fb_var(fbi, new_var))			r = -EINVAL;		else {			memcpy(&fbi->var, new_var, sizeof(*new_var));			ctrl_change_mode(fbi);		}	}	omapfb_rqueue_unlock(fbdev);	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_plane_struct *plane = fbi->par;	struct omapfb_device *fbdev = plane->fbdev;	int r = 0;	omapfb_rqueue_lock(fbdev);	mirror = mirror ? 1 : 0;	if (cpu_is_omap15xx())		r = -EINVAL;	else if (mirror != plane->info.mirror) {		plane->info.mirror = mirror;		r = ctrl_change_mode(fbi);	}	omapfb_rqueue_unlock(fbdev);	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_plane_struct *plane = fbi->par;	struct omapfb_device *fbdev = plane->fbdev;	int r;	omapfb_rqueue_lock(fbdev);	if (fbdev->ctrl->sync != NULL)		fbdev->ctrl->sync();	r = set_fb_var(fbi, var);	omapfb_rqueue_unlock(fbdev);	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_plane_struct *plane = fbi->par;	struct omapfb_device *fbdev = plane->fbdev;	int r = 0;	omapfb_rqueue_lock(fbdev);	set_fb_fix(fbi);	r = ctrl_change_mode(fbi);	omapfb_rqueue_unlock(fbdev);	return r;}int omapfb_update_window_async(struct fb_info *fbi,				struct omapfb_update_window *win,				void (*callback)(void *),				void *callback_data){	struct omapfb_plane_struct *plane = fbi->par;	struct omapfb_device *fbdev = plane->fbdev;	struct fb_var_screeninfo *var;	var = &fbi->var;	if (win->x >= var->xres || win->y >= var->yres ||	    win->out_x > var->xres || win->out_y >= var->yres)		return -EINVAL;	if (!fbdev->ctrl->update_window ||	    fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)		return -ENODEV;	if (win->x + win->width >= var->xres)		win->width = var->xres - win->x;	if (win->y + win->height >= var->yres)		win->height = var->yres - win->y;	/* The out sizes should be cropped to the LCD size */	if (win->out_x + win->out_width > fbdev->panel->x_res)		win->out_width = fbdev->panel->x_res - win->out_x;	if (win->out_y + win->out_height > fbdev->panel->y_res)		win->out_height = fbdev->panel->y_res - win->out_y;	if (!win->width || !win->height || !win->out_width || !win->out_height)		return 0;	return fbdev->ctrl->update_window(fbi, win, callback, callback_data);}EXPORT_SYMBOL(omapfb_update_window_async);static int omapfb_update_win(struct fb_info *fbi,				struct omapfb_update_window *win){	struct omapfb_plane_struct *plane = fbi->par;	int ret;	omapfb_rqueue_lock(plane->fbdev);	ret = omapfb_update_window_async(fbi, win, NULL, NULL);	omapfb_rqueue_unlock(plane->fbdev);	return ret;}static int omapfb_update_full_screen(struct fb_info *fbi){	struct omapfb_plane_struct *plane = fbi->par;	struct omapfb_device *fbdev = plane->fbdev;	struct omapfb_update_window win;	int r;	if (!fbdev->ctrl->update_window ||	    fbdev->ctrl->get_update_mode() != OMAPFB_MANUAL_UPDATE)		return -ENODEV;	win.x = 0;	win.y = 0;	win.width = fbi->var.xres;	win.height = fbi->var.yres;	win.out_x = 0;	win.out_y = 0;	win.out_width = fbi->var.xres;	win.out_height = fbi->var.yres;	win.format = 0;	omapfb_rqueue_lock(fbdev);	r = fbdev->ctrl->update_window(fbi, &win, NULL, NULL);	omapfb_rqueue_unlock(fbdev);	return r;}static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi){	struct omapfb_plane_struct *plane = fbi->par;	struct omapfb_device *fbdev = plane->fbdev;	struct lcd_panel *panel = fbdev->panel;	struct omapfb_plane_info old_info;	int r = 0;	if (pi->pos_x + pi->out_width > panel->x_res ||	    pi->pos_y + pi->out_height > panel->y_res)		return -EINVAL;	omapfb_rqueue_lock(fbdev);	if (pi->enabled && !fbdev->mem_desc.region[plane->idx].size) {		/*		 * This plane's memory was freed, can't enable it		 * until it's reallocated.		 */		r = -EINVAL;		goto out;	}	old_info = plane->info;	plane->info = *pi;	if (pi->enabled) {		r = ctrl_change_mode(fbi);		if (r < 0) {			plane->info = old_info;			goto out;		}	}	r = fbdev->ctrl->enable_plane(plane->idx, pi->enabled);	if (r < 0) {		plane->info = old_info;		goto out;	}out:	omapfb_rqueue_unlock(fbdev);	return r;}static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi){	struct omapfb_plane_struct *plane = fbi->par;	*pi = plane->info;	return 0;}static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi){	struct omapfb_plane_struct *plane = fbi->par;	struct omapfb_device *fbdev = plane->fbdev;	struct omapfb_mem_region *rg = &fbdev->mem_desc.region[plane->idx];	size_t size;	int r = 0;	if (fbdev->ctrl->setup_mem == NULL)		return -ENODEV;	if (mi->type > OMAPFB_MEMTYPE_MAX)		return -EINVAL;	size = PAGE_ALIGN(mi->size);	omapfb_rqueue_lock(fbdev);	if (plane->info.enabled) {		r = -EBUSY;		goto out;	}	if (rg->size != size || rg->type != mi->type) {		struct fb_var_screeninfo *new_var = &fbdev->new_var;		unsigned long old_size = rg->size;		u8	      old_type = rg->type;		unsigned long paddr;		rg->size = size;		rg->type = mi->type;		/*		 * size == 0 is a special case, for which we		 * don't check / adjust the screen parameters.		 * This isn't a problem since the plane can't		 * be reenabled unless its size is > 0.		 */		if (old_size != size && size) {			if (size) {				memcpy(new_var, &fbi->var, sizeof(*new_var));				r = set_fb_var(fbi, new_var);				if (r < 0)					goto out;			}		}		if (fbdev->ctrl->sync)			fbdev->ctrl->sync();		r = fbdev->ctrl->setup_mem(plane->idx, size, mi->type, &paddr);		if (r < 0) {			/* Revert changes. */			rg->size = old_size;			rg->type = old_type;			goto out;		}		rg->paddr = paddr;		if (old_size != size) {			if (size) {				memcpy(&fbi->var, new_var, sizeof(fbi->var));				set_fb_fix(fbi);			} else {				/*				 * Set these explicitly to indicate that the				 * plane memory is dealloce'd, the other				 * screen parameters in var / fix are invalid.				 */				fbi->fix.smem_start = 0;				fbi->fix.smem_len = 0;			}		}	}out:	omapfb_rqueue_unlock(fbdev);	return r;}static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi){	struct omapfb_plane_struct *plane = fbi->par;	struct omapfb_device *fbdev = plane->fbdev;	struct omapfb_mem_region *rg;	rg = &fbdev->mem_desc.region[plane->idx];	memset(mi, 0, sizeof(*mi));	mi->size = rg->size;	mi->type = rg->type;	return 0;}static int omapfb_set_color_key(struct omapfb_device *fbdev,				struct omapfb_color_key *ck){	int r;	if (!fbdev->ctrl->set_color_key)		return -ENODEV;	omapfb_rqueue_lock(fbdev);	r = fbdev->ctrl->set_color_key(ck);	omapfb_rqueue_unlock(fbdev);	return r;}static int omapfb_get_color_key(struct omapfb_device *fbdev,				struct omapfb_color_key *ck){	int r;	if (!fbdev->ctrl->get_color_key)		return -ENODEV;	omapfb_rqueue_lock(fbdev);	r = fbdev->ctrl->get_color_key(ck);	omapfb_rqueue_unlock(fbdev);	return r;}static struct blocking_notifier_head omapfb_client_list[OMAPFB_PLANE_NUM];static int notifier_inited;static void omapfb_init_notifier(void){	int i;	for (i = 0; i < OMAPFB_PLANE_NUM; i++)		BLOCKING_INIT_NOTIFIER_HEAD(&omapfb_client_list[i]);}int omapfb_register_client(struct omapfb_notifier_block *omapfb_nb,				omapfb_notifier_callback_t callback,				void *callback_data){	int r;	if ((unsigned)omapfb_nb->plane_idx > OMAPFB_PLANE_NUM)		return -EINVAL;	if (!notifier_inited) {		omapfb_init_notifier();		notifier_inited = 1;	}	omapfb_nb->nb.notifier_call = (int (*)(struct notifier_block *,					unsigned long, void *))callback;	omapfb_nb->data = callback_data;	r = blocking_notifier_chain_register(

⌨️ 快捷键说明

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