static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
WARN_ON(priv != file->private_data);
static int soc_camera_enum_input(struct file *file, void *priv,
struct v4l2_input *inp)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
int ret = 0;
if (inp->index != 0)
static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
return v4l2_subdev_call(sd, core, s_std, *a);
struct v4l2_requestbuffers *p)
{
int ret;
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
WARN_ON(priv != file->private_data);
- ret = videobuf_reqbufs(&icf->vb_vidq, p);
+ if (icd->streamer && icd->streamer != file)
+ return -EBUSY;
+
+ ret = videobuf_reqbufs(&icd->vb_vidq, p);
if (ret < 0)
return ret;
- return ici->ops->reqbufs(icf, p);
+ ret = ici->ops->reqbufs(icd, p);
+ if (!ret && !icd->streamer)
+ icd->streamer = file;
+
+ return ret;
}
static int soc_camera_querybuf(struct file *file, void *priv,
struct v4l2_buffer *p)
{
- struct soc_camera_file *icf = file->private_data;
+ struct soc_camera_device *icd = file->private_data;
WARN_ON(priv != file->private_data);
- return videobuf_querybuf(&icf->vb_vidq, p);
+ return videobuf_querybuf(&icd->vb_vidq, p);
}
static int soc_camera_qbuf(struct file *file, void *priv,
struct v4l2_buffer *p)
{
- struct soc_camera_file *icf = file->private_data;
+ struct soc_camera_device *icd = file->private_data;
WARN_ON(priv != file->private_data);
- return videobuf_qbuf(&icf->vb_vidq, p);
+ if (icd->streamer != file)
+ return -EBUSY;
+
+ return videobuf_qbuf(&icd->vb_vidq, p);
}
static int soc_camera_dqbuf(struct file *file, void *priv,
struct v4l2_buffer *p)
{
- struct soc_camera_file *icf = file->private_data;
+ struct soc_camera_device *icd = file->private_data;
WARN_ON(priv != file->private_data);
- return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK);
+ if (icd->streamer != file)
+ return -EBUSY;
+
+ return videobuf_dqbuf(&icd->vb_vidq, p, file->f_flags & O_NONBLOCK);
}
/* Always entered with .video_lock held */
((x) >> 24) & 0xff
/* Called with .vb_lock held, or from the first open(2), see comment there */
-static int soc_camera_set_fmt(struct soc_camera_file *icf,
+static int soc_camera_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
- struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct v4l2_pix_format *pix = &f->fmt.pix;
int ret;
icd->user_width = pix->width;
icd->user_height = pix->height;
icd->colorspace = pix->colorspace;
- icf->vb_vidq.field =
+ icd->vb_vidq.field =
icd->field = pix->field;
if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
dev);
struct soc_camera_link *icl = to_soc_camera_link(icd);
struct soc_camera_host *ici;
- struct soc_camera_file *icf;
int ret;
if (!icd->ops)
ici = to_soc_camera_host(icd->dev.parent);
- icf = vmalloc(sizeof(*icf));
- if (!icf)
- return -ENOMEM;
-
if (!try_module_get(ici->ops->owner)) {
dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
- ret = -EINVAL;
- goto emgi;
+ return -EINVAL;
}
/*
*/
mutex_lock(&icd->video_lock);
- icf->icd = icd;
icd->use_count++;
/* Now we really have to activate the camera */
* apart from someone else calling open() simultaneously, but
* .video_lock is protecting us against it.
*/
- ret = soc_camera_set_fmt(icf, &f);
+ ret = soc_camera_set_fmt(icd, &f);
if (ret < 0)
goto esfmt;
}
- file->private_data = icf;
+ file->private_data = icd;
dev_dbg(&icd->dev, "camera device open\n");
- ici->ops->init_videobuf(&icf->vb_vidq, icd);
+ ici->ops->init_videobuf(&icd->vb_vidq, icd);
mutex_unlock(&icd->video_lock);
icd->use_count--;
mutex_unlock(&icd->video_lock);
module_put(ici->ops->owner);
-emgi:
- vfree(icf);
+
return ret;
}
static int soc_camera_close(struct file *file)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
mutex_lock(&icd->video_lock);
icl->power(icd->pdev, 0);
}
+ if (icd->streamer == file)
+ icd->streamer = NULL;
+
mutex_unlock(&icd->video_lock);
module_put(ici->ops->owner);
- vfree(icf);
-
dev_dbg(&icd->dev, "camera device close\n");
return 0;
static ssize_t soc_camera_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
int err = -EINVAL;
dev_err(&icd->dev, "camera device read not implemented\n");
static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
int err;
dev_dbg(&icd->dev, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
- err = videobuf_mmap_mapper(&icf->vb_vidq, vma);
+ if (icd->streamer != file)
+ return -EBUSY;
+
+ err = videobuf_mmap_mapper(&icd->vb_vidq, vma);
dev_dbg(&icd->dev, "vma start=0x%08lx, size=%ld, ret=%d\n",
(unsigned long)vma->vm_start,
static unsigned int soc_camera_poll(struct file *file, poll_table *pt)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
- if (list_empty(&icf->vb_vidq.stream)) {
+ if (icd->streamer != file)
+ return -EBUSY;
+
+ if (list_empty(&icd->vb_vidq.stream)) {
dev_err(&icd->dev, "Trying to poll with no queued buffers!\n");
return POLLERR;
}
static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
int ret;
WARN_ON(priv != file->private_data);
- mutex_lock(&icf->vb_vidq.vb_lock);
+ if (icd->streamer && icd->streamer != file)
+ return -EBUSY;
- if (icf->vb_vidq.bufs[0]) {
+ mutex_lock(&icd->vb_vidq.vb_lock);
+
+ if (icd->vb_vidq.bufs[0]) {
dev_err(&icd->dev, "S_FMT denied: queue initialised\n");
ret = -EBUSY;
goto unlock;
}
- ret = soc_camera_set_fmt(icf, f);
+ ret = soc_camera_set_fmt(icd, f);
+
+ if (!ret && !icd->streamer)
+ icd->streamer = file;
unlock:
- mutex_unlock(&icf->vb_vidq.vb_lock);
+ mutex_unlock(&icd->vb_vidq.vb_lock);
return ret;
}
static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
const struct soc_mbus_pixelfmt *format;
WARN_ON(priv != file->private_data);
static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct v4l2_pix_format *pix = &f->fmt.pix;
WARN_ON(priv != file->private_data);
pix->width = icd->user_width;
pix->height = icd->user_height;
- pix->field = icf->vb_vidq.field;
+ pix->field = icd->vb_vidq.field;
pix->pixelformat = icd->current_fmt->host_fmt->fourcc;
pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
icd->current_fmt->host_fmt);
static int soc_camera_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
WARN_ON(priv != file->private_data);
static int soc_camera_streamon(struct file *file, void *priv,
enum v4l2_buf_type i)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
int ret;
if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
+ if (icd->streamer != file)
+ return -EBUSY;
+
mutex_lock(&icd->video_lock);
v4l2_subdev_call(sd, video, s_stream, 1);
/* This calls buf_queue from host driver's videobuf_queue_ops */
- ret = videobuf_streamon(&icf->vb_vidq);
+ ret = videobuf_streamon(&icd->vb_vidq);
mutex_unlock(&icd->video_lock);
static int soc_camera_streamoff(struct file *file, void *priv,
enum v4l2_buf_type i)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
WARN_ON(priv != file->private_data);
if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
+ if (icd->streamer != file)
+ return -EBUSY;
+
mutex_lock(&icd->video_lock);
/*
* This calls buf_release from host driver's videobuf_queue_ops for all
* remaining buffers. When the last buffer is freed, stop capture
*/
- videobuf_streamoff(&icf->vb_vidq);
+ videobuf_streamoff(&icd->vb_vidq);
v4l2_subdev_call(sd, video, s_stream, 0);
static int soc_camera_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *qc)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
int i;
static int soc_camera_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
int ret;
static int soc_camera_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
int ret;
static int soc_camera_cropcap(struct file *file, void *fh,
struct v4l2_cropcap *a)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
return ici->ops->cropcap(icd, a);
static int soc_camera_g_crop(struct file *file, void *fh,
struct v4l2_crop *a)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
int ret;
- mutex_lock(&icf->vb_vidq.vb_lock);
+ mutex_lock(&icd->vb_vidq.vb_lock);
ret = ici->ops->get_crop(icd, a);
- mutex_unlock(&icf->vb_vidq.vb_lock);
+ mutex_unlock(&icd->vb_vidq.vb_lock);
return ret;
}
static int soc_camera_s_crop(struct file *file, void *fh,
struct v4l2_crop *a)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct v4l2_rect *rect = &a->c;
struct v4l2_crop current_crop;
rect->width, rect->height, rect->left, rect->top);
/* Cropping is allowed during a running capture, guard consistency */
- mutex_lock(&icf->vb_vidq.vb_lock);
+ mutex_lock(&icd->vb_vidq.vb_lock);
/* If get_crop fails, we'll let host and / or client drivers decide */
ret = ici->ops->get_crop(icd, ¤t_crop);
if (ret < 0) {
dev_err(&icd->dev,
"S_CROP denied: getting current crop failed\n");
- } else if (icf->vb_vidq.bufs[0] &&
+ } else if (icd->vb_vidq.bufs[0] &&
(a->c.width != current_crop.c.width ||
a->c.height != current_crop.c.height)) {
dev_err(&icd->dev,
ret = ici->ops->set_crop(icd, a);
}
- mutex_unlock(&icf->vb_vidq.vb_lock);
+ mutex_unlock(&icd->vb_vidq.vb_lock);
return ret;
}
static int soc_camera_g_parm(struct file *file, void *fh,
struct v4l2_streamparm *a)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
if (ici->ops->get_parm)
static int soc_camera_s_parm(struct file *file, void *fh,
struct v4l2_streamparm *a)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
if (ici->ops->set_parm)
static int soc_camera_g_chip_ident(struct file *file, void *fh,
struct v4l2_dbg_chip_ident *id)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
return v4l2_subdev_call(sd, core, g_chip_ident, id);
static int soc_camera_g_register(struct file *file, void *fh,
struct v4l2_dbg_register *reg)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
return v4l2_subdev_call(sd, core, g_register, reg);
static int soc_camera_s_register(struct file *file, void *fh,
struct v4l2_dbg_register *reg)
{
- struct soc_camera_file *icf = file->private_data;
- struct soc_camera_device *icd = icf->icd;
+ struct soc_camera_device *icd = file->private_data;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
return v4l2_subdev_call(sd, core, s_register, reg);