summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHu Kejun <william.hu@rock-chips.com>2018-12-21 10:27:17 +0800
committerTao Huang <huangtao@rock-chips.com>2019-01-24 14:28:44 +0800
commitf944fd08f6c5c5116538faec997583b9e59b8f21 (patch)
tree35478ebcf48baebecd0c2d38a44e553e2ab01672
parent60edcb0765113a21387de88e0df6b97984dfa0d9 (diff)
media: rk-isp10: add api mutex for multi-thread app
Change-Id: If2f8600a5f6cdf57bc3859b81a68539bb2d05a84 Signed-off-by: Hu Kejun <william.hu@rock-chips.com>
-rw-r--r--drivers/media/platform/rk-isp10/cif_isp10.h2
-rw-r--r--drivers/media/platform/rk-isp10/cif_isp10_v4l2.c90
2 files changed, 85 insertions, 7 deletions
diff --git a/drivers/media/platform/rk-isp10/cif_isp10.h b/drivers/media/platform/rk-isp10/cif_isp10.h
index eb570430f2ae..c24d4e4323dd 100644
--- a/drivers/media/platform/rk-isp10/cif_isp10.h
+++ b/drivers/media/platform/rk-isp10/cif_isp10.h
@@ -674,6 +674,8 @@ struct cif_isp10_device {
struct pltfrm_soc_cfg soc_cfg;
void *nodes;
+ struct mutex api_mutex; /* user api mutex */
+
};
struct cif_isp10_fmt *get_cif_isp10_output_format(int index);
diff --git a/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c b/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c
index b19efe054892..480f5caaee50 100644
--- a/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c
+++ b/drivers/media/platform/rk-isp10/cif_isp10_v4l2.c
@@ -550,6 +550,7 @@ static int cif_isp10_v4l2_streamon(
static u32 streamon_cnt_dma;
u32 stream_ids = to_stream_id(file);
+ mutex_lock(&dev->api_mutex);
cif_isp10_pltfrm_pr_dbg(dev->dev, "%s(%d)\n",
cif_isp10_v4l2_buf_type_string(queue->type),
(stream_ids & CIF_ISP10_STREAM_MP) ? ++streamon_cnt_mp :
@@ -568,10 +569,12 @@ static int cif_isp10_v4l2_streamon(
goto err;
}
+ mutex_unlock(&dev->api_mutex);
return 0;
err:
(void)vb2_queue_release(queue);
cif_isp10_pltfrm_pr_err(dev->dev, "failed with error %d\n", ret);
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -609,12 +612,17 @@ static int cif_isp10_v4l2_streamoff(
void *priv,
enum v4l2_buf_type buf_type)
{
- int ret = cif_isp10_v4l2_do_streamoff(file);
+ int ret;
+ struct vb2_queue *queue = to_vb2_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ mutex_lock(&dev->api_mutex);
+ ret = cif_isp10_v4l2_do_streamoff(file);
if (IS_ERR_VALUE(ret))
cif_isp10_pltfrm_pr_err(NULL,
"failed with error %d\n", ret);
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -660,12 +668,14 @@ static int cif_isp10_v4l2_reqbufs(
struct cif_isp10_device *dev = to_cif_isp10_device(queue);
enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue);
+ mutex_lock(&dev->api_mutex);
ret = vb2_ioctl_reqbufs(file, priv, req);
if (IS_ERR_VALUE(ret)) {
cif_isp10_pltfrm_pr_err(NULL,
"videobuf_reqbufs failed with error %d\n", ret);
}
cif_isp10_reqbufs(dev, strm, req);
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -675,11 +685,15 @@ static int cif_isp10_v4l2_querybuf(
struct v4l2_buffer *buf)
{
int ret;
+ struct vb2_queue *queue = to_vb2_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ mutex_lock(&dev->api_mutex);
ret = vb2_ioctl_querybuf(file, priv, buf);
if (IS_ERR_VALUE(ret))
cif_isp10_pltfrm_pr_err(NULL,
"videobuf_querybuf failed with error %d\n", ret);
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -694,10 +708,12 @@ static int cif_isp10_v4l2_s_ctrl(
enum cif_isp10_cid id =
cif_isp10_v4l2_cid2cif_isp10_cid(vc->id);
int val = vc->value;
+ int ret;
if (IS_ERR_VALUE(id))
return id;
+ mutex_lock(&dev->api_mutex);
switch (vc->id) {
case V4L2_CID_COLORFX:
val = cif_isp10_v4l2_colorfx2cif_isp10_ie(val);
@@ -716,7 +732,9 @@ static int cif_isp10_v4l2_s_ctrl(
break;
}
- return cif_isp10_s_ctrl(dev, id, val);
+ ret = cif_isp10_s_ctrl(dev, id, val);
+ mutex_unlock(&dev->api_mutex);
+ return ret;
}
static int cif_isp10_v4l2_s_fmt(
@@ -735,8 +753,11 @@ static int cif_isp10_v4l2_s_fmt(
"%s\n",
cif_isp10_v4l2_buf_type_string(queue->type));
- if (node->owner && node->owner != fh)
+ mutex_lock(&dev->api_mutex);
+ if (node->owner && node->owner != fh) {
+ mutex_unlock(&dev->api_mutex);
return -EBUSY;
+ }
strm_fmt.frm_fmt.pix_fmt =
cif_isp10_v4l2_pix_fmt2cif_isp10_pix_fmt(
@@ -759,10 +780,12 @@ static int cif_isp10_v4l2_s_fmt(
if (IS_ERR_VALUE(ret))
goto err;
+ mutex_unlock(&dev->api_mutex);
return 0;
err:
cif_isp10_pltfrm_pr_err(NULL,
"failed with error %d\n", ret);
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -777,6 +800,7 @@ static int cif_isp10_v4l2_g_fmt(
struct cif_isp10_device *dev = to_cif_isp10_device(queue);
enum cif_isp10_stream_id stream_id = to_cif_isp10_stream_id(queue);
+ mutex_lock(&dev->api_mutex);
switch (stream_id) {
case CIF_ISP10_STREAM_SP:
pix_fmt = dev->config.mi_config.sp.output.pix_fmt;
@@ -795,9 +819,11 @@ static int cif_isp10_v4l2_g_fmt(
f->fmt.pix.pixelformat = cif_isp10_pix_fmt2v4l2_pix_fmt(pix_fmt, queue);
break;
default:
+ mutex_unlock(&dev->api_mutex);
return -EINVAL;
}
+ mutex_unlock(&dev->api_mutex);
return 0;
}
@@ -810,14 +836,17 @@ static int cif_isp10_v4l2_g_input(
struct vb2_queue *queue = to_vb2_queue(file);
struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ mutex_lock(&dev->api_mutex);
ret = cif_isp10_g_input(dev, i);
if (IS_ERR_VALUE(ret))
goto err;
+ mutex_unlock(&dev->api_mutex);
return 0;
err:
cif_isp10_pltfrm_pr_err(NULL,
"failed with error %d\n", ret);
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -832,14 +861,17 @@ static int cif_isp10_v4l2_s_input(
cif_isp10_pltfrm_pr_dbg(dev->dev, "setting input to %d\n", i);
+ mutex_lock(&dev->api_mutex);
ret = cif_isp10_s_input(dev, i);
if (IS_ERR_VALUE(ret))
goto err;
+ mutex_unlock(&dev->api_mutex);
return 0;
err:
cif_isp10_pltfrm_pr_err(NULL,
"failed with error %d\n", ret);
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -854,6 +886,7 @@ static int cif_isp10_v4l2_enum_framesizes(
struct cif_isp10_device *dev = to_cif_isp10_device(queue);
struct v4l2_subdev_frame_size_enum fse;
+ mutex_lock(&dev->api_mutex);
if (IS_ERR_OR_NULL(dev->img_src)) {
cif_isp10_pltfrm_pr_err(NULL,
"input has not yet been selected, cannot enumerate formats\n");
@@ -873,8 +906,11 @@ static int cif_isp10_v4l2_enum_framesizes(
fsize->discrete.width = fse.max_width;
fsize->discrete.height = fse.max_height;
+ mutex_unlock(&dev->api_mutex);
return 0;
+
err:
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -1032,6 +1068,7 @@ static int cif_isp10_v4l2_open(
"video device video%d.%d (%s)\n",
vdev->num, vdev->minor, vdev->name);
+ mutex_lock(&dev->api_mutex);
if (vdev->minor == cif_isp10_v4l2_dev->node[SP_DEV].vdev.minor) {
buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
stream_id = CIF_ISP10_STREAM_SP;
@@ -1064,8 +1101,10 @@ static int cif_isp10_v4l2_open(
v4l2_fh_add(&fh->fh);
node = to_node(fh);
- if (++node->users > 1)
+ if (++node->users > 1) {
+ mutex_unlock(&dev->api_mutex);
return 0;
+ }
/* First open of the device, so initialize everything */
node->owner = NULL;
@@ -1083,10 +1122,12 @@ static int cif_isp10_v4l2_open(
goto err;
}
+ mutex_unlock(&dev->api_mutex);
return 0;
err:
cif_isp10_pltfrm_pr_err(NULL,
"failed with error %d\n", ret);
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -1102,11 +1143,13 @@ static int cif_isp10_v4l2_release(struct file *file)
cif_isp10_pltfrm_pr_dbg(dev->dev, "%s\n",
cif_isp10_v4l2_buf_type_string(queue->type));
+ mutex_lock(&dev->api_mutex);
if (node->users) {
--node->users;
} else {
cif_isp10_pltfrm_pr_warn(dev->dev,
"number of users for this device is already 0\n");
+ mutex_unlock(&dev->api_mutex);
return 0;
}
@@ -1125,6 +1168,9 @@ static int cif_isp10_v4l2_release(struct file *file)
if (node->owner == fh)
node->owner = NULL;
+ if (file->private_data == queue->owner)
+ queue->owner = NULL;
+
v4l2_fh_del(&fh->fh);
v4l2_fh_exit(&fh->fh);
kfree(fh);
@@ -1132,6 +1178,8 @@ static int cif_isp10_v4l2_release(struct file *file)
if (IS_ERR_VALUE(ret))
cif_isp10_pltfrm_pr_err(dev->dev,
"failed with error %d\n", ret);
+
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -1360,10 +1408,12 @@ static long v4l2_default_ioctl(struct file *file, void *fh,
struct vb2_queue *queue = to_vb2_queue(file);
struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ mutex_lock(&dev->api_mutex);
if (!arg) {
cif_isp10_pltfrm_pr_err(dev->dev,
"NULL Pointer Violation from IOCTL arg:0x%lx\n",
(unsigned long)arg);
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -1377,6 +1427,7 @@ static long v4l2_default_ioctl(struct file *file, void *fh,
if (ret < 0) {
cif_isp10_pltfrm_pr_err(dev->dev,
"failed to get sensor mode data\n");
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -1403,6 +1454,7 @@ static long v4l2_default_ioctl(struct file *file, void *fh,
if (IS_ERR_VALUE(ret)) {
cif_isp10_pltfrm_pr_err(dev->dev,
"failed to get isp_output data\n");
+ mutex_unlock(&dev->api_mutex);
return ret;
}
}
@@ -1416,6 +1468,7 @@ static long v4l2_default_ioctl(struct file *file, void *fh,
if (ret < 0) {
cif_isp10_pltfrm_pr_err(dev->dev,
"failed to get camera module information\n");
+ mutex_unlock(&dev->api_mutex);
return ret;
}
} else if (cmd == RK_VIDIOC_SENSOR_CONFIGINFO) {
@@ -1428,6 +1481,7 @@ static long v4l2_default_ioctl(struct file *file, void *fh,
if (ret < 0) {
cif_isp10_pltfrm_pr_err(dev->dev,
"failed to get camera module information\n");
+ mutex_unlock(&dev->api_mutex);
return ret;
}
} else if (cmd == RK_VIDIOC_SENSOR_REG_ACCESS) {
@@ -1440,10 +1494,12 @@ static long v4l2_default_ioctl(struct file *file, void *fh,
if (ret < 0) {
cif_isp10_pltfrm_pr_err(dev->dev,
"failed to get camera module information\n");
+ mutex_unlock(&dev->api_mutex);
return ret;
}
}
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -1470,21 +1526,26 @@ static int v4l2_enum_input(struct file *file, void *priv,
struct cif_isp10_device *dev = to_cif_isp10_device(queue);
const char *inp_name;
+ mutex_lock(&dev->api_mutex);
if ((queue->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
(queue->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)) {
cif_isp10_pltfrm_pr_err(NULL,
"wrong buffer queue %d\n", queue->type);
+ mutex_unlock(&dev->api_mutex);
return -EINVAL;
}
inp_name = cif_isp10_g_input_name(dev, input->index);
- if (IS_ERR_OR_NULL(inp_name))
+ if (IS_ERR_OR_NULL(inp_name)) {
+ mutex_unlock(&dev->api_mutex);
return -EINVAL;
+ }
input->type = V4L2_INPUT_TYPE_CAMERA;
input->std = V4L2_STD_UNKNOWN;
strncpy(input->name, inp_name, sizeof(input->name)-1);
+ mutex_unlock(&dev->api_mutex);
return 0;
}
@@ -1560,11 +1621,15 @@ static int v4l2_enum_fmt_cap(struct file *file, void *fh,
{
int ret = 0;
int xgold_num_format = 0;
+ struct vb2_queue *queue = to_vb2_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ mutex_lock(&dev->api_mutex);
xgold_num_format = get_cif_isp10_output_format_desc_size();
if ((f->index >= xgold_num_format) ||
(get_cif_isp10_output_format_desc(f->index)->pixelformat == 0)) {
cif_isp10_pltfrm_pr_err(NULL, "index %d\n", f->index);
+ mutex_unlock(&dev->api_mutex);
return -EINVAL;
}
strlcpy(f->description,
@@ -1574,6 +1639,8 @@ static int v4l2_enum_fmt_cap(struct file *file, void *fh,
get_cif_isp10_output_format_desc(f->index)->pixelformat;
f->flags = get_cif_isp10_output_format_desc(f->index)->flags;
+ mutex_unlock(&dev->api_mutex);
+
return ret;
}
@@ -1584,7 +1651,9 @@ static int v4l2_g_ctrl(struct file *file, void *priv,
struct cif_isp10_device *dev = to_cif_isp10_device(queue);
enum cif_isp10_cid id =
cif_isp10_v4l2_cid2cif_isp10_cid(vc->id);
+ int ret;
+ mutex_lock(&dev->api_mutex);
if (id == CIF_ISP10_CID_MIN_BUFFER_FOR_CAPTURE) {
/* Three buffers needed at least.
* one for MI_MP_Y_BASE_AD_INIT, one for MI_MP_Y_BASE_AD_SHD
@@ -1594,11 +1663,13 @@ static int v4l2_g_ctrl(struct file *file, void *priv,
cif_isp10_pltfrm_pr_dbg(dev->dev,
"V4L2_CID_MIN_BUFFERS_FOR_CAPTURE %d\n",
vc->value);
+ mutex_unlock(&dev->api_mutex);
return 0;
}
- return cif_isp10_img_src_g_ctrl(dev->img_src,
- id, &vc->value);
+ ret = cif_isp10_img_src_g_ctrl(dev->img_src, id, &vc->value);
+ mutex_unlock(&dev->api_mutex);
+ return ret;
}
static int v4l2_s_ext_ctrls(struct file *file, void *priv,
@@ -1662,6 +1733,7 @@ int cif_isp10_v4l2_cropcap(
u32 target_width, target_height;
u32 h_offs, v_offs;
+ mutex_lock(&dev->api_mutex);
if ((dev->config.input_sel == CIF_ISP10_INP_DMA) ||
(dev->config.input_sel == CIF_ISP10_INP_DMA_IE)) {
/* calculate cropping for aspect ratio */
@@ -1675,6 +1747,7 @@ int cif_isp10_v4l2_cropcap(
if (ret < 0) {
cif_isp10_pltfrm_pr_err(dev->dev,
"failed to get target frame size\n");
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -1711,6 +1784,7 @@ int cif_isp10_v4l2_cropcap(
if (ret < 0) {
cif_isp10_pltfrm_pr_err(dev->dev,
"failed to get target frame size\n");
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -1743,6 +1817,7 @@ int cif_isp10_v4l2_cropcap(
a->bounds.left,
a->bounds.top);
+ mutex_unlock(&dev->api_mutex);
return ret;
}
@@ -1910,6 +1985,7 @@ static int cif_isp10_v4l2_drv_probe(struct platform_device *pdev)
spin_lock_init(&dev->iowrite32_verify_lock);
spin_lock_init(&dev->isp_state_lock);
init_waitqueue_head(&dev->isp_stop_wait);
+ mutex_init(&dev->api_mutex);
ret = v4l2_device_register(dev->dev, &dev->v4l2_dev);
if (IS_ERR_VALUE(ret)) {