[media] marvell-ccic: use vb2 helpers and core locking
[deliverable/linux.git] / drivers / media / platform / marvell-ccic / mcam-core.c
index dd5b1415f97444103835c677fc1cde879876fe8c..b6b838fd0af8c9f87e56504238f2e08d1699e8dd 100644 (file)
@@ -24,6 +24,7 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
 #include <media/ov7670.h>
 #include <media/videobuf2-vmalloc.h>
 #include <media/videobuf2-dma-contig.h>
@@ -188,6 +189,7 @@ static const struct v4l2_pix_format mcam_def_pix_format = {
        .field          = V4L2_FIELD_NONE,
        .bytesperline   = VGA_WIDTH*2,
        .sizeimage      = VGA_WIDTH*VGA_HEIGHT*2,
+       .colorspace     = V4L2_COLORSPACE_SRGB,
 };
 
 static const u32 mcam_def_mbus_code = MEDIA_BUS_FMT_YUYV8_2X8;
@@ -969,7 +971,6 @@ static int mcam_cam_init(struct mcam_camera *cam)
 {
        int ret;
 
-       mutex_lock(&cam->s_mutex);
        if (cam->state != S_NOTREADY)
                cam_warn(cam, "Cam init with device in funky state %d",
                                cam->state);
@@ -977,7 +978,6 @@ static int mcam_cam_init(struct mcam_camera *cam)
        /* Get/set parameters? */
        cam->state = S_IDLE;
        mcam_ctlr_power_down(cam);
-       mutex_unlock(&cam->s_mutex);
        return ret;
 }
 
@@ -1114,6 +1114,9 @@ static int mcam_vb_start_streaming(struct vb2_queue *vq, unsigned int count)
                INIT_LIST_HEAD(&cam->buffers);
                return -EINVAL;
        }
+       cam->frame_state.frames = 0;
+       cam->frame_state.singles = 0;
+       cam->frame_state.delivered = 0;
        cam->sequence = 0;
        /*
         * Videobuf2 sneakily hoards all the buffers and won't
@@ -1142,6 +1145,9 @@ static void mcam_vb_stop_streaming(struct vb2_queue *vq)
        struct mcam_camera *cam = vb2_get_drv_priv(vq);
        unsigned long flags;
 
+       cam_dbg(cam, "stop_streaming: %d frames, %d singles, %d delivered\n",
+                       cam->frame_state.frames, cam->frame_state.singles,
+                       cam->frame_state.delivered);
        if (cam->state == S_BUFWAIT) {
                /* They never gave us buffers */
                cam->state = S_IDLE;
@@ -1246,6 +1252,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
        vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        vq->drv_priv = cam;
        vq->lock = &cam->s_mutex;
+       vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
        INIT_LIST_HEAD(&cam->buffers);
        switch (cam->buffer_mode) {
        case B_DMA_contig:
@@ -1253,7 +1260,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
                vq->ops = &mcam_vb2_ops;
                vq->mem_ops = &vb2_dma_contig_memops;
                vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
-               vq->io_modes = VB2_MMAP | VB2_USERPTR;
+               vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
                cam->dma_setup = mcam_ctlr_dma_contig;
                cam->frame_complete = mcam_dma_contig_done;
                cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
@@ -1266,7 +1273,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
                vq->ops = &mcam_vb2_sg_ops;
                vq->mem_ops = &vb2_dma_sg_memops;
                vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
-               vq->io_modes = VB2_MMAP | VB2_USERPTR;
+               vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
                cam->dma_setup = mcam_ctlr_dma_sg;
                cam->frame_complete = mcam_dma_sg_done;
                cam->vb_alloc_ctx_sg = vb2_dma_sg_init_ctx(cam->dev);
@@ -1281,7 +1288,7 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
                vq->ops = &mcam_vb2_ops;
                vq->mem_ops = &vb2_vmalloc_memops;
                vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
-               vq->io_modes = VB2_MMAP;
+               vq->io_modes = VB2_MMAP | VB2_READ;
                cam->dma_setup = mcam_ctlr_dma_vmalloc;
                cam->frame_complete = mcam_vmalloc_done;
 #endif
@@ -1292,7 +1299,6 @@ static int mcam_setup_vb2(struct mcam_camera *cam)
 
 static void mcam_cleanup_vb2(struct mcam_camera *cam)
 {
-       vb2_queue_release(&cam->vb_queue);
 #ifdef MCAM_MODE_DMA_CONTIG
        if (cam->buffer_mode == B_DMA_contig)
                vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx);
@@ -1309,86 +1315,14 @@ static void mcam_cleanup_vb2(struct mcam_camera *cam)
  * The long list of V4L2 ioctl() operations.
  */
 
-static int mcam_vidioc_streamon(struct file *filp, void *priv,
-               enum v4l2_buf_type type)
-{
-       struct mcam_camera *cam = filp->private_data;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = vb2_streamon(&cam->vb_queue, type);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-
-static int mcam_vidioc_streamoff(struct file *filp, void *priv,
-               enum v4l2_buf_type type)
-{
-       struct mcam_camera *cam = filp->private_data;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = vb2_streamoff(&cam->vb_queue, type);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-
-static int mcam_vidioc_reqbufs(struct file *filp, void *priv,
-               struct v4l2_requestbuffers *req)
-{
-       struct mcam_camera *cam = filp->private_data;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = vb2_reqbufs(&cam->vb_queue, req);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-
-static int mcam_vidioc_querybuf(struct file *filp, void *priv,
-               struct v4l2_buffer *buf)
-{
-       struct mcam_camera *cam = filp->private_data;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = vb2_querybuf(&cam->vb_queue, buf);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-static int mcam_vidioc_qbuf(struct file *filp, void *priv,
-               struct v4l2_buffer *buf)
-{
-       struct mcam_camera *cam = filp->private_data;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = vb2_qbuf(&cam->vb_queue, buf);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-static int mcam_vidioc_dqbuf(struct file *filp, void *priv,
-               struct v4l2_buffer *buf)
-{
-       struct mcam_camera *cam = filp->private_data;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = vb2_dqbuf(&cam->vb_queue, buf, filp->f_flags & O_NONBLOCK);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
 static int mcam_vidioc_querycap(struct file *file, void *priv,
                struct v4l2_capability *cap)
 {
+       struct mcam_camera *cam = video_drvdata(file);
+
        strcpy(cap->driver, "marvell_ccic");
        strcpy(cap->card, "marvell_ccic");
+       strlcpy(cap->bus_info, cam->bus_info, sizeof(cap->bus_info));
        cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
                V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
        cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -1410,7 +1344,7 @@ static int mcam_vidioc_enum_fmt_vid_cap(struct file *filp,
 static int mcam_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
                struct v4l2_format *fmt)
 {
-       struct mcam_camera *cam = priv;
+       struct mcam_camera *cam = video_drvdata(filp);
        struct mcam_format_struct *f;
        struct v4l2_pix_format *pix = &fmt->fmt.pix;
        struct v4l2_mbus_framefmt mbus_fmt;
@@ -1419,9 +1353,7 @@ static int mcam_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
        f = mcam_find_format(pix->pixelformat);
        pix->pixelformat = f->pixelformat;
        v4l2_fill_mbus_format(&mbus_fmt, pix, f->mbus_code);
-       mutex_lock(&cam->s_mutex);
        ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt);
-       mutex_unlock(&cam->s_mutex);
        v4l2_fill_pix_format(pix, &mbus_fmt);
        switch (f->pixelformat) {
        case V4L2_PIX_FMT_YUV420:
@@ -1433,13 +1365,14 @@ static int mcam_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
                break;
        }
        pix->sizeimage = pix->height * pix->bytesperline;
+       pix->colorspace = V4L2_COLORSPACE_SRGB;
        return ret;
 }
 
 static int mcam_vidioc_s_fmt_vid_cap(struct file *filp, void *priv,
                struct v4l2_format *fmt)
 {
-       struct mcam_camera *cam = priv;
+       struct mcam_camera *cam = video_drvdata(filp);
        struct mcam_format_struct *f;
        int ret;
 
@@ -1462,7 +1395,6 @@ static int mcam_vidioc_s_fmt_vid_cap(struct file *filp, void *priv,
         * Now we start to change things for real, so let's do it
         * under lock.
         */
-       mutex_lock(&cam->s_mutex);
        cam->pix_format = fmt->fmt.pix;
        cam->mbus_code = f->mbus_code;
 
@@ -1476,7 +1408,6 @@ static int mcam_vidioc_s_fmt_vid_cap(struct file *filp, void *priv,
        }
        mcam_set_config_needed(cam, 1);
 out:
-       mutex_unlock(&cam->s_mutex);
        return ret;
 }
 
@@ -1488,7 +1419,7 @@ out:
 static int mcam_vidioc_g_fmt_vid_cap(struct file *filp, void *priv,
                struct v4l2_format *f)
 {
-       struct mcam_camera *cam = priv;
+       struct mcam_camera *cam = video_drvdata(filp);
 
        f->fmt.pix = cam->pix_format;
        return 0;
@@ -1504,7 +1435,6 @@ static int mcam_vidioc_enum_input(struct file *filp, void *priv,
                return -EINVAL;
 
        input->type = V4L2_INPUT_TYPE_CAMERA;
-       input->std = V4L2_STD_ALL; /* Not sure what should go here */
        strcpy(input->name, "Camera");
        return 0;
 }
@@ -1522,18 +1452,6 @@ static int mcam_vidioc_s_input(struct file *filp, void *priv, unsigned int i)
        return 0;
 }
 
-/* from vivi.c */
-static int mcam_vidioc_s_std(struct file *filp, void *priv, v4l2_std_id a)
-{
-       return 0;
-}
-
-static int mcam_vidioc_g_std(struct file *filp, void *priv, v4l2_std_id *a)
-{
-       *a = V4L2_STD_NTSC_M;
-       return 0;
-}
-
 /*
  * G/S_PARM.  Most of this is done by the sensor, but we are
  * the level which controls the number of read buffers.
@@ -1541,12 +1459,10 @@ static int mcam_vidioc_g_std(struct file *filp, void *priv, v4l2_std_id *a)
 static int mcam_vidioc_g_parm(struct file *filp, void *priv,
                struct v4l2_streamparm *parms)
 {
-       struct mcam_camera *cam = priv;
+       struct mcam_camera *cam = video_drvdata(filp);
        int ret;
 
-       mutex_lock(&cam->s_mutex);
        ret = sensor_call(cam, video, g_parm, parms);
-       mutex_unlock(&cam->s_mutex);
        parms->parm.capture.readbuffers = n_dma_bufs;
        return ret;
 }
@@ -1554,12 +1470,10 @@ static int mcam_vidioc_g_parm(struct file *filp, void *priv,
 static int mcam_vidioc_s_parm(struct file *filp, void *priv,
                struct v4l2_streamparm *parms)
 {
-       struct mcam_camera *cam = priv;
+       struct mcam_camera *cam = video_drvdata(filp);
        int ret;
 
-       mutex_lock(&cam->s_mutex);
        ret = sensor_call(cam, video, s_parm, parms);
-       mutex_unlock(&cam->s_mutex);
        parms->parm.capture.readbuffers = n_dma_bufs;
        return ret;
 }
@@ -1567,32 +1481,68 @@ static int mcam_vidioc_s_parm(struct file *filp, void *priv,
 static int mcam_vidioc_enum_framesizes(struct file *filp, void *priv,
                struct v4l2_frmsizeenum *sizes)
 {
-       struct mcam_camera *cam = priv;
+       struct mcam_camera *cam = video_drvdata(filp);
+       struct mcam_format_struct *f;
+       struct v4l2_subdev_frame_size_enum fse = {
+               .index = sizes->index,
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        int ret;
 
-       mutex_lock(&cam->s_mutex);
-       ret = sensor_call(cam, video, enum_framesizes, sizes);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
+       f = mcam_find_format(sizes->pixel_format);
+       if (f->pixelformat != sizes->pixel_format)
+               return -EINVAL;
+       fse.code = f->mbus_code;
+       ret = sensor_call(cam, pad, enum_frame_size, NULL, &fse);
+       if (ret)
+               return ret;
+       if (fse.min_width == fse.max_width &&
+           fse.min_height == fse.max_height) {
+               sizes->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+               sizes->discrete.width = fse.min_width;
+               sizes->discrete.height = fse.min_height;
+               return 0;
+       }
+       sizes->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
+       sizes->stepwise.min_width = fse.min_width;
+       sizes->stepwise.max_width = fse.max_width;
+       sizes->stepwise.min_height = fse.min_height;
+       sizes->stepwise.max_height = fse.max_height;
+       sizes->stepwise.step_width = 1;
+       sizes->stepwise.step_height = 1;
+       return 0;
 }
 
 static int mcam_vidioc_enum_frameintervals(struct file *filp, void *priv,
                struct v4l2_frmivalenum *interval)
 {
-       struct mcam_camera *cam = priv;
+       struct mcam_camera *cam = video_drvdata(filp);
+       struct mcam_format_struct *f;
+       struct v4l2_subdev_frame_interval_enum fie = {
+               .index = interval->index,
+               .width = interval->width,
+               .height = interval->height,
+               .which = V4L2_SUBDEV_FORMAT_ACTIVE,
+       };
        int ret;
 
-       mutex_lock(&cam->s_mutex);
-       ret = sensor_call(cam, video, enum_frameintervals, interval);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
+       f = mcam_find_format(interval->pixel_format);
+       if (f->pixelformat != interval->pixel_format)
+               return -EINVAL;
+       fie.code = f->mbus_code;
+       ret = sensor_call(cam, pad, enum_frame_interval, NULL, &fie);
+       if (ret)
+               return ret;
+       interval->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+       interval->discrete = fie.interval;
+       return 0;
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 static int mcam_vidioc_g_register(struct file *file, void *priv,
                struct v4l2_dbg_register *reg)
 {
-       struct mcam_camera *cam = priv;
+       struct mcam_camera *cam = video_drvdata(file);
 
        if (reg->reg > cam->regs_size - 4)
                return -EINVAL;
@@ -1604,7 +1554,7 @@ static int mcam_vidioc_g_register(struct file *file, void *priv,
 static int mcam_vidioc_s_register(struct file *file, void *priv,
                const struct v4l2_dbg_register *reg)
 {
-       struct mcam_camera *cam = priv;
+       struct mcam_camera *cam = video_drvdata(file);
 
        if (reg->reg > cam->regs_size - 4)
                return -EINVAL;
@@ -1622,18 +1572,18 @@ static const struct v4l2_ioctl_ops mcam_v4l_ioctl_ops = {
        .vidioc_enum_input      = mcam_vidioc_enum_input,
        .vidioc_g_input         = mcam_vidioc_g_input,
        .vidioc_s_input         = mcam_vidioc_s_input,
-       .vidioc_s_std           = mcam_vidioc_s_std,
-       .vidioc_g_std           = mcam_vidioc_g_std,
-       .vidioc_reqbufs         = mcam_vidioc_reqbufs,
-       .vidioc_querybuf        = mcam_vidioc_querybuf,
-       .vidioc_qbuf            = mcam_vidioc_qbuf,
-       .vidioc_dqbuf           = mcam_vidioc_dqbuf,
-       .vidioc_streamon        = mcam_vidioc_streamon,
-       .vidioc_streamoff       = mcam_vidioc_streamoff,
+       .vidioc_reqbufs         = vb2_ioctl_reqbufs,
+       .vidioc_querybuf        = vb2_ioctl_querybuf,
+       .vidioc_qbuf            = vb2_ioctl_qbuf,
+       .vidioc_dqbuf           = vb2_ioctl_dqbuf,
+       .vidioc_streamon        = vb2_ioctl_streamon,
+       .vidioc_streamoff       = vb2_ioctl_streamoff,
        .vidioc_g_parm          = mcam_vidioc_g_parm,
        .vidioc_s_parm          = mcam_vidioc_s_parm,
        .vidioc_enum_framesizes = mcam_vidioc_enum_framesizes,
        .vidioc_enum_frameintervals = mcam_vidioc_enum_frameintervals,
+       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .vidioc_g_register      = mcam_vidioc_g_register,
        .vidioc_s_register      = mcam_vidioc_s_register,
@@ -1647,43 +1597,36 @@ static const struct v4l2_ioctl_ops mcam_v4l_ioctl_ops = {
 static int mcam_v4l_open(struct file *filp)
 {
        struct mcam_camera *cam = video_drvdata(filp);
-       int ret = 0;
-
-       filp->private_data = cam;
+       int ret;
 
-       cam->frame_state.frames = 0;
-       cam->frame_state.singles = 0;
-       cam->frame_state.delivered = 0;
        mutex_lock(&cam->s_mutex);
-       if (cam->users == 0) {
-               ret = mcam_setup_vb2(cam);
-               if (ret)
-                       goto out;
+       ret = v4l2_fh_open(filp);
+       if (ret)
+               goto out;
+       if (v4l2_fh_is_singular_file(filp)) {
                ret = mcam_ctlr_power_up(cam);
                if (ret)
                        goto out;
                __mcam_cam_reset(cam);
                mcam_set_config_needed(cam, 1);
        }
-       (cam->users)++;
 out:
        mutex_unlock(&cam->s_mutex);
+       if (ret)
+               v4l2_fh_release(filp);
        return ret;
 }
 
 
 static int mcam_v4l_release(struct file *filp)
 {
-       struct mcam_camera *cam = filp->private_data;
+       struct mcam_camera *cam = video_drvdata(filp);
+       bool last_open;
 
-       cam_dbg(cam, "Release, %d frames, %d singles, %d delivered\n",
-                       cam->frame_state.frames, cam->frame_state.singles,
-                       cam->frame_state.delivered);
        mutex_lock(&cam->s_mutex);
-       (cam->users)--;
-       if (cam->users == 0) {
-               mcam_ctlr_stop_dma(cam);
-               mcam_cleanup_vb2(cam);
+       last_open = v4l2_fh_is_singular_file(filp);
+       _vb2_fop_release(filp, NULL);
+       if (last_open) {
                mcam_disable_mipi(cam);
                mcam_ctlr_power_down(cam);
                if (cam->buffer_mode == B_vmalloc && alloc_bufs_at_read)
@@ -1694,54 +1637,13 @@ static int mcam_v4l_release(struct file *filp)
        return 0;
 }
 
-static ssize_t mcam_v4l_read(struct file *filp,
-               char __user *buffer, size_t len, loff_t *pos)
-{
-       struct mcam_camera *cam = filp->private_data;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = vb2_read(&cam->vb_queue, buffer, len, pos,
-                       filp->f_flags & O_NONBLOCK);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-
-
-static unsigned int mcam_v4l_poll(struct file *filp,
-               struct poll_table_struct *pt)
-{
-       struct mcam_camera *cam = filp->private_data;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = vb2_poll(&cam->vb_queue, filp, pt);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-
-static int mcam_v4l_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-       struct mcam_camera *cam = filp->private_data;
-       int ret;
-
-       mutex_lock(&cam->s_mutex);
-       ret = vb2_mmap(&cam->vb_queue, vma);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
-}
-
-
-
 static const struct v4l2_file_operations mcam_v4l_fops = {
        .owner = THIS_MODULE,
        .open = mcam_v4l_open,
        .release = mcam_v4l_release,
-       .read = mcam_v4l_read,
-       .poll = mcam_v4l_poll,
-       .mmap = mcam_v4l_mmap,
+       .read = vb2_fop_read,
+       .poll = vb2_fop_poll,
+       .mmap = vb2_fop_mmap,
        .unlocked_ioctl = video_ioctl2,
 };
 
@@ -1752,8 +1654,6 @@ static const struct v4l2_file_operations mcam_v4l_fops = {
  */
 static struct video_device mcam_v4l_template = {
        .name = "mcam",
-       .tvnorms = V4L2_STD_NTSC_M,
-
        .fops = &mcam_v4l_fops,
        .ioctl_ops = &mcam_v4l_ioctl_ops,
        .release = video_device_release_empty,
@@ -1887,6 +1787,14 @@ int mccic_register(struct mcam_camera *cam)
        INIT_LIST_HEAD(&cam->buffers);
        mcam_ctlr_init(cam);
 
+       /*
+        * Get the v4l2 setup done.
+        */
+       ret = v4l2_ctrl_handler_init(&cam->ctrl_handler, 10);
+       if (ret)
+               goto out_unregister;
+       cam->v4l2_dev.ctrl_handler = &cam->ctrl_handler;
+
        /*
         * Try to find the sensor.
         */
@@ -1903,21 +1811,22 @@ int mccic_register(struct mcam_camera *cam)
        ret = mcam_cam_init(cam);
        if (ret)
                goto out_unregister;
-       /*
-        * Get the v4l2 setup done.
-        */
-       ret = v4l2_ctrl_handler_init(&cam->ctrl_handler, 10);
+
+       ret = mcam_setup_vb2(cam);
        if (ret)
                goto out_unregister;
-       cam->v4l2_dev.ctrl_handler = &cam->ctrl_handler;
 
        mutex_lock(&cam->s_mutex);
        cam->vdev = mcam_v4l_template;
        cam->vdev.v4l2_dev = &cam->v4l2_dev;
+       cam->vdev.lock = &cam->s_mutex;
+       cam->vdev.queue = &cam->vb_queue;
        video_set_drvdata(&cam->vdev, cam);
        ret = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
-       if (ret)
-               goto out;
+       if (ret) {
+               mutex_unlock(&cam->s_mutex);
+               goto out_unregister;
+       }
 
        /*
         * If so requested, try to get our DMA buffers now.
@@ -1928,11 +1837,11 @@ int mccic_register(struct mcam_camera *cam)
                                        " will try again later.");
        }
 
-out:
-       v4l2_ctrl_handler_free(&cam->ctrl_handler);
        mutex_unlock(&cam->s_mutex);
-       return ret;
+       return 0;
+
 out_unregister:
+       v4l2_ctrl_handler_free(&cam->ctrl_handler);
        v4l2_device_unregister(&cam->v4l2_dev);
        return ret;
 }
@@ -1946,11 +1855,11 @@ void mccic_shutdown(struct mcam_camera *cam)
         * take it down again will wedge the machine, which is frowned
         * upon.
         */
-       if (cam->users > 0) {
+       if (!list_empty(&cam->vdev.fh_list)) {
                cam_warn(cam, "Removing a device with users!\n");
                mcam_ctlr_power_down(cam);
        }
-       vb2_queue_release(&cam->vb_queue);
+       mcam_cleanup_vb2(cam);
        if (cam->buffer_mode == B_vmalloc)
                mcam_free_dma_bufs(cam);
        video_unregister_device(&cam->vdev);
@@ -1966,7 +1875,7 @@ void mccic_shutdown(struct mcam_camera *cam)
 void mccic_suspend(struct mcam_camera *cam)
 {
        mutex_lock(&cam->s_mutex);
-       if (cam->users > 0) {
+       if (!list_empty(&cam->vdev.fh_list)) {
                enum mcam_state cstate = cam->state;
 
                mcam_ctlr_stop_dma(cam);
@@ -1981,7 +1890,7 @@ int mccic_resume(struct mcam_camera *cam)
        int ret = 0;
 
        mutex_lock(&cam->s_mutex);
-       if (cam->users > 0) {
+       if (!list_empty(&cam->vdev.fh_list)) {
                ret = mcam_ctlr_power_up(cam);
                if (ret) {
                        mutex_unlock(&cam->s_mutex);
This page took 0.032859 seconds and 5 git commands to generate.