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

📄 mx27_v4l2_output.c

📁 LINUX下的ov2640驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
}/*! * Shut down the voutera * * @param vout      structure vout_data * * * @return status  0 Success */static int mxc_v4l2out_streamoff(vout_data * vout){	int i, retval = 0;	unsigned long lock_flag = 0;	if (!vout)		return -EINVAL;	if (vout->state == STATE_STREAM_OFF) {		return 0;	}	spin_lock_irqsave(&g_lock, lock_flag);	del_timer(&vout->output_timer);	pp_enable(0);		/* Disable PP */	if (vout->state == STATE_STREAM_ON) {		vout->state = STATE_STREAM_STOPPING;	}	spin_unlock_irqrestore(&g_lock, lock_flag);	vout->ready_q.head = vout->ready_q.tail = 0;	vout->done_q.head = vout->done_q.tail = 0;	for (i = 0; i < vout->buffer_cnt; i++) {		vout->v4l2_bufs[i].flags = 0;		vout->v4l2_bufs[i].timestamp.tv_sec = 0;		vout->v4l2_bufs[i].timestamp.tv_usec = 0;	}	vout->state = STATE_STREAM_OFF;	if (vout->v4l2_fb.flags == V4L2_FBUF_FLAG_OVERLAY) {		struct fb_gwinfo gwinfo;		/* Disable graphic window */		gwinfo.enabled = 0;		mx2_gw_set(&gwinfo);	}#ifdef CONFIG_VIDEO_MXC_OUTPUT_FBSYNC	if (vout->tear_protection == TEARING_PROTECTION_ACTIVE) {		g_output_fb = -1;		g_fb_enabled = 0;		g_pp_ready = 0;		fb_unregister_client(&fb_event_notifier);		mx2fb_unregister_client(&mx2fb_event_notifier);	}#endif	mxc_free_buffers(vout->display_bufs, vout->display_bufs_vaddr,			 2, vout->sdc_fg_buf_size);	return retval;}/* * Valid whether the palette is supported * * @param palette  V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_BGR24 or V4L2_PIX_FMT_BGR32 * * @return 1 if supported, 0 if failed */static inline int valid_mode(u32 palette){	return (palette == V4L2_PIX_FMT_YUV420);}/* * Returns bits per pixel for given pixel format * * @param pixelformat  V4L2_PIX_FMT_RGB565, V4L2_PIX_FMT_BGR24 or V4L2_PIX_FMT_BGR32 * * @return bits per pixel of pixelformat */static u32 fmt_to_bpp(u32 pixelformat){	u32 bpp;	switch (pixelformat) {	case V4L2_PIX_FMT_RGB565:		bpp = 16;		break;	case V4L2_PIX_FMT_BGR24:	case V4L2_PIX_FMT_RGB24:		bpp = 24;		break;	case V4L2_PIX_FMT_BGR32:	case V4L2_PIX_FMT_RGB32:		bpp = 32;		break;	default:		bpp = 8;		break;	}	return bpp;}/* * V4L2 - Handles VIDIOC_G_FMT Ioctl * * @param vout         structure vout_data * * * @param v4l2_format structure v4l2_format * * * @return  status    0 success, EINVAL failed */static int mxc_v4l2out_g_fmt(vout_data * vout, struct v4l2_format *f){	if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {		return -EINVAL;	}	*f = vout->v2f;	return 0;}/* * V4L2 - Handles VIDIOC_S_FMT Ioctl * * @param vout         structure vout_data * * * @param v4l2_format structure v4l2_format * * * @return  status    0 success, EINVAL failed */static int mxc_v4l2out_s_fmt(vout_data * vout, struct v4l2_format *f){	int retval = 0;	u32 size = 0;	u32 bytesperline;	if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {		retval = -EINVAL;		goto err0;	}	if (!valid_mode(f->fmt.pix.pixelformat)) {		pr_debug("pixel format not supported\n");		retval = -EINVAL;		goto err0;	}	bytesperline = (f->fmt.pix.width * fmt_to_bpp(f->fmt.pix.pixelformat)) /	    8;	if (f->fmt.pix.bytesperline < bytesperline) {		f->fmt.pix.bytesperline = bytesperline;	} else {		bytesperline = f->fmt.pix.bytesperline;	}	switch (f->fmt.pix.pixelformat) {	case V4L2_PIX_FMT_YUV422P:		/* byteperline for YUV planar formats is for		   Y plane only */		size = bytesperline * f->fmt.pix.height * 2;		break;	case V4L2_PIX_FMT_YUV420:		size = (bytesperline * f->fmt.pix.height * 3) / 2;		break;	default:		size = bytesperline * f->fmt.pix.height;		break;	}	/* Return the actual size of the image to the app */	f->fmt.pix.sizeimage = size;	vout->v2f.fmt.pix.sizeimage = size;	vout->v2f.fmt.pix.width = f->fmt.pix.width;	vout->v2f.fmt.pix.height = f->fmt.pix.height;	vout->v2f.fmt.pix.pixelformat = f->fmt.pix.pixelformat;	vout->v2f.fmt.pix.bytesperline = f->fmt.pix.bytesperline;	retval = 0;      err0:	return retval;}/* * V4L2 - Handles VIDIOC_G_CTRL Ioctl * * @param vout         structure vout_data * * * @param c           structure v4l2_control * * * @return  status    0 success, EINVAL failed */static int mxc_get_v42lout_control(vout_data * vout, struct v4l2_control *c){	switch (c->id) {	case V4L2_CID_HFLIP:		return (vout->rotate & IPU_ROTATE_HORIZ_FLIP) ? 1 : 0;	case V4L2_CID_VFLIP:		return (vout->rotate & IPU_ROTATE_VERT_FLIP) ? 1 : 0;	case (V4L2_CID_PRIVATE_BASE + 1):		return vout->rotate;	case V4L2_CID_MXC_TEAR_PROTECT:		c->value = vout->tear_protection;		return 0;	default:		return -EINVAL;	}}/* * V4L2 - Handles VIDIOC_S_CTRL Ioctl * * @param vout         structure vout_data * * * @param c           structure v4l2_control * * * @return  status    0 success, EINVAL failed */static int mxc_set_v42lout_control(vout_data * vout, struct v4l2_control *c){	switch (c->id) {	case V4L2_CID_HFLIP:	case V4L2_CID_VFLIP:	case V4L2_CID_MXC_ROT:		return 0;	case V4L2_CID_MXC_TEAR_PROTECT:#ifdef CONFIG_VIDEO_MXC_OUTPUT_FBSYNC		if (c->value == TEARING_PROTECTION_ACTIVE)			vout->tear_protection = TEARING_PROTECTION_ACTIVE;		else			vout->tear_protection = TEARING_PROTECTION_INACTIVE;;#else		vout->tear_protection = TEARING_PROTECTION_UNSUPPORTED;#endif		return 0;	default:		return -EINVAL;	}	return 0;}/*! * V4L2 interface - open function * * @param inode        structure inode * * * @param file         structure file * * * @return  status    0 success, ENODEV invalid device instance, *                    ENODEV timeout, ERESTARTSYS interrupted by user */static int mxc_v4l2out_open(struct inode *inode, struct file *file){	struct video_device *dev = video_devdata(file);	vout_data *vout = video_get_drvdata(dev);	int err;	dq_intr_cnt = 0;	if (!vout) {		pr_info("Internal error, vout_data not found!\n");		return -ENODEV;	}	down(&vout->busy_lock);	err = -EINTR;	if (signal_pending(current))		goto oops;	if (vout->open_count++ == 0) {		pp_init(vout);		init_waitqueue_head(&vout->v4l_bufq);		init_timer(&vout->output_timer);		vout->output_timer.function = mxc_v4l2out_timer_handler;		vout->output_timer.data = (unsigned long)vout;		vout->state = STATE_STREAM_OFF;		g_irq_cnt = g_buf_output_cnt = g_buf_q_cnt = g_buf_dq_cnt = 0;	}#ifdef CONFIG_VIDEO_MXC_OUTPUT_FBSYNC	vout->tear_protection = TEARING_PROTECTION_ACTIVE;#else	vout->tear_protection = TEARING_PROTECTION_UNSUPPORTED;#endif	file->private_data = dev;	up(&vout->busy_lock);	return 0;      oops:	up(&vout->busy_lock);	return err;}/*! * V4L2 interface - close function * * @param inode    struct inode * * * @param file     struct file * * * @return         0 success */static int mxc_v4l2out_close(struct inode *inode, struct file *file){	struct video_device *dev = file->private_data;	vout_data *vout = video_get_drvdata(dev);	if (--vout->open_count == 0) {		pr_debug("release resource\n");		pp_exit(vout);		if (vout->state != STATE_STREAM_OFF)			mxc_v4l2out_streamoff(vout);		file->private_data = NULL;		mxc_free_buffers(vout->queue_buf_paddr,				 vout->queue_buf_vaddr,				 vout->buffer_cnt, vout->queue_buf_size);		vout->buffer_cnt = 0;		mxc_free_buffers(vout->display_bufs,				 vout->display_bufs_vaddr,				 2, vout->sdc_fg_buf_size);		/* capture off */		wake_up_interruptible(&vout->v4l_bufq);	}	return 0;}/*! * V4L2 interface - ioctl function * * @param inode      struct inode * * * @param file       struct file * * * @param ioctlnr    unsigned int * * @param arg        void * * * @return           0 success, ENODEV for invalid device instance, *                   -1 for other errors. */static intmxc_v4l2out_do_ioctl(struct inode *inode, struct file *file,		     unsigned int ioctlnr, void *arg){	struct video_device *dev = file->private_data;	vout_data *vout = video_get_drvdata(dev);	int retval = 0;	int i = 0;	if (!vout)		return -EBADF;	/* make this _really_ smp-safe */	if (down_interruptible(&vout->busy_lock))		return -EBUSY;	switch (ioctlnr) {	case VIDIOC_QUERYCAP:		{			struct v4l2_capability *cap = arg;			strcpy(cap->driver, "mxc_v4l2_output");			cap->version = 0;			cap->capabilities =			    V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;			cap->card[0] = '\0';			cap->bus_info[0] = '\0';			retval = 0;			break;		}	case VIDIOC_G_FMT:		{			struct v4l2_format *gf = arg;			retval = mxc_v4l2out_g_fmt(vout, gf);			break;		}	case VIDIOC_S_FMT:		{			struct v4l2_format *sf = arg;			if (vout->state != STATE_STREAM_OFF) {				retval = -EBUSY;				break;			}			retval = mxc_v4l2out_s_fmt(vout, sf);			break;		}	case VIDIOC_REQBUFS:		{			struct v4l2_requestbuffers *req = arg;			if ((req->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ||			    (req->memory != V4L2_MEMORY_MMAP)) {				pr_debug				    ("VIDIOC_REQBUFS: incorrect buffer type\n");				retval = -EINVAL;				break;			}			if (req->count == 0)				mxc_v4l2out_streamoff(vout);			if (vout->state == STATE_STREAM_OFF) {				if (vout->queue_buf_paddr[0] != 0) {					mxc_free_buffers(vout->queue_buf_paddr,							 vout->queue_buf_vaddr,							 vout->buffer_cnt,							 vout->queue_buf_size);					pr_debug					    ("VIDIOC_REQBUFS: freed buffers\n");				}				vout->buffer_cnt = 0;			} else {				pr_debug("VIDIOC_REQBUFS: Buffer is in use\n");				retval = -EBUSY;				break;			}			if (req->count == 0)				break;			if (req->count < MIN_FRAME_NUM) {				req->count = MIN_FRAME_NUM;			} else if (req->count > MAX_FRAME_NUM) {				req->count = MAX_FRAME_NUM;			}			vout->buffer_cnt = req->count;			vout->queue_buf_size =			    PAGE_ALIGN(vout->v2f.fmt.pix.sizeimage);			retval = mxc_allocate_buffers(vout->queue_buf_paddr,						      vout->queue_buf_vaddr,						      vout->buffer_cnt,						      vout->queue_buf_size);			if (retval < 0)				break;			/* Init buffer queues */			vout->done_q.head = 0;			vout->done_q.tail = 0;			vout->ready_q.head = 0;			vout->ready_q.tail = 0;			for (i = 0; i < vout->buffer_cnt; i++) {				memset(&(vout->v4l2_bufs[i]), 0,				       sizeof(vout->v4l2_bufs[i]));				vout->v4l2_bufs[i].flags = 0;				vout->v4l2_bufs[i].memory = V4L2_MEMORY_MMAP;				vout->v4l2_bufs[i].index = i;				vout->v4l2_bufs[i].type =				    V4L2_BUF_TYPE_VIDEO_OUTPUT;				vout->v4l2_bufs[i].length =				    PAGE_ALIGN(vout->v2f.fmt.pix.sizeimage);				vout->v4l2_bufs[i].m.offset =				    (unsigned long)vout->queue_buf_paddr[i];				vout->v4l2_bufs[i].timestamp.tv_sec = 0;				vout->v4l2_bufs[i].timestamp.tv_usec = 0;			}			break;		}	case VIDIOC_QUERYBUF:		{			struct v4l2_buffer *buf = arg;			u32 type = buf->type;			int index = buf->index;			if ((type != V4L2_BUF_TYPE_VIDEO_OUTPUT) ||			    (index >= vout->buffer_cnt)) {				pr_debug				    ("VIDIOC_QUERYBUFS: incorrect buffer type\n");				retval = -EINVAL;				break;			}			down(&vout->param_lock);			memcpy(buf, &(vout->v4l2_bufs[index]), sizeof(*buf));			up(&vout->param_lock);			break;		}	case VIDIOC_QBUF:		{			struct v4l2_buffer *buf = arg;			int index = buf->index;			unsigned long lock_flags;			unsigned long timeout;

⌨️ 快捷键说明

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