Commit d4cdfa06 authored by Enrico Scholz's avatar Enrico Scholz

media:mx6s_capture: ported to v4l2_fh

(re)opening /dev/video0 while streaming (e.g. to change properties)
reinitialized internal structures and stopping streaming.

Ported to use v4l2_fh which implements reference counting.
Signed-off-by: Enrico Scholz's avatarEnrico Scholz <enrico.scholz@sigma-chemnitz.de>
parent b201533c
......@@ -1174,20 +1174,11 @@ static irqreturn_t mx6s_csi_irq_handler(int irq, void *data)
return IRQ_HANDLED;
}
/*
* File operations for the device
*/
static int mx6s_csi_open(struct file *file)
static int _mx6s_csi_open_init(struct mx6s_csi_dev *csi_dev)
{
struct mx6s_csi_dev *csi_dev = video_drvdata(file);
struct v4l2_subdev *sd = csi_dev->sd;
struct vb2_queue *q = &csi_dev->vb2_vidq;
int ret = 0;
file->private_data = csi_dev;
if (mutex_lock_interruptible(&csi_dev->lock))
return -ERESTARTSYS;
int ret;
q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
q->io_modes = VB2_MMAP | VB2_USERPTR;
......@@ -1200,42 +1191,83 @@ static int mx6s_csi_open(struct file *file)
ret = vb2_queue_init(q);
if (ret < 0)
goto unlock;
goto out;
pm_runtime_get_sync(csi_dev->dev);
request_bus_freq(BUS_FREQ_HIGH);
v4l2_subdev_call(sd, core, s_power, 1);
mx6s_csi_init(csi_dev);
mutex_unlock(&csi_dev->lock);
ret = 0;
out:
return ret;
unlock:
}
/*
* File operations for the device
*/
static int mx6s_csi_open(struct file *file)
{
struct mx6s_csi_dev *csi_dev = video_drvdata(file);
struct v4l2_fh *fh = NULL;
int ret = 0;
if (mutex_lock_interruptible(&csi_dev->lock))
return -ERESTARTSYS;
ret = v4l2_fh_open(file);
if (ret < 0)
goto out;
fh = file->private_data;
if (v4l2_fh_is_singular(fh)) {
ret = _mx6s_csi_open_init(csi_dev);
if (ret < 0) {
v4l2_fh_release(file);
goto out;
}
}
ret = 0;
out:
mutex_unlock(&csi_dev->lock);
return ret;
}
static int mx6s_csi_close(struct file *file)
{
struct mx6s_csi_dev *csi_dev = video_drvdata(file);
struct v4l2_fh *fh = file->private_data;
struct v4l2_subdev *sd = csi_dev->sd;
bool do_release;
mutex_lock(&csi_dev->lock);
vb2_queue_release(&csi_dev->vb2_vidq);
do_release = v4l2_fh_is_singular(fh);
mx6s_csi_deinit(csi_dev);
v4l2_subdev_call(sd, core, s_power, 0);
if (do_release) {
v4l2_subdev_call(sd, video, s_stream, 0);
vb2_queue_release(&csi_dev->vb2_vidq);
mx6s_csi_deinit(csi_dev);
v4l2_subdev_call(sd, core, s_power, 0);
mutex_unlock(&csi_dev->lock);
v4l2_fh_release(file);
file->private_data = NULL;
release_bus_freq(BUS_FREQ_HIGH);
}
mutex_unlock(&csi_dev->lock);
release_bus_freq(BUS_FREQ_HIGH);
if (do_release)
pm_runtime_put_sync_suspend(csi_dev->dev);
pm_runtime_put_sync_suspend(csi_dev->dev);
return 0;
}
......@@ -1342,8 +1374,6 @@ static int mx6s_vidioc_reqbufs(struct file *file, void *priv,
{
struct mx6s_csi_dev *csi_dev = video_drvdata(file);
WARN_ON(priv != file->private_data);
return vb2_reqbufs(&csi_dev->vb2_vidq, p);
}
......@@ -1353,8 +1383,6 @@ static int mx6s_vidioc_querybuf(struct file *file, void *priv,
struct mx6s_csi_dev *csi_dev = video_drvdata(file);
int ret;
WARN_ON(priv != file->private_data);
ret = vb2_querybuf(&csi_dev->vb2_vidq, p);
if (!ret) {
......@@ -1371,8 +1399,6 @@ static int mx6s_vidioc_qbuf(struct file *file, void *priv,
{
struct mx6s_csi_dev *csi_dev = video_drvdata(file);
WARN_ON(priv != file->private_data);
return vb2_qbuf(&csi_dev->vb2_vidq, p);
}
......@@ -1381,8 +1407,6 @@ static int mx6s_vidioc_dqbuf(struct file *file, void *priv,
{
struct mx6s_csi_dev *csi_dev = video_drvdata(file);
WARN_ON(priv != file->private_data);
return vb2_dqbuf(&csi_dev->vb2_vidq, p, file->f_flags & O_NONBLOCK);
}
......@@ -1398,8 +1422,6 @@ static int mx6s_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
struct mx6s_fmt *fmt;
int ret;
WARN_ON(priv != file->private_data);
ret = v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
if (ret < 0) {
/* no more formats */
......@@ -1492,8 +1514,6 @@ static int mx6s_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
{
struct mx6s_csi_dev *csi_dev = video_drvdata(file);
WARN_ON(priv != file->private_data);
f->fmt.pix = csi_dev->pix;
return 0;
......@@ -1504,8 +1524,6 @@ static int mx6s_vidioc_querycap(struct file *file, void *priv,
{
struct mx6s_csi_dev *csi_dev = video_drvdata(file);
WARN_ON(priv != file->private_data);
/* cap->name is set by the friendly caller:-> */
strlcpy(cap->driver, MX6S_CAM_DRV_NAME, sizeof(cap->driver));
strlcpy(cap->card, MX6S_CAM_DRIVER_DESCRIPTION, sizeof(cap->card));
......@@ -1535,8 +1553,6 @@ static int mx6s_vidioc_streamon(struct file *file, void *priv,
struct v4l2_subdev *sd = csi_dev->sd;
int ret;
WARN_ON(priv != file->private_data);
if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
......@@ -1553,8 +1569,6 @@ static int mx6s_vidioc_streamoff(struct file *file, void *priv,
struct mx6s_csi_dev *csi_dev = video_drvdata(file);
struct v4l2_subdev *sd = csi_dev->sd;
WARN_ON(priv != file->private_data);
if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment