OSDN Git Service

msm: camera: Return HAL buffer to fix drain issues
authorHariram Purushothaman <hariramp@codeaurora.org>
Tue, 29 Mar 2016 21:05:56 +0000 (14:05 -0700)
committerKyle Yan <kyan@codeaurora.org>
Wed, 6 Jul 2016 22:43:27 +0000 (15:43 -0700)
Return the HAL buffer to avoid drain issue
and provide the get buf by index interface so clients
can get buffer based on index.

CRs-Fixed: 1018651
Change-Id: I20329a6834f5f1498388c39b1dd95db2896b3239
Signed-off-by: Hariram Purushothaman <hariramp@codeaurora.org>
drivers/media/platform/msm/camera_v2/camera/camera.c
drivers/media/platform/msm/camera_v2/fd/Makefile
drivers/media/platform/msm/camera_v2/msm.c
drivers/media/platform/msm/camera_v2/msm.h
drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h
drivers/media/platform/msm/camera_v2/msm_sd.h
drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
include/uapi/media/msmb_camera.h
include/uapi/media/msmb_generic_buf_mgr.h

index 60a8345..c1aeb8c 100644 (file)
@@ -475,6 +475,38 @@ static int camera_v4l2_unsubscribe_event(struct v4l2_fh *fh,
        return rc;
 }
 
+static long camera_v4l2_vidioc_private_ioctl(struct file *filep, void *fh,
+       bool valid_prio, unsigned int cmd, void *arg)
+{
+       struct camera_v4l2_private *sp = fh_to_private(fh);
+       struct msm_video_device *pvdev = video_drvdata(filep);
+       struct msm_camera_private_ioctl_arg *k_ioctl = arg;
+       long rc = -EINVAL;
+
+       if (WARN_ON(!k_ioctl || !pvdev))
+               return -EIO;
+
+       switch (k_ioctl->id) {
+       case MSM_CAMERA_PRIV_IOCTL_ID_RETURN_BUF: {
+               struct msm_camera_return_buf ptr, *tmp = NULL;
+
+               MSM_CAM_GET_IOCTL_ARG_PTR(&tmp, &k_ioctl->ioctl_ptr,
+                       sizeof(tmp));
+               if (copy_from_user(&ptr, tmp,
+                       sizeof(struct msm_camera_return_buf))) {
+                       return -EFAULT;
+               }
+               rc = msm_vb2_return_buf_by_idx(pvdev->vdev->num, sp->stream_id,
+                       ptr.index);
+               }
+               break;
+       default:
+               pr_debug("unimplemented id %d", k_ioctl->id);
+               return -EINVAL;
+       }
+       return rc;
+}
+
 static const struct v4l2_ioctl_ops camera_v4l2_ioctl_ops = {
        .vidioc_querycap = camera_v4l2_querycap,
        .vidioc_s_crop = camera_v4l2_s_crop,
@@ -499,6 +531,7 @@ static const struct v4l2_ioctl_ops camera_v4l2_ioctl_ops = {
        /* event subscribe/unsubscribe */
        .vidioc_subscribe_event = camera_v4l2_subscribe_event,
        .vidioc_unsubscribe_event = camera_v4l2_unsubscribe_event,
+       .vidioc_default = camera_v4l2_vidioc_private_ioctl,
 };
 
 static int camera_v4l2_fh_open(struct file *filep)
@@ -747,10 +780,62 @@ static int camera_v4l2_close(struct file *filep)
 }
 
 #ifdef CONFIG_COMPAT
