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

📄 mxc_v4l2_output.c

📁 LINUX下的ov2640驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
			}			if (ipu_init_channel_buffer(MEM_ROT_PP_MEM,						    IPU_INPUT_BUFFER,						    params.mem_pp_mem.						    out_pixel_fmt, out_width,						    out_height, out_width,						    vout->rotate,						    vout->rot_pp_bufs[0],						    vout->rot_pp_bufs[1], 0,						    0) != 0) {				dev_err(dev,					"Error initializing PP ROT input buffer\n");				return -EINVAL;			}			/* swap width and height */			out_width = vout->crop_current.width;			out_height = vout->crop_current.height;			if (ipu_init_channel_buffer(MEM_ROT_PP_MEM,						    IPU_OUTPUT_BUFFER,						    params.mem_pp_mem.						    out_pixel_fmt, out_width,						    out_height, out_width,						    IPU_ROTATE_NONE,						    vout->display_bufs[0],						    vout->display_bufs[1], 0,						    0) != 0) {				dev_err(dev,					"Error initializing PP output buffer\n");				return -EINVAL;			}			if (ipu_link_channels(vout->post_proc_ch,					      MEM_ROT_PP_MEM) < 0) {				return -EINVAL;			}			ipu_select_buffer(MEM_ROT_PP_MEM, IPU_OUTPUT_BUFFER, 0);			ipu_select_buffer(MEM_ROT_PP_MEM, IPU_OUTPUT_BUFFER, 1);			ipu_enable_channel(MEM_ROT_PP_MEM);			display_input_ch = MEM_ROT_PP_MEM;		} else {			if (ipu_init_channel_buffer(vout->post_proc_ch,						    IPU_OUTPUT_BUFFER,						    params.mem_pp_mem.						    out_pixel_fmt, out_width,						    out_height, out_width,						    vout->rotate,						    vout->display_bufs[0],						    vout->display_bufs[1], 0,						    0) != 0) {				dev_err(dev,					"Error initializing PP output buffer\n");				return -EINVAL;			}		}		if (ipu_link_channels(display_input_ch, vout->display_ch) < 0) {			dev_err(dev, "Error linking ipu channels\n");			return -EINVAL;		}	}	vout->state = STATE_STREAM_PAUSED;	ipu_select_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, 0);	ipu_select_buffer(vout->post_proc_ch, IPU_INPUT_BUFFER, 1);	if (use_direct_adc == false) {		ipu_select_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, 0);		ipu_select_buffer(vout->post_proc_ch, IPU_OUTPUT_BUFFER, 1);		ipu_enable_channel(vout->post_proc_ch);		ipu_enable_channel(vout->display_ch);	} else {		ipu_enable_channel(vout->post_proc_ch);	}	vout->start_jiffies = jiffies;	dev_dbg(dev,		"streamon: start time = %lu jiffies\n", vout->start_jiffies);	return 0;}/*! * 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;	u32 lockflag = 0;	if (!vout)		return -EINVAL;	if (vout->state == STATE_STREAM_OFF) {		return 0;	}	spin_lock_irqsave(&g_lock, lockflag);	del_timer(&vout->output_timer);	if (vout->state == STATE_STREAM_ON) {		vout->state = STATE_STREAM_STOPPING;	}	ipu_disable_irq(IPU_IRQ_PP_IN_EOF);	spin_unlock_irqrestore(&g_lock, lockflag);	if (vout->post_proc_ch == MEM_PP_MEM) {	/* SDC or ADC with Rotation */		ipu_disable_channel(MEM_PP_MEM, true);		if (vout->rotate >= IPU_ROTATE_90_RIGHT) {			ipu_disable_channel(MEM_ROT_PP_MEM, true);			ipu_unlink_channels(MEM_PP_MEM, MEM_ROT_PP_MEM);			ipu_unlink_channels(MEM_ROT_PP_MEM, vout->display_ch);		} else {			ipu_unlink_channels(MEM_PP_MEM, vout->display_ch);		}		ipu_disable_channel(vout->display_ch, true);		ipu_uninit_channel(vout->display_ch);		ipu_uninit_channel(MEM_PP_MEM);		ipu_uninit_channel(MEM_ROT_PP_MEM);	} else {		/* ADC Direct */		ipu_disable_channel(MEM_PP_ADC, true);		ipu_uninit_channel(MEM_PP_ADC);	}	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;#ifdef CONFIG_FB_MXC_ASYNC_PANEL	if (vout->cur_disp_output != DISP3) {		mxcfb_set_refresh_mode(registered_fb				       [vout->					output_fb_num[vout->cur_disp_output]],				       MXCFB_REFRESH_PARTIAL, 0);	}#endif	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_RGB565) ||		(palette == V4L2_PIX_FMT_BGR24) ||		(palette == V4L2_PIX_FMT_RGB24) ||		(palette == V4L2_PIX_FMT_BGR32) ||		(palette == V4L2_PIX_FMT_RGB32) ||		(palette == V4L2_PIX_FMT_YUV422P) ||		(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)) {		dev_err(vout->video_dev->dev, "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 */	if (f->fmt.pix.sizeimage < size) {		f->fmt.pix.sizeimage = size;	} else {		size = f->fmt.pix.sizeimage;	}	vout->v2f.fmt.pix = f->fmt.pix;	copy_from_user(&vout->offset, (void *)vout->v2f.fmt.pix.priv,		       sizeof(vout->offset));	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;	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:		vout->rotate |= c->value ? IPU_ROTATE_HORIZ_FLIP :		    IPU_ROTATE_NONE;		break;	case V4L2_CID_VFLIP:		vout->rotate |= c->value ? IPU_ROTATE_VERT_FLIP :		    IPU_ROTATE_NONE;		break;	case V4L2_CID_MXC_ROT:		vout->rotate = c->value;		break;	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;	dq_timeout_cnt = 0;	if (!vout) {		return -ENODEV;	}	down(&vout->busy_lock);	err = -EINTR;	if (signal_pending(current))		goto oops;	if (vout->open_count++ == 0) {		ipu_request_irq(IPU_IRQ_PP_IN_EOF,				mxc_v4l2out_pp_in_irq_handler,				0, dev->name, 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;	}	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) {		if (vout->state != STATE_STREAM_OFF)			mxc_v4l2out_streamoff(vout);		ipu_free_irq(IPU_IRQ_PP_IN_EOF, 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);		mxc_free_buffers(vout->rot_pp_bufs, vout->rot_pp_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 *vdev = file->private_data;	vout_data *vout = video_get_drvdata(vdev);	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)) {				dev_dbg(vdev->dev,					"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);					dev_dbg(vdev->dev,						"VIDIOC_REQBUFS: freed buffers\n");				}				vout->buffer_cnt = 0;			} else {				dev_dbg(vdev->dev,					"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 =

⌨️ 快捷键说明

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