/* -----------------------------------------------------------------------------
* 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);
}