Загрузка данных


/* -----------------------------------------------------------------------------
 * Registration
 */

int mxc_isi_video_register(struct mxc_isi_pipe *pipe,
			   struct v4l2_device *v4l2_dev)
{
	struct mxc_isi_video *video = &pipe->video;
	struct v4l2_pix_format_mplane *pix = &video->pix;
	struct video_device *vdev = &video->vdev;
	struct vb2_queue *q = &video->vb2_q;
	int ret = -ENOMEM;

	video->pipe = pipe;

	mutex_init(&video->lock);
	spin_lock_init(&video->buf_lock);

	pix->width = MXC_ISI_DEF_WIDTH;
	pix->height = MXC_ISI_DEF_HEIGHT;
	pix->pixelformat = MXC_ISI_DEF_PIXEL_FORMAT;
	pix->colorspace = MXC_ISI_DEF_COLOR_SPACE;
	pix->ycbcr_enc = MXC_ISI_DEF_YCBCR_ENC;
	pix->quantization = MXC_ISI_DEF_QUANTIZATION;
	pix->xfer_func = MXC_ISI_DEF_XFER_FUNC;
	video->fmtinfo = mxc_isi_format_try(video->pipe, pix, MXC_ISI_VIDEO_CAP);

	memset(vdev, 0, sizeof(*vdev));
	snprintf(vdev->name, sizeof(vdev->name), "mxc_isi.%d.capture", pipe->id);

	vdev->fops	= &mxc_isi_video_fops;
	vdev->ioctl_ops	= &mxc_isi_video_ioctl_ops;
	vdev->v4l2_dev	= v4l2_dev;
	vdev->minor	= -1;
	vdev->release	= video_device_release_empty;
	vdev->queue	= q;
	vdev->lock	= &video->lock;

	vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE_MPLANE
			  | V4L2_CAP_IO_MC;
	video_set_drvdata(vdev, video);

	INIT_LIST_HEAD(&video->out_pending);
	INIT_LIST_HEAD(&video->out_active);
	INIT_LIST_HEAD(&video->out_discard);

	memset(q, 0, sizeof(*q));
	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
	q->io_modes = VB2_MMAP | VB2_DMABUF;
	q->drv_priv = video;
	q->ops = &mxc_isi_vb2_qops;
	q->mem_ops = &vb2_dma_contig_memops;
	q->buf_struct_size = sizeof(struct mxc_isi_buffer);
	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
	q->min_queued_buffers = 2;
	q->lock = &video->lock;
	q->dev = pipe->isi->dev;

	ret = vb2_queue_init(q);
	if (ret)
		goto err_free_ctx;

	video->pad.flags = MEDIA_PAD_FL_SINK;
	vdev->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER;
	ret = media_entity_pads_init(&vdev->entity, 1, &video->pad);
	if (ret)
		goto err_free_ctx;

	ret = mxc_isi_video_ctrls_create(video);
	if (ret)
		goto err_me_cleanup;

	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
	if (ret)
		goto err_ctrl_free;

	ret = media_create_pad_link(&pipe->sd.entity,
				    MXC_ISI_PIPE_PAD_SOURCE,
				    &vdev->entity, 0,
				    MEDIA_LNK_FL_IMMUTABLE |
				    MEDIA_LNK_FL_ENABLED);
	if (ret)
		goto err_video_unreg;

	return 0;

err_video_unreg:
	video_unregister_device(vdev);
err_ctrl_free:
	mxc_isi_video_ctrls_delete(video);
err_me_cleanup:
	media_entity_cleanup(&vdev->entity);
err_free_ctx:
	return ret;
}

void mxc_isi_video_unregister(struct mxc_isi_pipe *pipe)
{
	struct mxc_isi_video *video = &pipe->video;
	struct video_device *vdev = &video->vdev;

	mutex_lock(&video->lock);

	if (video_is_registered(vdev)) {
		video_unregister_device(vdev);
		mxc_isi_video_ctrls_delete(video);
		media_entity_cleanup(&vdev->entity);
	}

	mutex_unlock(&video->lock);
}