+static long camera_handle_internal_compat_ioctl(struct file *file,
+               unsigned int cmd, unsigned long arg)
+{
+       long rc = 0;
+       struct msm_camera_private_ioctl_arg k_ioctl;
+       void __user *tmp_compat_ioctl_ptr = NULL;
+
+       rc = msm_copy_camera_private_ioctl_args(arg,
+               &k_ioctl, &tmp_compat_ioctl_ptr);
+       if (rc < 0) {
+               pr_err("Subdev cmd %d failed\n", cmd);
+               return rc;
+       }
+       switch (k_ioctl.id) {
+       case MSM_CAMERA_PRIV_IOCTL_ID_RETURN_BUF: {
+               if (k_ioctl.size != sizeof(struct msm_camera_return_buf)) {
+                       pr_debug("Invalid size for id %d with size %d",
+                               k_ioctl.id, k_ioctl.size);
+                       return -EINVAL;
+               }
+               k_ioctl.ioctl_ptr = (__u64)tmp_compat_ioctl_ptr;
+               if (!k_ioctl.ioctl_ptr) {
+                       pr_debug("Invalid ptr for id %d", k_ioctl.id);
+                       return -EINVAL;
+               }
+               rc = camera_v4l2_vidioc_private_ioctl(file, file->private_data,
+                       0, cmd, (void *)&k_ioctl);
+               }
+               break;
+       default:
+               pr_debug("unimplemented id %d", k_ioctl.id);
+               return -EINVAL;
+       }
+       return rc;
+}
+
 long camera_v4l2_compat_ioctl(struct file *file, unsigned int cmd,
        unsigned long arg)
 {
-       return -ENOIOCTLCMD;
+       long ret = 0;
+
+       switch (cmd) {
+       case VIDIOC_MSM_CAMERA_PRIVATE_IOCTL_CMD: {
+               ret = camera_handle_internal_compat_ioctl(file, cmd, arg);
+               if (ret < 0) {
+                       pr_debug("Subdev cmd %d fail\n", cmd);
+                       return ret;
+               }
+               }
+               break;
+       default:
+               ret = -ENOIOCTLCMD;
+               break;
+
+       }
+       return ret;
 }
 #endif
 static struct v4l2_file_operations camera_v4l2_fops = {
index 82b37a7..8d01d3a 100644 (file)
@@ -1,5 +1,8 @@
 GCC_VERSION      := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
 ccflags-y += -Idrivers/media/video/msm
 ccflags-y += -Idrivers/media/platform/msm/camera_v2/common
+ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/pproc/cpp
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/msm_buf_mgr/
 
 obj-$(CONFIG_MSM_FD) += msm_fd_dev.o msm_fd_hw.o
index a34dbb8..c6dc4b7 100644 (file)
@@ -1099,6 +1099,28 @@ struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q)
 }
 EXPORT_SYMBOL(msm_get_stream_from_vb2q);
 
+#ifdef CONFIG_COMPAT
+long msm_copy_camera_private_ioctl_args(unsigned long arg,
+       struct msm_camera_private_ioctl_arg *k_ioctl,
+       void __user **tmp_compat_ioctl_ptr)
+{
+       struct msm_camera_private_ioctl_arg *up_ioctl_ptr =
+               (struct msm_camera_private_ioctl_arg *)arg;
+
+       if (WARN_ON(!arg || !k_ioctl || !tmp_compat_ioctl_ptr))
+               return -EIO;
+
+       k_ioctl->id = up_ioctl_ptr->id;
+       k_ioctl->size = up_ioctl_ptr->size;
+       k_ioctl->result = up_ioctl_ptr->result;
+       k_ioctl->reserved = up_ioctl_ptr->reserved;
+       *tmp_compat_ioctl_ptr = compat_ptr(up_ioctl_ptr->ioctl_ptr);
+
+       return 0;
+}
+EXPORT_SYMBOL(msm_copy_camera_private_ioctl_args);
+#endif
+
 static void msm_sd_notify(struct v4l2_subdev *sd,
        unsigned int notification, void *arg)
 {
index cab07df..2b3576b 100644 (file)
@@ -133,4 +133,9 @@ struct vb2_queue *msm_get_stream_vb2q(unsigned int session_id,
        unsigned int stream_id);
 struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q);
 struct msm_session *msm_session_find(unsigned int session_id);
+#ifdef CONFIG_COMPAT
+long msm_copy_camera_private_ioctl_args(unsigned long arg,
+       struct msm_camera_private_ioctl_arg *k_ioctl,
+       void __user **tmp_compat_ioctl_ptr);
+#endif
 #endif /*_MSM_H */
index b6cbdcc..ac9a4b2 100644 (file)
@@ -48,6 +48,7 @@ static int32_t msm_buf_mngr_hdl_cont_get_buf(struct msm_buf_mngr_device *dev,
        }
        return 0;
 }
