diff options
Diffstat (limited to 'drivers/staging/media/imx/imx-media-capture.c')
-rw-r--r-- | drivers/staging/media/imx/imx-media-capture.c | 97 |
1 files changed, 64 insertions, 33 deletions
diff --git a/drivers/staging/media/imx/imx-media-capture.c b/drivers/staging/media/imx/imx-media-capture.c index 9430c835c434..b33a07bc9105 100644 --- a/drivers/staging/media/imx/imx-media-capture.c +++ b/drivers/staging/media/imx/imx-media-capture.c @@ -202,6 +202,7 @@ static int capture_g_fmt_vid_cap(struct file *file, void *fh, static int __capture_try_fmt_vid_cap(struct capture_priv *priv, struct v4l2_subdev_format *fmt_src, struct v4l2_format *f, + const struct imx_media_pixfmt **retcc, struct v4l2_rect *compose) { const struct imx_media_pixfmt *cc, *cc_src; @@ -242,8 +243,17 @@ static int __capture_try_fmt_vid_cap(struct capture_priv *priv, } } - imx_media_mbus_fmt_to_pix_fmt(&f->fmt.pix, compose, - &fmt_src->format, cc); + imx_media_mbus_fmt_to_pix_fmt(&f->fmt.pix, &fmt_src->format, cc); + + if (retcc) + *retcc = cc; + + if (compose) { + compose->left = 0; + compose->top = 0; + compose->width = fmt_src->format.width; + compose->height = fmt_src->format.height; + } return 0; } @@ -261,7 +271,7 @@ static int capture_try_fmt_vid_cap(struct file *file, void *fh, if (ret) return ret; - return __capture_try_fmt_vid_cap(priv, &fmt_src, f, NULL); + return __capture_try_fmt_vid_cap(priv, &fmt_src, f, NULL, NULL); } static int capture_s_fmt_vid_cap(struct file *file, void *fh, @@ -269,7 +279,6 @@ static int capture_s_fmt_vid_cap(struct file *file, void *fh, { struct capture_priv *priv = video_drvdata(file); struct v4l2_subdev_format fmt_src; - struct v4l2_rect compose; int ret; if (vb2_is_busy(&priv->q)) { @@ -283,14 +292,12 @@ static int capture_s_fmt_vid_cap(struct file *file, void *fh, if (ret) return ret; - ret = __capture_try_fmt_vid_cap(priv, &fmt_src, f, &compose); + ret = __capture_try_fmt_vid_cap(priv, &fmt_src, f, &priv->vdev.cc, + &priv->vdev.compose); if (ret) return ret; priv->vdev.fmt.fmt.pix = f->fmt.pix; - priv->vdev.cc = imx_media_find_format(f->fmt.pix.pixelformat, - CS_SEL_ANY, true); - priv->vdev.compose = compose; return 0; } @@ -520,6 +527,33 @@ static void capture_buf_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&priv->q_lock, flags); } +static int capture_validate_fmt(struct capture_priv *priv) +{ + struct v4l2_subdev_format fmt_src; + const struct imx_media_pixfmt *cc; + struct v4l2_rect compose; + struct v4l2_format f; + int ret; + + fmt_src.pad = priv->src_sd_pad; + fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE; + ret = v4l2_subdev_call(priv->src_sd, pad, get_fmt, NULL, &fmt_src); + if (ret) + return ret; + + v4l2_fill_pix_format(&f.fmt.pix, &fmt_src.format); + + ret = __capture_try_fmt_vid_cap(priv, &fmt_src, &f, &cc, &compose); + if (ret) + return ret; + + return (priv->vdev.fmt.fmt.pix.width != f.fmt.pix.width || + priv->vdev.fmt.fmt.pix.height != f.fmt.pix.height || + priv->vdev.cc->cs != cc->cs || + priv->vdev.compose.width != compose.width || + priv->vdev.compose.height != compose.height) ? -EINVAL : 0; +} + static int capture_start_streaming(struct vb2_queue *vq, unsigned int count) { struct capture_priv *priv = vb2_get_drv_priv(vq); @@ -527,6 +561,12 @@ static int capture_start_streaming(struct vb2_queue *vq, unsigned int count) unsigned long flags; int ret; + ret = capture_validate_fmt(priv); + if (ret) { + v4l2_err(priv->src_sd, "capture format not valid\n"); + goto return_bufs; + } + ret = imx_media_pipeline_set_stream(priv->md, &priv->src_sd->entity, true); if (ret) { @@ -614,7 +654,6 @@ static int capture_release(struct file *file) struct capture_priv *priv = video_drvdata(file); struct video_device *vfd = priv->vdev.vfd; struct vb2_queue *vq = &priv->q; - int ret = 0; mutex_lock(&priv->mutex); @@ -627,7 +666,7 @@ static int capture_release(struct file *file) v4l2_fh_release(file); mutex_unlock(&priv->mutex); - return ret; + return 0; } static const struct v4l2_file_operations capture_fops = { @@ -649,21 +688,6 @@ static struct video_device capture_videodev = { .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING, }; -void imx_media_capture_device_set_format(struct imx_media_video_dev *vdev, - const struct v4l2_pix_format *pix, - const struct v4l2_rect *compose) -{ - struct capture_priv *priv = to_capture_priv(vdev); - - mutex_lock(&priv->mutex); - priv->vdev.fmt.fmt.pix = *pix; - priv->vdev.cc = imx_media_find_format(pix->pixelformat, CS_SEL_ANY, - true); - priv->vdev.compose = *compose; - mutex_unlock(&priv->mutex); -} -EXPORT_SYMBOL_GPL(imx_media_capture_device_set_format); - struct imx_media_buffer * imx_media_capture_device_next_buf(struct imx_media_video_dev *vdev) { @@ -701,19 +725,20 @@ void imx_media_capture_device_error(struct imx_media_video_dev *vdev) } EXPORT_SYMBOL_GPL(imx_media_capture_device_error); -int imx_media_capture_device_register(struct imx_media_dev *md, - struct imx_media_video_dev *vdev) +int imx_media_capture_device_register(struct imx_media_video_dev *vdev) { struct capture_priv *priv = to_capture_priv(vdev); struct v4l2_subdev *sd = priv->src_sd; + struct v4l2_device *v4l2_dev = sd->v4l2_dev; struct video_device *vfd = vdev->vfd; struct vb2_queue *vq = &priv->q; struct v4l2_subdev_format fmt_src; int ret; - priv->md = md; + /* get media device */ + priv->md = container_of(v4l2_dev->mdev, struct imx_media_dev, md); - vfd->v4l2_dev = sd->v4l2_dev; + vfd->v4l2_dev = v4l2_dev; ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); if (ret) { @@ -765,8 +790,10 @@ int imx_media_capture_device_register(struct imx_media_dev *md, } vdev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - imx_media_mbus_fmt_to_pix_fmt(&vdev->fmt.fmt.pix, &vdev->compose, + imx_media_mbus_fmt_to_pix_fmt(&vdev->fmt.fmt.pix, &fmt_src.format, NULL); + vdev->compose.width = fmt_src.format.width; + vdev->compose.height = fmt_src.format.height; vdev->cc = imx_media_find_format(vdev->fmt.fmt.pix.pixelformat, CS_SEL_ANY, false); @@ -775,6 +802,9 @@ int imx_media_capture_device_register(struct imx_media_dev *md, vfd->ctrl_handler = &priv->ctrl_hdlr; + /* add vdev to the video device list */ + imx_media_add_video_device(priv->md, vdev); + return 0; unreg: video_unregister_device(vfd); @@ -799,18 +829,19 @@ void imx_media_capture_device_unregister(struct imx_media_video_dev *vdev) EXPORT_SYMBOL_GPL(imx_media_capture_device_unregister); struct imx_media_video_dev * -imx_media_capture_device_init(struct v4l2_subdev *src_sd, int pad) +imx_media_capture_device_init(struct device *dev, struct v4l2_subdev *src_sd, + int pad) { struct capture_priv *priv; struct video_device *vfd; - priv = devm_kzalloc(src_sd->dev, sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return ERR_PTR(-ENOMEM); priv->src_sd = src_sd; priv->src_sd_pad = pad; - priv->dev = src_sd->dev; + priv->dev = dev; mutex_init(&priv->mutex); spin_lock_init(&priv->q_lock); |