summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHariram Purushothaman <hariramp@codeaurora.org>2016-03-29 14:05:56 -0700
committerKyle Yan <kyan@codeaurora.org>2016-07-06 15:43:27 -0700
commitbb4f495a72058a6cb63b754530a2927c4928c6ad (patch)
tree0a4f9d51550ef5f35ff11575aa0809ab01b86fa5
parentd6c6b61a880dbdf860f24c09d058846c125a25c5 (diff)
msm: camera: Return HAL buffer to fix drain issues
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>
-rw-r--r--drivers/media/platform/msm/camera_v2/camera/camera.c87
-rw-r--r--drivers/media/platform/msm/camera_v2/fd/Makefile3
-rw-r--r--drivers/media/platform/msm/camera_v2/msm.c22
-rw-r--r--drivers/media/platform/msm/camera_v2/msm.h5
-rw-r--r--drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c319
-rw-r--r--drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h12
-rw-r--r--drivers/media/platform/msm/camera_v2/msm_sd.h5
-rw-r--r--drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c79
-rw-r--r--drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h4
-rw-r--r--include/uapi/media/msmb_camera.h19
-rw-r--r--include/uapi/media/msmb_generic_buf_mgr.h7
11 files changed, 510 insertions, 52 deletions
diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c
index 60a834588767..c1aeb8c43e81 100644
--- a/drivers/media/platform/msm/camera_v2/camera/camera.c
+++ b/drivers/media/platform/msm/camera_v2/camera/camera.c
@@ -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 = {
diff --git a/drivers/media/platform/msm/camera_v2/fd/Makefile b/drivers/media/platform/msm/camera_v2/fd/Makefile
index 82b37a73bfa3..8d01d3a8708d 100644
--- a/drivers/media/platform/msm/camera_v2/fd/Makefile
+++ b/drivers/media/platform/msm/camera_v2/fd/Makefile
@@ -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
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index a34dbb80b468..c6dc4b75e479 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -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)
{
diff --git a/drivers/media/platform/msm/camera_v2/msm.h b/drivers/media/platform/msm/camera_v2/msm.h
index cab07df2a5bb..2b3576b8edd2 100644
--- a/drivers/media/platform/msm/camera_v2/msm.h
+++ b/drivers/media/platform/msm/camera_v2/msm.h
@@ -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 */
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
index b6cbdcc32360..ac9a4b2048d1 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
@@ -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
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h
index dc7f745f6190..c2f1a1527800 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h
@@ -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
diff --git a/drivers/media/platform/msm/camera_v2/msm_sd.h b/drivers/media/platform/msm/camera_v2/msm_sd.h
index 6bb95ad0de87..d893d9fc07e3 100644
--- a/drivers/media/platform/msm/camera_v2/msm_sd.h
+++ b/drivers/media/platform/msm/camera_v2/msm_sd.h
@@ -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,
diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
index 6e0dac4608a9..59135225cb15 100644
--- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
+++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
@@ -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;
}
diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
index 96fa1d4c64c9..53511d5416d7 100644
--- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
+++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
@@ -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 */
diff --git a/include/uapi/media/msmb_camera.h b/include/uapi/media/msmb_camera.h
index 092551d0cc16..fe70daa772df 100644
--- a/include/uapi/media/msmb_camera.h
+++ b/include/uapi/media/msmb_camera.h
@@ -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
diff --git a/include/uapi/media/msmb_generic_buf_mgr.h b/include/uapi/media/msmb_generic_buf_mgr.h
index a68b174b97bb..2961cae1e7c1 100644
--- a/include/uapi/media/msmb_generic_buf_mgr.h
+++ b/include/uapi/media/msmb_generic_buf_mgr.h
@@ -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