+
 static int32_t msm_buf_mngr_get_buf(struct msm_buf_mngr_device *dev,
        void __user *argp)
 {
@@ -91,6 +92,52 @@ static int32_t msm_buf_mngr_get_buf(struct msm_buf_mngr_device *dev,
        return rc;
 }
 
+static int32_t msm_buf_mngr_get_buf_by_idx(struct msm_buf_mngr_device *dev,
+       void *argp)
+{
+       unsigned long flags;
+       int32_t rc = 0;
+       struct msm_buf_mngr_info *buf_info =
+               (struct msm_buf_mngr_info *)argp;
+       struct msm_get_bufs *new_entry =
+               kzalloc(sizeof(struct msm_get_bufs), GFP_KERNEL);
+
+       if (!new_entry)
+               return -ENOMEM;
+
+       if (!buf_info) {
+               kfree(new_entry);
+               return -EIO;
+       }
+
+       INIT_LIST_HEAD(&new_entry->entry);
+       new_entry->vb2_v4l2_buf = dev->vb2_ops.get_buf_by_idx(
+               buf_info->session_id, buf_info->stream_id, buf_info->index);
+       if (!new_entry->vb2_v4l2_buf) {
+               pr_debug("%s:Get buf is null\n", __func__);
+               kfree(new_entry);
+               return -EINVAL;
+       }
+       new_entry->session_id = buf_info->session_id;
+       new_entry->stream_id = buf_info->stream_id;
+       new_entry->index = new_entry->vb2_v4l2_buf->vb2_buf.index;
+       spin_lock_irqsave(&dev->buf_q_spinlock, flags);
+       list_add_tail(&new_entry->entry, &dev->buf_qhead);
+       spin_unlock_irqrestore(&dev->buf_q_spinlock, flags);
+       if (buf_info->type == MSM_CAMERA_BUF_MNGR_BUF_USER) {
+               mutex_lock(&dev->cont_mutex);
+               if (!list_empty(&dev->cont_qhead)) {
+                       rc = msm_buf_mngr_hdl_cont_get_buf(dev, buf_info);
+               } else {
+                       pr_err("Nothing mapped in user buf for %d,%d\n",
+                               buf_info->session_id, buf_info->stream_id);
+                       rc = -EINVAL;
+               }
+               mutex_unlock(&dev->cont_mutex);
+       }
+       return rc;
+}
+
 static int32_t msm_buf_mngr_buf_done(struct msm_buf_mngr_device *buf_mngr_dev,
        struct msm_buf_mngr_info *buf_info)
 {
@@ -413,6 +460,67 @@ static int msm_generic_buf_mngr_close(struct v4l2_subdev *sd,
        return rc;
 }
 
+int msm_cam_buf_mgr_ops(unsigned int cmd, void *argp)
+{
+       int rc = 0;
+
+       if (!msm_buf_mngr_dev)
+               return -ENODEV;
+       if (!argp)
+               return -EINVAL;
+
+       switch (cmd) {
+       case VIDIOC_MSM_BUF_MNGR_GET_BUF:
+               rc = msm_buf_mngr_get_buf(msm_buf_mngr_dev, argp);
+               break;
+       case VIDIOC_MSM_BUF_MNGR_BUF_DONE:
+               rc = msm_buf_mngr_buf_done(msm_buf_mngr_dev, argp);
+               break;
+       case VIDIOC_MSM_BUF_MNGR_PUT_BUF:
+               rc = msm_buf_mngr_put_buf(msm_buf_mngr_dev, argp);
+               break;
+       case VIDIOC_MSM_BUF_MNGR_IOCTL_CMD: {
+               struct msm_camera_private_ioctl_arg *k_ioctl = argp;
+
+               switch (k_ioctl->id) {
+               case MSM_CAMERA_BUF_MNGR_IOCTL_ID_GET_BUF_BY_IDX: {
+                       struct msm_buf_mngr_info *tmp = NULL;
+
+                       if (!k_ioctl->ioctl_ptr)
+                               return -EINVAL;
+                       if (k_ioctl->size != sizeof(struct msm_buf_mngr_info))
+                               return -EINVAL;
+
+                       MSM_CAM_GET_IOCTL_ARG_PTR(&tmp, &k_ioctl->ioctl_ptr,
+                               sizeof(tmp));
+                       rc = msm_buf_mngr_get_buf_by_idx(msm_buf_mngr_dev,
+                               tmp);
+                       }
+                       break;
+               default:
+                       pr_debug("unimplemented id %d", k_ioctl->id);
+                       return -EINVAL;
+               }
+       break;
+       }
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       return rc;
+}
+
+int msm_cam_buf_mgr_register_ops(struct msm_cam_buf_mgr_req_ops *cb_struct)
+{
+       if (!msm_buf_mngr_dev)
+               return -ENODEV;
+       if (!cb_struct)
+               return -EINVAL;
+
+       cb_struct->msm_cam_buf_mgr_ops = msm_cam_buf_mgr_ops;
+       return 0;
+}
+
 static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd,
        unsigned int cmd, void *arg)
 {
@@ -425,16 +533,45 @@ static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd,
                rc = -ENOMEM;
                return rc;
        }
-
        switch (cmd) {
-       case VIDIOC_MSM_BUF_MNGR_GET_BUF:
-               rc = msm_buf_mngr_get_buf(buf_mngr_dev, argp);
+       case VIDIOC_MSM_BUF_MNGR_IOCTL_CMD: {
+               struct msm_camera_private_ioctl_arg k_ioctl, *ptr;
+
+               if (!arg)
+                       return -EINVAL;
+               ptr = arg;
+               k_ioctl = *ptr;
+               switch (k_ioctl.id) {
+               case MSM_CAMERA_BUF_MNGR_IOCTL_ID_GET_BUF_BY_IDX: {
+                       struct msm_buf_mngr_info buf_info, *tmp = NULL;
+
+                       if (k_ioctl.size != sizeof(struct msm_buf_mngr_info))
+                               return -EINVAL;
+                       if (!k_ioctl.ioctl_ptr)
+                               return -EINVAL;
+
+                       MSM_CAM_GET_IOCTL_ARG_PTR(&tmp, &k_ioctl.ioctl_ptr,
+                               sizeof(tmp));
+                       if (copy_from_user(&buf_info, tmp,
+                               sizeof(struct msm_buf_mngr_info))) {
+                               return -EFAULT;
+                       }
+                       MSM_CAM_GET_IOCTL_ARG_PTR(&k_ioctl.ioctl_ptr,
+                               &buf_info, sizeof(void *));
+                       argp = &k_ioctl;
+                       rc = msm_cam_buf_mgr_ops(cmd, argp);
+                       }
+                       break;
+               default:
+                       pr_debug("unimplemented id %d", k_ioctl.id);
+                       return -EINVAL;
+               }
                break;
+       }
+       case VIDIOC_MSM_BUF_MNGR_GET_BUF:
        case VIDIOC_MSM_BUF_MNGR_BUF_DONE:
-               rc = msm_buf_mngr_buf_done(buf_mngr_dev, argp);
-               break;
        case VIDIOC_MSM_BUF_MNGR_PUT_BUF:
-               rc = msm_buf_mngr_put_buf(buf_mngr_dev, argp);
+               rc = msm_cam_buf_mgr_ops(cmd, argp);
                break;
        case VIDIOC_MSM_BUF_MNGR_INIT:
                rc = msm_generic_buf_mngr_open(sd, NULL);
@@ -462,6 +599,107 @@ static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd,
 }
 
 #ifdef CONFIG_COMPAT
+static long msm_camera_buf_mgr_fetch_buf_info(
+               struct msm_buf_mngr_info32_t *buf_info32,
+               struct msm_buf_mngr_info *buf_info, unsigned long arg)
+{
+       if (!arg || !buf_info32 || !buf_info)
+               return -EINVAL;
+
+       if (copy_from_user(buf_info32, (void __user *)arg,
+                               sizeof(struct msm_buf_mngr_info32_t)))
+               return -EFAULT;
+
+       buf_info->session_id = buf_info32->session_id;
+       buf_info->stream_id = buf_info32->stream_id;
+       buf_info->frame_id = buf_info32->frame_id;
+       buf_info->index = buf_info32->index;
+       buf_info->timestamp.tv_sec = (long) buf_info32->timestamp.tv_sec;
+       buf_info->timestamp.tv_usec = (long) buf_info32->
+                                       timestamp.tv_usec;
+       buf_info->reserved = buf_info32->reserved;
+       buf_info->type = buf_info32->type;
+       return 0;
+}
+
+static long msm_camera_buf_mgr_update_buf_info(
+               struct msm_buf_mngr_info32_t *buf_info32,
+               struct msm_buf_mngr_info *buf_info, unsigned long arg)
+{
+       if (!arg || !buf_info32 || !buf_info)
+               return -EINVAL;
+
+       buf_info32->session_id = buf_info->session_id;
+       buf_info32->stream_id = buf_info->stream_id;
+       buf_info32->index = buf_info->index;
+       buf_info32->timestamp.tv_sec = (int32_t) buf_info->
+                                               timestamp.tv_sec;
+       buf_info32->timestamp.tv_usec = (int32_t) buf_info->timestamp.
+                                               tv_usec;
+       buf_info32->reserved = buf_info->reserved;
+       buf_info32->type = buf_info->type;
+       buf_info32->user_buf.buf_cnt = buf_info->user_buf.buf_cnt;
+       memcpy(&buf_info32->user_buf.buf_idx,
+               &buf_info->user_buf.buf_idx,
+               sizeof(buf_info->user_buf.buf_idx));
+       if (copy_to_user((void __user *)arg, buf_info32,
+                       sizeof(struct msm_buf_mngr_info32_t)))
+               return -EFAULT;
+       return 0;
+}
+static long msm_camera_buf_mgr_internal_compat_ioctl(struct file *file,
+               unsigned int cmd, unsigned long arg)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
+       long rc = 0;
+       struct msm_camera_private_ioctl_arg k_ioctl;
+       void __user *tmp_compat_ioctl_ptr = NULL;
+
+       rc = msm_copy_camera_private_ioctl_args(arg,
+               &k_ioctl, &tmp_compat_ioctl_ptr);
+       if (rc < 0) {
+               pr_err("Subdev cmd %d failed\n", cmd);
+               return rc;
+       }
+
+       switch (k_ioctl.id) {
+       case MSM_CAMERA_BUF_MNGR_IOCTL_ID_GET_BUF_BY_IDX: {
+               struct msm_buf_mngr_info32_t buf_info32;
+               struct msm_buf_mngr_info buf_info;
+
+               if (k_ioctl.size != sizeof(struct msm_buf_mngr_info32_t)) {
+                       pr_err("Invalid size for id %d with size %d",
+                               k_ioctl.id, k_ioctl.size);
+                       return -EINVAL;
+               }
+               if (!tmp_compat_ioctl_ptr) {
+                       pr_err("Invalid ptr for id %d", k_ioctl.id);
+                       return -EINVAL;
+               }
+               k_ioctl.ioctl_ptr = (__u64)&buf_info;
+               rc = msm_camera_buf_mgr_fetch_buf_info(&buf_info32, &buf_info,
+                       (unsigned long)tmp_compat_ioctl_ptr);
+               if (rc < 0) {
+                       pr_err("Fetch buf info failed for cmd=%d", cmd);
+                       return rc;
+               }
+               rc = v4l2_subdev_call(sd, core, ioctl, cmd, &k_ioctl);
+               if (rc < 0) {
+                       pr_err("Subdev cmd %d failed for id %d", cmd,
+                               k_ioctl.id);
+                       return rc;
+               }
+               }
+               break;
+       default:
+               pr_debug("unimplemented id %d", k_ioctl.id);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static long msm_bmgr_subdev_fops_compat_ioctl(struct file *file,
                unsigned int cmd, unsigned long arg)
 {
@@ -469,8 +707,6 @@ static long msm_bmgr_subdev_fops_compat_ioctl(struct file *file,
        struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
        int32_t rc = 0;
 
-       void __user *up = (void __user *)arg;
-
        /* Convert 32 bit IOCTL ID's to 64 bit IOCTL ID's
         * except VIDIOC_MSM_CPP_CFG32, which needs special
         * processing
@@ -486,13 +722,14 @@ static long msm_bmgr_subdev_fops_compat_ioctl(struct file *file,
                cmd = VIDIOC_MSM_BUF_MNGR_PUT_BUF;
                break;
        case VIDIOC_MSM_BUF_MNGR_CONT_CMD:
-               cmd = VIDIOC_MSM_BUF_MNGR_CONT_CMD;
                break;
        case VIDIOC_MSM_BUF_MNGR_FLUSH32:
                cmd = VIDIOC_MSM_BUF_MNGR_FLUSH;
                break;
+       case VIDIOC_MSM_BUF_MNGR_IOCTL_CMD:
+               break;
        default:
-               pr_debug("%s : unsupported compat type", __func__);
+               pr_debug("unsupported compat type\n");
                return -ENOIOCTLCMD;
        }
 
@@ -504,65 +741,51 @@ static long msm_bmgr_subdev_fops_compat_ioctl(struct file *file,
                struct msm_buf_mngr_info32_t buf_info32;
                struct msm_buf_mngr_info buf_info;
 
-               if (copy_from_user(&buf_info32, (void __user *)up,
-                                       sizeof(struct msm_buf_mngr_info32_t)))
-                       return -EFAULT;
-
-               buf_info.session_id = buf_info32.session_id;
-               buf_info.stream_id = buf_info32.stream_id;
-               buf_info.frame_id = buf_info32.frame_id;
-               buf_info.index = buf_info32.index;
-               buf_info.timestamp.tv_sec = (long) buf_info32.timestamp.tv_sec;
-               buf_info.timestamp.tv_usec = (long) buf_info32.
-                                               timestamp.tv_usec;
-               buf_info.reserved = buf_info32.reserved;
-               buf_info.type = buf_info32.type;
-
+               rc = msm_camera_buf_mgr_fetch_buf_info(&buf_info32, &buf_info,
+                       arg);
+               if (rc < 0) {
+                       pr_err("Fetch buf info failed for cmd=%d\n", cmd);
+                       return rc;
+               }
                rc = v4l2_subdev_call(sd, core, ioctl, cmd, &buf_info);
                if (rc < 0) {
-                       pr_debug("%s : Subdev cmd %d fail", __func__, cmd);
+                       pr_debug("Subdev cmd %d fail\n", cmd);
+                       return rc;
+               }
+               rc = msm_camera_buf_mgr_update_buf_info(&buf_info32, &buf_info,
+                       arg);
+               if (rc < 0) {
+                       pr_err("Update buf info failed for cmd=%d\n", cmd);
+                       return rc;
+               }
+               break;
+       }
+       case VIDIOC_MSM_BUF_MNGR_IOCTL_CMD: {
+               rc = msm_camera_buf_mgr_internal_compat_ioctl(file, cmd, arg);
+               if (rc < 0) {
+                       pr_debug("Subdev cmd %d fail\n", cmd);
                        return rc;
                }
-
-               buf_info32.session_id = buf_info.session_id;
-               buf_info32.stream_id = buf_info.stream_id;
-               buf_info32.index = buf_info.index;
-               buf_info32.timestamp.tv_sec = (int32_t) buf_info.
-                                                       timestamp.tv_sec;
-               buf_info32.timestamp.tv_usec = (int32_t) buf_info.timestamp.
-                                                       tv_usec;
-               buf_info32.reserved = buf_info.reserved;
-               buf_info32.type = buf_info.type;
-               buf_info32.user_buf.buf_cnt = buf_info.user_buf.buf_cnt;
-               memcpy(&buf_info32.user_buf.buf_idx,
-                       &buf_info.user_buf.buf_idx,
-                       sizeof(buf_info.user_buf.buf_idx));
-               if (copy_to_user((void __user *)up, &buf_info32,
-                               sizeof(struct msm_buf_mngr_info32_t)))
-                       return -EFAULT;
                }
                break;
        case VIDIOC_MSM_BUF_MNGR_CONT_CMD: {
                struct msm_buf_mngr_main_cont_info cont_cmd;
 
-               if (copy_from_user(&cont_cmd, (void __user *)up,
+               if (copy_from_user(&cont_cmd, (void __user *)arg,
                        sizeof(struct msm_buf_mngr_main_cont_info)))
                        return -EFAULT;
                rc = v4l2_subdev_call(sd, core, ioctl, cmd, &cont_cmd);
                if (rc < 0) {
-                       pr_debug("%s : Subdev cmd %d fail", __func__, cmd);
+                       pr_debug("Subdev cmd %d fail\n", cmd);
                        return rc;
                }
                }
                break;
        default:
-               pr_debug("%s : unsupported compat type", __func__);
+               pr_debug("unsupported compat type\n");
                return -ENOIOCTLCMD;
                break;
        }
-
-
-
        return 0;
 }
 #endif
index dc7f745..c2f1a15 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -52,4 +52,14 @@ struct msm_buf_mngr_user_buf_cont_info {
        uint32_t cnt;
        struct ion_handle *ion_handle;
 };
+
+/* kernel space functions*/
+struct msm_cam_buf_mgr_req_ops {
+       int (*msm_cam_buf_mgr_ops)(unsigned int cmd, void *argp);
+};
+
+/* API to register callback from client. This assumes cb_struct is allocated by
+ * client.
+ */
+int msm_cam_buf_mgr_register_ops(struct msm_cam_buf_mgr_req_ops *cb_struct);
 #endif
index 6bb95ad..d893d9f 100644 (file)
@@ -73,6 +73,8 @@ struct msm_sd_req_vb2_q {
                unsigned int stream_id);
        struct vb2_queue * (*get_vb2_queue)(int session_id,
                unsigned int stream_id);
+       struct vb2_v4l2_buffer * (*get_buf_by_idx)(int session_id,
+               unsigned int stream_id, uint32_t index);
        int (*put_buf)(struct vb2_v4l2_buffer *vb2_buf, int session_id,
                unsigned int stream_id);
        int (*buf_done)(struct vb2_v4l2_buffer *vb2_v4l2_buf, int session_id,
@@ -85,6 +87,9 @@ struct msm_sd_req_vb2_q {
 #define MSM_SD_NOTIFY_PUT_SD 0x00000002
 #define MSM_SD_NOTIFY_REQ_CB 0x00000003
 
+#define MSM_CAM_GET_IOCTL_ARG_PTR(ptr, \
+       ioctl_ptr, len) memcpy(ptr, ioctl_ptr, len)
+
 int msm_sd_register(struct msm_sd_subdev *msm_subdev);
 int msm_sd_unregister(struct msm_sd_subdev *sd);
 struct v4l2_subdev *msm_sd_get_subdev(struct v4l2_subdev *sd,
index 6e0dac4..5913522 100644 (file)
@@ -231,6 +231,41 @@ end:
        return vb2_v4l2_buf;
 }
 
+static struct vb2_v4l2_buffer *msm_vb2_get_buf_by_idx(int session_id,
+       unsigned int stream_id, uint32_t index)
+{
+       struct msm_stream *stream;
+       struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
+       struct msm_vb2_buffer *msm_vb2 = NULL;
+       unsigned long flags;
+
+       stream = msm_get_stream(session_id, stream_id);
+       if (IS_ERR_OR_NULL(stream))
+               return NULL;
+
+       spin_lock_irqsave(&stream->stream_lock, flags);
+
+       if (!stream->vb2_q) {
+               pr_err("%s: stream q not available\n", __func__);
+               goto end;
+       }
+
+       list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
+               vb2_v4l2_buf = &(msm_vb2->vb2_v4l2_buf);
+               if ((vb2_v4l2_buf->vb2_buf.index != index) || msm_vb2->in_freeq
+                       || vb2_v4l2_buf->vb2_buf.state != VB2_BUF_STATE_ACTIVE)
+                       continue;
+
+               msm_vb2->in_freeq = 1;
+               goto end;
+       }
+       msm_vb2 = NULL;
+       vb2_v4l2_buf = NULL;
+end:
+       spin_unlock_irqrestore(&stream->stream_lock, flags);
+       return vb2_v4l2_buf;
+}
+
 static int msm_vb2_put_buf(struct vb2_v4l2_buffer *vb, int session_id,
                                unsigned int stream_id)
 {
@@ -320,6 +355,48 @@ static int msm_vb2_buf_done(struct vb2_v4l2_buffer *vb, int session_id,
        return rc;
 }
 
+long msm_vb2_return_buf_by_idx(int session_id, unsigned int stream_id,
+                               uint32_t index)
+{
+       struct msm_stream *stream;
+       struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
+       struct msm_vb2_buffer *msm_vb2 = NULL;
+       unsigned long flags;
+       long rc = -EINVAL;
+
+       stream = msm_get_stream(session_id, stream_id);
+       if (IS_ERR_OR_NULL(stream))
+               return rc;
+
+       spin_lock_irqsave(&stream->stream_lock, flags);
+
+       if (!stream->vb2_q) {
+               pr_err("%s: stream q not available\n", __func__);
+               goto end;
+       }
+
+       list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
+               vb2_v4l2_buf = &(msm_vb2->vb2_v4l2_buf);
+               if ((vb2_v4l2_buf->vb2_buf.index != index)
+                       || vb2_v4l2_buf->vb2_buf.state != VB2_BUF_STATE_ACTIVE)
+                       continue;
+
+               if (!msm_vb2->in_freeq) {
+                       vb2_buffer_done(&vb2_v4l2_buf->vb2_buf,
+                               VB2_BUF_STATE_ERROR);
+                       rc = 0;
+               } else {
+                       rc = -EINVAL;
+               }
+               break;
+       }
+
+end:
+       spin_unlock_irqrestore(&stream->stream_lock, flags);
+       return rc;
+}
+EXPORT_SYMBOL(msm_vb2_return_buf_by_idx);
+
 static int msm_vb2_flush_buf(int session_id, unsigned int stream_id)
 {
        unsigned long flags;
@@ -350,11 +427,11 @@ int msm_vb2_request_cb(struct msm_sd_req_vb2_q *req)
        }
 
        req->get_buf = msm_vb2_get_buf;
+       req->get_buf_by_idx = msm_vb2_get_buf_by_idx;
        req->get_vb2_queue = msm_vb2_get_queue;
        req->put_buf = msm_vb2_put_buf;
        req->buf_done = msm_vb2_buf_done;
        req->flush_buf = msm_vb2_flush_buf;
-
        return 0;
 }
 
index 96fa1d4..53511d5 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -65,5 +65,7 @@ struct msm_stream {
 struct vb2_ops *msm_vb2_get_q_ops(void);
 struct vb2_mem_ops *msm_vb2_get_q_mem_ops(void);
 int msm_vb2_request_cb(struct msm_sd_req_vb2_q *req_sd);
+long msm_vb2_return_buf_by_idx(int session_id, unsigned int stream_id,
+       uint32_t index);
 
 #endif /*_MSM_VB_H */
index 092551d..fe70daa 100644 (file)
@@ -202,5 +202,24 @@ struct msm_camera_user_buf_cont_t {
        unsigned int buf_idx[MSM_CAMERA_MAX_USER_BUFF_CNT];
 };
 
+struct msm_camera_return_buf {
+       __u32 index;
+       __u32 reserved;
+};
+
+#define MSM_CAMERA_PRIV_IOCTL_ID_BASE 0
+#define MSM_CAMERA_PRIV_IOCTL_ID_RETURN_BUF 1
+
+struct msm_camera_private_ioctl_arg {
+       __u32 id;
+       __u32 size;
+       __u32 result;
+       __u32 reserved;
+       __user __u64 ioctl_ptr;
+};
+
+#define VIDIOC_MSM_CAMERA_PRIVATE_IOCTL_CMD \
+       _IOWR('V', BASE_VIDIOC_PRIVATE, struct msm_camera_private_ioctl_arg)
+
 #endif
 
index a68b174..2961cae 100644 (file)
@@ -34,6 +34,9 @@ struct msm_buf_mngr_main_cont_info {
        int32_t cont_fd;
 };
 
+#define MSM_CAMERA_BUF_MNGR_IOCTL_ID_BASE 0
+#define MSM_CAMERA_BUF_MNGR_IOCTL_ID_GET_BUF_BY_IDX 1
+
 #define VIDIOC_MSM_BUF_MNGR_GET_BUF \
        _IOWR('V', BASE_VIDIOC_PRIVATE + 33, struct msm_buf_mngr_info)
 
@@ -55,5 +58,9 @@ struct msm_buf_mngr_main_cont_info {
 #define VIDIOC_MSM_BUF_MNGR_FLUSH \
        _IOWR('V', BASE_VIDIOC_PRIVATE + 39, struct msm_buf_mngr_info)
 
+#define VIDIOC_MSM_BUF_MNGR_IOCTL_CMD \
+       _IOWR('V', BASE_VIDIOC_PRIVATE + 40, \
+       struct msm_camera_private_ioctl_arg)
+
 #endif