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

📄 s3c2440camif.c

📁 ov9650的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
	return 0;error3:	PDEBUG("free img_buff[2] pages.\n");	free_pages(img_buff[2].virt_base, order);	img_buff[2].phy_base = (unsigned long)NULL;error2:	PDEBUG("free img_buff[1] pages.\n");	free_pages(img_buff[1].virt_base, order);	img_buff[1].phy_base = (unsigned long)NULL;error1:	PDEBUG("free img_buff[0] pages.\n");	free_pages(img_buff[0].virt_base, order);	img_buff[0].phy_base = (unsigned long)NULL;error0:	return -ENOMEM;}/* free image buffers (only when the camif is latest close). */static void __inline__ free_image_buffer(void){	if ((img_buff[0].virt_base == (unsigned long)NULL)		||(img_buff[1].virt_base == (unsigned long)NULL)		||(img_buff[2].virt_base == (unsigned long)NULL)		||(img_buff[3].virt_base == (unsigned long)NULL))	{		PDEBUG("bug here.");		BUG();	}	free_pages(img_buff[0].virt_base, img_buff[0].order);	free_pages(img_buff[1].virt_base, img_buff[1].order);	free_pages(img_buff[2].virt_base, img_buff[2].order);	free_pages(img_buff[3].virt_base, img_buff[3].order);	img_buff[0].order = 0;	img_buff[0].virt_base = (unsigned long)NULL;	img_buff[0].phy_base = (unsigned long)NULL;	img_buff[1].order = 0;	img_buff[1].virt_base = (unsigned long)NULL;	img_buff[1].phy_base = (unsigned long)NULL;	img_buff[2].order = 0;	img_buff[2].virt_base = (unsigned long)NULL;	img_buff[2].phy_base = (unsigned long)NULL;	img_buff[3].order = 0;	img_buff[3].virt_base = (unsigned long)NULL;	img_buff[3].phy_base = (unsigned long)NULL;	PDEBUG("free pages for img_buff[0..3] done.\n");}/* * vidioc_querycap(), *  * IOCTL method for cmd 'VIDIOC_QUERYCAP' */static int vidioc_querycap (struct file *file, void  *priv, struct v4l2_capability *cap){	PDEBUG("now in %s().\n", __FUNCTION__);	memset(cap, 0, sizeof(struct v4l2_capability));	strcpy(cap->driver, DRIVER_NAME);	strcpy(cap->card, CARD_NAME);	cap->version = DRIVER_VERSION;	cap->capabilities =	V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;	return 0;}/* * vidioc_enum_fmt_cap () * * IOCTL method for cmd 'VIDIOC_ENUM_FMT' */static int vidioc_enum_fmt_cap (struct file *file, void  *priv, struct v4l2_fmtdesc *f){	int index;	int ret;	PDEBUG("now in %s().\n", __FUNCTION__);	switch (f->type)	{	case V4L2_BUF_TYPE_VIDEO_CAPTURE:		index = f->index;		if (index < ARRAY_SIZE(formats))		{			memset (f, 0, sizeof (struct v4l2_fmtdesc));			f->index = index;			f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;			f->flags = 0;			f->pixelformat = formats[index].pixelformat;			memcpy (&f->description[0], &formats[index].description[0], sizeof(formats[index].description));			ret = 0;			PDEBUG("%s() successfully!\n", __FUNCTION__);		}		else		{			PDEBUG("%s() fail, f->index = %d.\n", __FUNCTION__, f->index);			ret = -EINVAL;		}		break;	default:		PDEBUG("%s() failed with unknown buffer type %d.\n", __FUNCTION__, f->type);		ret = -EINVAL;		break;	}		return ret;}/* * vidioc_g_fmt_cap () * * IOCTL method for cmd 'VIDIOC_G_FMT' */static int vidioc_g_fmt_cap (struct file *file, void * priv, struct v4l2_format * f){	int ret;	struct s3c2440camif_fh  * fh;	struct s3c2440camif_dev * pdev;	fh = priv;	pdev = fh->dev;	PDEBUG("now in %s().\n", __FUNCTION__);	if (pdev->format >= ARRAY_SIZE(formats)) BUG();	switch(f->type)	{	case V4L2_BUF_TYPE_VIDEO_CAPTURE:		switch (formats[pdev->format].pixelformat)		{		case V4L2_PIX_FMT_RGB565:		case V4L2_PIX_FMT_RGB24:			f->fmt.pix.width = pdev->preTargetHsize;			f->fmt.pix.height = pdev->preTargetVsize;			f->fmt.pix.field = V4L2_FIELD_ANY;			f->fmt.pix.pixelformat = formats[pdev->format].pixelformat;			f->fmt.pix.bytesperline = (pdev->preTargetHsize * formats[pdev->format].depth) / 8;			f->fmt.pix.sizeimage = pdev->preTargetVsize * f->fmt.pix.bytesperline;			f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;			f->fmt.pix.priv = 0;			PDEBUG("%s() successfully.\n", __FUNCTION__);			break;		case V4L2_PIX_FMT_YUV420:		case V4L2_PIX_FMT_YUYV:			f->fmt.pix.width = pdev->coTargetHsize;			f->fmt.pix.height = pdev->coTargetVsize;			f->fmt.pix.field = V4L2_FIELD_ANY;			f->fmt.pix.pixelformat = formats[pdev->format].pixelformat;			f->fmt.pix.bytesperline = (pdev->coTargetHsize * formats[pdev->format].depth) / 8;			f->fmt.pix.sizeimage = pdev->coTargetVsize * f->fmt.pix.bytesperline;			f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;			f->fmt.pix.priv = 0;			PDEBUG("%s() successfully.\n", __FUNCTION__);			break;		default:			PDEBUG("bug here.");			BUG();			break;		}		ret = 0;		break;	default:		PDEBUG("%s() failed with unknown buffer type %d.\n", __FUNCTION__, f->type);		ret = -EINVAL;		break;	}	return ret;}/* * vidioc_s_fmt_cap () * * IOCTL method for cmd 'VIDIOC_S_FMT' */static int vidioc_s_fmt_cap (struct file *file, void *priv, struct v4l2_format * f){	int i;	int ret;	struct v4l2_pix_format  * pfmt;	struct s3c2440camif_fh  * fh;	struct s3c2440camif_dev * pdev;	u32 cmdcode;	fh = priv;	pdev = fh->dev;	cmdcode = CAMIF_CMD_NONE;	PDEBUG("now in %s().\n", __FUNCTION__);	if (fh->master != 1)	{		if (mutex_trylock(&pdev->mfhlock) != 0)		{			fh->master = 1;			PDEBUG("pid %d[%s] is now the master file handle.\n", current->pid, current->comm);		}		else		{			PDEBUG("%s(), not a master file handle!\n", __FUNCTION__);			return -EBUSY;		}	}	ret = 0;	switch(f->type)	{	case V4L2_BUF_TYPE_VIDEO_CAPTURE:		pfmt = &f->fmt.pix;		for (i = 0; i < ARRAY_SIZE(formats); i++)		{			if (formats[i].pixelformat == pfmt->pixelformat)			{				PDEBUG("%s() find, the new format is %s!\n", __FUNCTION__, &formats[i].description[0]);				break;			}		}		if (i >= ARRAY_SIZE(formats))		{			/* unsupport image format, just return current image format. */			PDEBUG("unsupported pixel format, 0x%08x\n", pfmt->pixelformat);			vidioc_g_fmt_cap(file, priv, f);		}		else		{			switch (formats[i].pixelformat)			{			case V4L2_PIX_FMT_RGB565:			case V4L2_PIX_FMT_RGB24:				/* change P-path setting. */				if (pfmt->width >= MAX_P_WIDTH)					pdev->preTargetHsize = MAX_P_WIDTH;				else					pdev->preTargetHsize = pfmt->width & 0xFFFFFFF8;				if (pfmt->height >= MAX_P_HEIGHT)					pdev->preTargetVsize = MAX_P_HEIGHT;				else					pdev->preTargetVsize = pfmt->height & 0xFFFFFFF8;				f->fmt.pix.width = pdev->preTargetHsize;				f->fmt.pix.height = pdev->preTargetVsize;				f->fmt.pix.pixelformat = formats[i].pixelformat;				f->fmt.pix.bytesperline = (pdev->preTargetHsize * formats[i].depth) / 8;				f->fmt.pix.sizeimage = pdev->preTargetVsize * f->fmt.pix.bytesperline;				f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;				f->fmt.pix.priv = 0;				pdev->format = i;					pdev->p_format = i;				PDEBUG("P-path default output format changed.\n");				break;			case V4L2_PIX_FMT_YUV420:			case V4L2_PIX_FMT_YUYV:				/* change C-path setting. */				if (pfmt->width >= MAX_C_WIDTH)					pdev->coTargetHsize = MAX_C_WIDTH;				else					pdev->coTargetHsize = pfmt->width & 0xFFFFFFF8;				if (pfmt->height >= MAX_C_HEIGHT)					pdev->coTargetVsize = MAX_C_HEIGHT;				else					pdev->coTargetVsize = pfmt->height & 0xFFFFFFF8;				f->fmt.pix.width = pdev->coTargetHsize;				f->fmt.pix.height = pdev->coTargetVsize;				f->fmt.pix.pixelformat = formats[i].pixelformat;				f->fmt.pix.bytesperline = (pdev->coTargetHsize * formats[i].depth) / 8;				f->fmt.pix.sizeimage = pdev->coTargetVsize * f->fmt.pix.bytesperline;				f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;				f->fmt.pix.priv = 0;				pdev->format = i;				pdev->c_format = i;				PDEBUG("C-path default output format changed.\n");				break;			default:				BUG();				break;			}		}		update_camif_config(fh, cmdcode);	// ok, updates the camif regs.		break;	default:		PDEBUG("%s() unknown buffer type %d.\n", __FUNCTION__, f->type);		ret = -EINVAL;		break;	}	return ret;}static int vidioc_queryctrl (struct file *file, void  *priv, struct v4l2_queryctrl * arg){	int ret;	PDEBUG("now in %s().\n", __FUNCTION__);	if (arg->id < ARRAY_SIZE(g_ctrls))	{		memcpy (arg, &g_ctrls[arg->id], sizeof(struct v4l2_queryctrl));		ret = 0;	}	else	{		ret = -EINVAL;	}		return ret;}static int vidioc_g_ctrl (struct file *file, void  *priv, struct v4l2_control * arg){	int ret;	struct s3c2440camif_fh  * fh;	struct s3c2440camif_dev * pdev;	PDEBUG("now in %s().\n", __FUNCTION__);	fh = priv;	pdev = fh->dev;	switch (arg->id)	{	case 0:		arg->value = (pdev->srcHsize - pdev->wndHsize) / 2;		PDEBUG("horizontal window offset: %d\n", arg->value);		ret = 0;		break;			case 1:		arg->value = (pdev->srcVsize - pdev->wndVsize) / 2;		PDEBUG("vertical window offset: %d\n", arg->value);		ret = 0;		break;			default:		PDEBUG("unknown control id: [%d]\n", arg->id);		ret = -EINVAL;		break;	}		return ret;}static int vidioc_s_ctrl (struct file *file, void  *priv, struct v4l2_control * arg){	int ret;	struct s3c2440camif_fh  * fh;	struct s3c2440camif_dev * pdev;	PDEBUG("now in %s().\n", __FUNCTION__);	fh = priv;	pdev = fh->dev;	switch (arg->id)	{	case 0:		BUG_ON((arg->value%8)!=0);		pdev->wndHsize = (pdev->srcHsize - arg->value) / 2;		PDEBUG("horizontal window size changed to: %d\n", pdev->wndHsize);		ret = 0;		break;			case 1:		BUG_ON((arg->value%8)!=0);		pdev->wndVsize = (pdev->srcVsize - arg->value) / 2;		PDEBUG("vertical window offset: %d\n", pdev->wndVsize);		ret = 0;		break;			default:		PDEBUG("unknown control id: [%d]\n", arg->id);		ret = -EINVAL;		break;	}	return ret;}/* * ISR: service for C-path interrupt. */static irqreturn_t on_camif_irq_c(int irq, void * dev){	u32 cicostatus;	u32 frame;	struct s3c2440camif_dev * pdev;	cicostatus = ioread32(S3C244X_CICOSTATUS);	PDEBUG("Now in CAM_C ISR, CICOSTATUS=0x%08x!!\n", cicostatus);	if ((cicostatus & (1<<21))== 0)	{		return IRQ_RETVAL(IRQ_NONE);	}	pdev = (struct s3c2440camif_dev *)dev;	/* valid img_buff[x] just DMAed. */	frame = (cicostatus&(3<<26))>>26;	frame = (frame+4-1)%4;	PDEBUG("frame=%d\n", frame);	if (formats[pdev->format].pixelformat == V4L2_PIX_FMT_YUV420)	{		img_buff[frame].state = CAMIF_BUFF_YCbCr420;	}	else	{		img_buff[frame].state = CAMIF_BUFF_YCbCr422;	}	if (pdev->cmdcode & CAMIF_CMD_STOP)	{		stop_capture(pdev);		pdev->state = CAMIF_STATE_READY;	}	else	{		if (pdev->cmdcode & CAMIF_CMD_C2P)		{			camif_c2p(pdev);		}		if (pdev->cmdcode & CAMIF_CMD_WND)		{			update_target_wnd_regs(pdev);		}		if (pdev->cmdcode & CAMIF_CMD_TFMT)		{			update_target_fmt_regs(pdev);		}		if (pdev->cmdcode & CAMIF_CMD_ZOOM)		{			update_target_zoom_regs(pdev);		}		invalid_image_buffer();	}	pdev->cmdcode = CAMIF_CMD_NONE;	wake_up(&pdev->cmdqueue);	PDEBUG("wake up some process from camif command queue!\n");	return IRQ_RETVAL(IRQ_HANDLED);}/* * ISR: service for P-path interrupt. */static irqreturn_t on_camif_irq_p(int irq, void * dev){	u32 ciprstatus;	u32 frame;	struct s3c2440camif_dev * pdev;	ciprstatus = ioread32(S3C244X_CIPRSTATUS);	PDEBUG("Now in CAM_P ISR, CIPRSTATUS=0x%08x!!\n", ciprstatus);	if ((ciprstatus & (1<<21))== 0)	{		return IRQ_RETVAL(IRQ_NONE);	}	pdev = (struct s3c2440camif_dev *)dev;	/* valid img_buff[x] just DMAed. */	frame = (ciprstatus&(3<<26))>>26;	frame = (frame+4-1)%4;	PDEBUG("frame=%d\n", frame);	if (formats[pdev->format].pixelformat == V4L2_PIX_FMT_RGB565)	{		img_buff[frame].state = CAMIF_BUFF_RGB565;	}	else	{		img_buff[frame].state = CAMIF_BUFF_RGB24;	}	if (pdev->cmdcode & CAMIF_CMD_STOP)	{		stop_capture(pdev);		pdev->state = CAMIF_STATE_READY;	}	else	{		if (pdev->cmdcode & CAMIF_CMD_P2C)		{			camif_c2p(pdev);		}		if (pdev->cmdcode & CAMIF_CMD_WND)		{			update_target_wnd_regs(pdev);		}		if (pdev->cmdcode & CAMIF_CMD_TFMT)		{			update_target_fmt_regs(pdev);		}		if (pdev->cmdcode & CAMIF_CMD_ZOOM)		{			update_target_zoom_regs(pdev);		}		invalid_image_buffer();	}	pdev->cmdcode = CAMIF_CMD_NONE;	wake_up(&pdev->cmdqueue);	PDEBUG("wake up some process from camif command queue!\n");	return IRQ_RETVAL(IRQ_HANDLED);}/* * camif_open()

⌨️ 快捷键说明

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