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

📄 ivtvfb.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
	itv->yuv_info.yuv_forced_update = 1;	return 0;}static int ivtvfb_set_par(struct fb_info *info){	int rc = 0;	struct ivtv *itv = (struct ivtv *) info->par;	IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");	rc = ivtvfb_set_var(itv, &info->var);	ivtvfb_pan_display(&info->var, info);	ivtvfb_get_fix(itv, &info->fix);	return rc;}static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,				unsigned blue, unsigned transp,				struct fb_info *info){	u32 color, *palette;	struct ivtv *itv = (struct ivtv *)info->par;	if (regno >= info->cmap.len)		return -EINVAL;	color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);	if (info->var.bits_per_pixel <= 8) {		write_reg(regno, 0x02a30);		write_reg(color, 0x02a34);		return 0;	}	if (regno >= 16)		return -EINVAL;	palette = info->pseudo_palette;	if (info->var.bits_per_pixel == 16) {		switch (info->var.green.length) {			case 4:				color = ((red & 0xf000) >> 4) |					((green & 0xf000) >> 8) |					((blue & 0xf000) >> 12);				break;			case 5:				color = ((red & 0xf800) >> 1) |					((green & 0xf800) >> 6) |					((blue & 0xf800) >> 11);				break;			case 6:				color = (red & 0xf800 ) |					((green & 0xfc00) >> 5) |					((blue & 0xf800) >> 11);				break;		}	}	palette[regno] = color;	return 0;}/* We don't really support blanking. All this does is enable or   disable the OSD. */static int ivtvfb_blank(int blank_mode, struct fb_info *info){	struct ivtv *itv = (struct ivtv *)info->par;	IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode);	switch (blank_mode) {	case FB_BLANK_UNBLANK:		ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);		ivtv_saa7127(itv, VIDIOC_STREAMON, NULL);		break;	case FB_BLANK_NORMAL:	case FB_BLANK_HSYNC_SUSPEND:	case FB_BLANK_VSYNC_SUSPEND:		ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);		ivtv_saa7127(itv, VIDIOC_STREAMON, NULL);		break;	case FB_BLANK_POWERDOWN:		ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL);		ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);		break;	}	return 0;}static struct fb_ops ivtvfb_ops = {	.owner = THIS_MODULE,	.fb_write       = ivtvfb_write,	.fb_check_var   = ivtvfb_check_var,	.fb_set_par     = ivtvfb_set_par,	.fb_setcolreg   = ivtvfb_setcolreg,	.fb_fillrect    = cfb_fillrect,	.fb_copyarea    = cfb_copyarea,	.fb_imageblit   = cfb_imageblit,	.fb_cursor      = NULL,	.fb_ioctl       = ivtvfb_ioctl,	.fb_pan_display = ivtvfb_pan_display,	.fb_blank       = ivtvfb_blank,};/* Initialization *//* Setup our initial video mode */static int ivtvfb_init_vidmode(struct ivtv *itv){	struct osd_info *oi = itv->osd_info;	struct v4l2_rect start_window;	int max_height;	/* Color mode */	if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)		osd_depth = 8;	oi->bits_per_pixel = osd_depth;	oi->bytes_per_pixel = oi->bits_per_pixel / 8;	/* Horizontal size & position */	if (osd_xres > 720)		osd_xres = 720;	/* Must be a multiple of 4 for 8bpp & 2 for 16bpp */	if (osd_depth == 8)		osd_xres &= ~3;	else if (osd_depth == 16)		osd_xres &= ~1;	start_window.width = osd_xres ? osd_xres : 640;	/* Check horizontal start (osd_left). */	if (osd_left && osd_left + start_window.width > 721) {		IVTVFB_ERR("Invalid osd_left - assuming default\n");		osd_left = 0;	}	/* Hardware coords start at 0, user coords start at 1. */	osd_left--;	start_window.left = osd_left >= 0 ? osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);	oi->display_byte_stride =			start_window.width * oi->bytes_per_pixel;	/* Vertical size & position */	max_height = itv->is_50hz ? 576 : 480;	if (osd_yres > max_height)		osd_yres = max_height;	start_window.height = osd_yres ? osd_yres : itv->is_50hz ? 480 : 400;	/* Check vertical start (osd_upper). */	if (osd_upper + start_window.height > max_height + 1) {		IVTVFB_ERR("Invalid osd_upper - assuming default\n");		osd_upper = 0;	}	/* Hardware coords start at 0, user coords start at 1. */	osd_upper--;	start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2);	oi->display_width = start_window.width;	oi->display_height = start_window.height;	/* Generate a valid fb_var_screeninfo */	oi->ivtvfb_defined.xres = oi->display_width;	oi->ivtvfb_defined.yres = oi->display_height;	oi->ivtvfb_defined.xres_virtual = oi->display_width;	oi->ivtvfb_defined.yres_virtual = oi->display_height;	oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel;	oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED);	oi->ivtvfb_defined.left_margin = start_window.left + 1;	oi->ivtvfb_defined.upper_margin = start_window.top + 1;	oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE;	oi->ivtvfb_defined.nonstd = 0;	/* We've filled in the most data, let the usual mode check	   routine fill in the rest. */	_ivtvfb_check_var(&oi->ivtvfb_defined, itv);	/* Generate valid fb_fix_screeninfo */	ivtvfb_get_fix(itv, &oi->ivtvfb_fix);	/* Generate valid fb_info */	oi->ivtvfb_info.node = -1;	oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT;	oi->ivtvfb_info.fbops = &ivtvfb_ops;	oi->ivtvfb_info.par = itv;	oi->ivtvfb_info.var = oi->ivtvfb_defined;	oi->ivtvfb_info.fix = oi->ivtvfb_fix;	oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase;	oi->ivtvfb_info.fbops = &ivtvfb_ops;	/* Supply some monitor specs. Bogus values will do for now */	oi->ivtvfb_info.monspecs.hfmin = 8000;	oi->ivtvfb_info.monspecs.hfmax = 70000;	oi->ivtvfb_info.monspecs.vfmin = 10;	oi->ivtvfb_info.monspecs.vfmax = 100;	/* Allocate color map */	if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) {		IVTVFB_ERR("abort, unable to alloc cmap\n");		return -ENOMEM;	}	/* Allocate the pseudo palette */	oi->ivtvfb_info.pseudo_palette =		kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN);	if (!oi->ivtvfb_info.pseudo_palette) {		IVTVFB_ERR("abort, unable to alloc pseudo pallete\n");		return -ENOMEM;	}	return 0;}/* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */static int ivtvfb_init_io(struct ivtv *itv){	struct osd_info *oi = itv->osd_info;	mutex_lock(&itv->serialize_lock);	if (ivtv_init_on_first_open(itv)) {		mutex_unlock(&itv->serialize_lock);		IVTVFB_ERR("Failed to initialize ivtv\n");		return -ENXIO;	}	mutex_unlock(&itv->serialize_lock);	ivtvfb_get_framebuffer(itv, &oi->video_rbase, &oi->video_buffer_size);	/* The osd buffer size depends on the number of video buffers allocated	   on the PVR350 itself. For now we'll hardcode the smallest osd buffer	   size to prevent any overlap. */	oi->video_buffer_size = 1704960;	oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase;	oi->video_vbase = itv->dec_mem + oi->video_rbase;	if (!oi->video_vbase) {		IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",		     oi->video_buffer_size, oi->video_pbase);		return -EIO;	}	IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",			oi->video_pbase, oi->video_vbase,			oi->video_buffer_size / 1024);#ifdef CONFIG_MTRR	{		/* Find the largest power of two that maps the whole buffer */		int size_shift = 31;		while (!(oi->video_buffer_size & (1 << size_shift))) {			size_shift--;		}		size_shift++;		oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);		oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;		oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;		oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);		if (mtrr_add(oi->fb_start_aligned_physaddr,			oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr,			     MTRR_TYPE_WRCOMB, 1) < 0) {			IVTVFB_INFO("disabled mttr\n");			oi->fb_start_aligned_physaddr = 0;			oi->fb_end_aligned_physaddr = 0;		}	}#endif	/* Blank the entire osd. */	memset_io(oi->video_vbase, 0, oi->video_buffer_size);	return 0;}/* Release any memory we've grabbed & remove mtrr entry */static void ivtvfb_release_buffers (struct ivtv *itv){	struct osd_info *oi = itv->osd_info;	/* Release cmap */	if (oi->ivtvfb_info.cmap.len)		fb_dealloc_cmap(&oi->ivtvfb_info.cmap);	/* Release pseudo palette */	if (oi->ivtvfb_info.pseudo_palette)		kfree(oi->ivtvfb_info.pseudo_palette);#ifdef CONFIG_MTRR	if (oi->fb_end_aligned_physaddr) {		mtrr_del(-1, oi->fb_start_aligned_physaddr,			oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr);	}#endif	kfree(oi);	itv->osd_info = NULL;}/* Initialize the specified card */static int ivtvfb_init_card(struct ivtv *itv){	int rc;	if (itv->osd_info) {		IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);		return -EBUSY;	}	itv->osd_info = kzalloc(sizeof(struct osd_info),					GFP_ATOMIC|__GFP_NOWARN);	if (itv->osd_info == NULL) {		IVTVFB_ERR("Failed to allocate memory for osd_info\n");		return -ENOMEM;	}	/* Find & setup the OSD buffer */	if ((rc = ivtvfb_init_io(itv)))		return rc;	/* Set the startup video mode information */	if ((rc = ivtvfb_init_vidmode(itv))) {		ivtvfb_release_buffers(itv);		return rc;	}	/* Register the framebuffer */	if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) {		ivtvfb_release_buffers(itv);		return -EINVAL;	}	itv->osd_video_pbase = itv->osd_info->video_pbase;	/* Set the card to the requested mode */	ivtvfb_set_par(&itv->osd_info->ivtvfb_info);	/* Set color 0 to black */	write_reg(0, 0x02a30);	write_reg(0, 0x02a34);	/* Enable the osd */	ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);	/* Allocate DMA */	ivtv_udma_alloc(itv);	return 0;}static int __init ivtvfb_init(void){	struct ivtv *itv;	int i, registered = 0;	if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {		printk(KERN_ERR "ivtvfb:  ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",		     IVTV_MAX_CARDS - 1);		return -EINVAL;	}	/* Locate & initialise all cards supporting an OSD. */	for (i = 0; i < ivtv_cards_active; i++) {		if (ivtvfb_card_id != -1 && i != ivtvfb_card_id)			continue;		itv = ivtv_cards[i];		if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {			if (ivtvfb_init_card(itv) == 0) {				IVTVFB_INFO("Framebuffer registered on ivtv card id %d\n", i);				registered++;			}		}	}	if (!registered) {		printk(KERN_ERR "ivtvfb:  no cards found");		return -ENODEV;	}	return 0;}static void ivtvfb_cleanup(void){	struct ivtv *itv;	int i;	printk(KERN_INFO "ivtvfb:  Unloading framebuffer module\n");	for (i = 0; i < ivtv_cards_active; i++) {		itv = ivtv_cards[i];		if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) && itv->osd_info) {			if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {				IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", i);				return;			}			IVTVFB_DEBUG_INFO("Unregister framebuffer %d\n", i);			ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info);			ivtvfb_release_buffers(itv);			itv->osd_video_pbase = 0;		}	}}module_init(ivtvfb_init);module_exit(ivtvfb_cleanup);

⌨️ 快捷键说明

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