Commit 57bee29d authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Mauro Carvalho Chehab

V4L/DVB: soc-camera: allow only one video queue per device

Multiple user-space application instances can open the same video device, but
it only makes sense for one of them to manage the videobuffer queue and set
video format of the device. Restrict soc-camera respectively.
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 79c6ff93
...@@ -638,7 +638,7 @@ static int mx1_camera_try_fmt(struct soc_camera_device *icd, ...@@ -638,7 +638,7 @@ static int mx1_camera_try_fmt(struct soc_camera_device *icd,
return 0; return 0;
} }
static int mx1_camera_reqbufs(struct soc_camera_file *icf, static int mx1_camera_reqbufs(struct soc_camera_device *icd,
struct v4l2_requestbuffers *p) struct v4l2_requestbuffers *p)
{ {
int i; int i;
...@@ -650,7 +650,7 @@ static int mx1_camera_reqbufs(struct soc_camera_file *icf, ...@@ -650,7 +650,7 @@ static int mx1_camera_reqbufs(struct soc_camera_file *icf,
* it hadn't triggered * it hadn't triggered
*/ */
for (i = 0; i < p->count; i++) { for (i = 0; i < p->count; i++) {
struct mx1_buffer *buf = container_of(icf->vb_vidq.bufs[i], struct mx1_buffer *buf = container_of(icd->vb_vidq.bufs[i],
struct mx1_buffer, vb); struct mx1_buffer, vb);
buf->inwork = 0; buf->inwork = 0;
INIT_LIST_HEAD(&buf->vb.queue); INIT_LIST_HEAD(&buf->vb.queue);
...@@ -661,10 +661,10 @@ static int mx1_camera_reqbufs(struct soc_camera_file *icf, ...@@ -661,10 +661,10 @@ static int mx1_camera_reqbufs(struct soc_camera_file *icf,
static unsigned int mx1_camera_poll(struct file *file, poll_table *pt) static unsigned int mx1_camera_poll(struct file *file, poll_table *pt)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct mx1_buffer *buf; struct mx1_buffer *buf;
buf = list_entry(icf->vb_vidq.stream.next, struct mx1_buffer, buf = list_entry(icd->vb_vidq.stream.next, struct mx1_buffer,
vb.stream); vb.stream);
poll_wait(file, &buf->vb.done, pt); poll_wait(file, &buf->vb.done, pt);
......
...@@ -976,7 +976,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd, ...@@ -976,7 +976,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd,
return ret; return ret;
} }
static int mx3_camera_reqbufs(struct soc_camera_file *icf, static int mx3_camera_reqbufs(struct soc_camera_device *icd,
struct v4l2_requestbuffers *p) struct v4l2_requestbuffers *p)
{ {
return 0; return 0;
...@@ -984,9 +984,9 @@ static int mx3_camera_reqbufs(struct soc_camera_file *icf, ...@@ -984,9 +984,9 @@ static int mx3_camera_reqbufs(struct soc_camera_file *icf,
static unsigned int mx3_camera_poll(struct file *file, poll_table *pt) static unsigned int mx3_camera_poll(struct file *file, poll_table *pt)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
return videobuf_poll_stream(file, &icf->vb_vidq, pt); return videobuf_poll_stream(file, &icd->vb_vidq, pt);
} }
static int mx3_camera_querycap(struct soc_camera_host *ici, static int mx3_camera_querycap(struct soc_camera_host *ici,
......
...@@ -1539,7 +1539,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd, ...@@ -1539,7 +1539,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd,
return ret; return ret;
} }
static int pxa_camera_reqbufs(struct soc_camera_file *icf, static int pxa_camera_reqbufs(struct soc_camera_device *icd,
struct v4l2_requestbuffers *p) struct v4l2_requestbuffers *p)
{ {
int i; int i;
...@@ -1551,7 +1551,7 @@ static int pxa_camera_reqbufs(struct soc_camera_file *icf, ...@@ -1551,7 +1551,7 @@ static int pxa_camera_reqbufs(struct soc_camera_file *icf,
* it hadn't triggered * it hadn't triggered
*/ */
for (i = 0; i < p->count; i++) { for (i = 0; i < p->count; i++) {
struct pxa_buffer *buf = container_of(icf->vb_vidq.bufs[i], struct pxa_buffer *buf = container_of(icd->vb_vidq.bufs[i],
struct pxa_buffer, vb); struct pxa_buffer, vb);
buf->inwork = 0; buf->inwork = 0;
INIT_LIST_HEAD(&buf->vb.queue); INIT_LIST_HEAD(&buf->vb.queue);
...@@ -1562,10 +1562,10 @@ static int pxa_camera_reqbufs(struct soc_camera_file *icf, ...@@ -1562,10 +1562,10 @@ static int pxa_camera_reqbufs(struct soc_camera_file *icf,
static unsigned int pxa_camera_poll(struct file *file, poll_table *pt) static unsigned int pxa_camera_poll(struct file *file, poll_table *pt)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct pxa_buffer *buf; struct pxa_buffer *buf;
buf = list_entry(icf->vb_vidq.stream.next, struct pxa_buffer, buf = list_entry(icd->vb_vidq.stream.next, struct pxa_buffer,
vb.stream); vb.stream);
poll_wait(file, &buf->vb.done, pt); poll_wait(file, &buf->vb.done, pt);
......
...@@ -1726,7 +1726,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, ...@@ -1726,7 +1726,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
return ret; return ret;
} }
static int sh_mobile_ceu_reqbufs(struct soc_camera_file *icf, static int sh_mobile_ceu_reqbufs(struct soc_camera_device *icd,
struct v4l2_requestbuffers *p) struct v4l2_requestbuffers *p)
{ {
int i; int i;
...@@ -1740,7 +1740,7 @@ static int sh_mobile_ceu_reqbufs(struct soc_camera_file *icf, ...@@ -1740,7 +1740,7 @@ static int sh_mobile_ceu_reqbufs(struct soc_camera_file *icf,
for (i = 0; i < p->count; i++) { for (i = 0; i < p->count; i++) {
struct sh_mobile_ceu_buffer *buf; struct sh_mobile_ceu_buffer *buf;
buf = container_of(icf->vb_vidq.bufs[i], buf = container_of(icd->vb_vidq.bufs[i],
struct sh_mobile_ceu_buffer, vb); struct sh_mobile_ceu_buffer, vb);
INIT_LIST_HEAD(&buf->vb.queue); INIT_LIST_HEAD(&buf->vb.queue);
} }
...@@ -1750,10 +1750,10 @@ static int sh_mobile_ceu_reqbufs(struct soc_camera_file *icf, ...@@ -1750,10 +1750,10 @@ static int sh_mobile_ceu_reqbufs(struct soc_camera_file *icf,
static unsigned int sh_mobile_ceu_poll(struct file *file, poll_table *pt) static unsigned int sh_mobile_ceu_poll(struct file *file, poll_table *pt)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct sh_mobile_ceu_buffer *buf; struct sh_mobile_ceu_buffer *buf;
buf = list_entry(icf->vb_vidq.stream.next, buf = list_entry(icd->vb_vidq.stream.next,
struct sh_mobile_ceu_buffer, vb.stream); struct sh_mobile_ceu_buffer, vb.stream);
poll_wait(file, &buf->vb.done, pt); poll_wait(file, &buf->vb.done, pt);
......
...@@ -92,8 +92,7 @@ EXPORT_SYMBOL(soc_camera_apply_sensor_flags); ...@@ -92,8 +92,7 @@ EXPORT_SYMBOL(soc_camera_apply_sensor_flags);
static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f) struct v4l2_format *f)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
WARN_ON(priv != file->private_data); WARN_ON(priv != file->private_data);
...@@ -105,8 +104,7 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv, ...@@ -105,8 +104,7 @@ static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
static int soc_camera_enum_input(struct file *file, void *priv, static int soc_camera_enum_input(struct file *file, void *priv,
struct v4l2_input *inp) struct v4l2_input *inp)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
int ret = 0; int ret = 0;
if (inp->index != 0) if (inp->index != 0)
...@@ -141,8 +139,7 @@ static int soc_camera_s_input(struct file *file, void *priv, unsigned int i) ...@@ -141,8 +139,7 @@ static int soc_camera_s_input(struct file *file, void *priv, unsigned int i)
static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a) 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 = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
return v4l2_subdev_call(sd, core, s_std, *a); return v4l2_subdev_call(sd, core, s_std, *a);
...@@ -152,47 +149,59 @@ static int soc_camera_reqbufs(struct file *file, void *priv, ...@@ -152,47 +149,59 @@ static int soc_camera_reqbufs(struct file *file, void *priv,
struct v4l2_requestbuffers *p) struct v4l2_requestbuffers *p)
{ {
int ret; int ret;
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
WARN_ON(priv != file->private_data); 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) if (ret < 0)
return ret; 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, static int soc_camera_querybuf(struct file *file, void *priv,
struct v4l2_buffer *p) 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); 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, static int soc_camera_qbuf(struct file *file, void *priv,
struct v4l2_buffer *p) 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); 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, static int soc_camera_dqbuf(struct file *file, void *priv,
struct v4l2_buffer *p) 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); 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 */ /* Always entered with .video_lock held */
...@@ -280,10 +289,9 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd) ...@@ -280,10 +289,9 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd)
((x) >> 24) & 0xff ((x) >> 24) & 0xff
/* Called with .vb_lock held, or from the first open(2), see comment there */ /* 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 v4l2_format *f)
{ {
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_pix_format *pix = &f->fmt.pix;
int ret; int ret;
...@@ -309,7 +317,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, ...@@ -309,7 +317,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf,
icd->user_width = pix->width; icd->user_width = pix->width;
icd->user_height = pix->height; icd->user_height = pix->height;
icd->colorspace = pix->colorspace; icd->colorspace = pix->colorspace;
icf->vb_vidq.field = icd->vb_vidq.field =
icd->field = pix->field; icd->field = pix->field;
if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
...@@ -331,7 +339,6 @@ static int soc_camera_open(struct file *file) ...@@ -331,7 +339,6 @@ static int soc_camera_open(struct file *file)
dev); dev);
struct soc_camera_link *icl = to_soc_camera_link(icd); struct soc_camera_link *icl = to_soc_camera_link(icd);
struct soc_camera_host *ici; struct soc_camera_host *ici;
struct soc_camera_file *icf;
int ret; int ret;
if (!icd->ops) if (!icd->ops)
...@@ -340,14 +347,9 @@ static int soc_camera_open(struct file *file) ...@@ -340,14 +347,9 @@ static int soc_camera_open(struct file *file)
ici = to_soc_camera_host(icd->dev.parent); ici = to_soc_camera_host(icd->dev.parent);
icf = vmalloc(sizeof(*icf));
if (!icf)
return -ENOMEM;
if (!try_module_get(ici->ops->owner)) { if (!try_module_get(ici->ops->owner)) {
dev_err(&icd->dev, "Couldn't lock capture bus driver.\n"); dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
ret = -EINVAL; return -EINVAL;
goto emgi;
} }
/* /*
...@@ -356,7 +358,6 @@ static int soc_camera_open(struct file *file) ...@@ -356,7 +358,6 @@ static int soc_camera_open(struct file *file)
*/ */
mutex_lock(&icd->video_lock); mutex_lock(&icd->video_lock);
icf->icd = icd;
icd->use_count++; icd->use_count++;
/* Now we really have to activate the camera */ /* Now we really have to activate the camera */
...@@ -401,15 +402,15 @@ static int soc_camera_open(struct file *file) ...@@ -401,15 +402,15 @@ static int soc_camera_open(struct file *file)
* apart from someone else calling open() simultaneously, but * apart from someone else calling open() simultaneously, but
* .video_lock is protecting us against it. * .video_lock is protecting us against it.
*/ */
ret = soc_camera_set_fmt(icf, &f); ret = soc_camera_set_fmt(icd, &f);
if (ret < 0) if (ret < 0)
goto esfmt; goto esfmt;
} }
file->private_data = icf; file->private_data = icd;
dev_dbg(&icd->dev, "camera device open\n"); 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); mutex_unlock(&icd->video_lock);
...@@ -430,15 +431,13 @@ static int soc_camera_open(struct file *file) ...@@ -430,15 +431,13 @@ static int soc_camera_open(struct file *file)
icd->use_count--; icd->use_count--;
mutex_unlock(&icd->video_lock); mutex_unlock(&icd->video_lock);
module_put(ici->ops->owner); module_put(ici->ops->owner);
emgi:
vfree(icf);
return ret; return ret;
} }
static int soc_camera_close(struct file *file) static int soc_camera_close(struct file *file)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
mutex_lock(&icd->video_lock); mutex_lock(&icd->video_lock);
...@@ -455,12 +454,13 @@ static int soc_camera_close(struct file *file) ...@@ -455,12 +454,13 @@ static int soc_camera_close(struct file *file)
icl->power(icd->pdev, 0); icl->power(icd->pdev, 0);
} }
if (icd->streamer == file)
icd->streamer = NULL;
mutex_unlock(&icd->video_lock); mutex_unlock(&icd->video_lock);
module_put(ici->ops->owner); module_put(ici->ops->owner);
vfree(icf);
dev_dbg(&icd->dev, "camera device close\n"); dev_dbg(&icd->dev, "camera device close\n");
return 0; return 0;
...@@ -469,8 +469,7 @@ static int soc_camera_close(struct file *file) ...@@ -469,8 +469,7 @@ static int soc_camera_close(struct file *file)
static ssize_t soc_camera_read(struct file *file, char __user *buf, static ssize_t soc_camera_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
int err = -EINVAL; int err = -EINVAL;
dev_err(&icd->dev, "camera device read not implemented\n"); dev_err(&icd->dev, "camera device read not implemented\n");
...@@ -480,13 +479,15 @@ static ssize_t soc_camera_read(struct file *file, char __user *buf, ...@@ -480,13 +479,15 @@ static ssize_t soc_camera_read(struct file *file, char __user *buf,
static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma) 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 = file->private_data;
struct soc_camera_device *icd = icf->icd;
int err; int err;
dev_dbg(&icd->dev, "mmap called, vma=0x%08lx\n", (unsigned long)vma); 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", dev_dbg(&icd->dev, "vma start=0x%08lx, size=%ld, ret=%d\n",
(unsigned long)vma->vm_start, (unsigned long)vma->vm_start,
...@@ -498,11 +499,13 @@ static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -498,11 +499,13 @@ static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma)
static unsigned int soc_camera_poll(struct file *file, poll_table *pt) 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 = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); 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"); dev_err(&icd->dev, "Trying to poll with no queued buffers!\n");
return POLLERR; return POLLERR;
} }
...@@ -523,24 +526,29 @@ static struct v4l2_file_operations soc_camera_fops = { ...@@ -523,24 +526,29 @@ static struct v4l2_file_operations soc_camera_fops = {
static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f) struct v4l2_format *f)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
int ret; int ret;
WARN_ON(priv != file->private_data); 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"); dev_err(&icd->dev, "S_FMT denied: queue initialised\n");
ret = -EBUSY; ret = -EBUSY;
goto unlock; goto unlock;
} }
ret = soc_camera_set_fmt(icf, f); ret = soc_camera_set_fmt(icd, f);
if (!ret && !icd->streamer)
icd->streamer = file;
unlock: unlock:
mutex_unlock(&icf->vb_vidq.vb_lock); mutex_unlock(&icd->vb_vidq.vb_lock);
return ret; return ret;
} }
...@@ -548,8 +556,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, ...@@ -548,8 +556,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f) struct v4l2_fmtdesc *f)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
const struct soc_mbus_pixelfmt *format; const struct soc_mbus_pixelfmt *format;
WARN_ON(priv != file->private_data); WARN_ON(priv != file->private_data);
...@@ -568,15 +575,14 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv, ...@@ -568,15 +575,14 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv,
static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f) struct v4l2_format *f)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct v4l2_pix_format *pix = &f->fmt.pix; struct v4l2_pix_format *pix = &f->fmt.pix;
WARN_ON(priv != file->private_data); WARN_ON(priv != file->private_data);
pix->width = icd->user_width; pix->width = icd->user_width;
pix->height = icd->user_height; 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->pixelformat = icd->current_fmt->host_fmt->fourcc;
pix->bytesperline = soc_mbus_bytes_per_line(pix->width, pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
icd->current_fmt->host_fmt); icd->current_fmt->host_fmt);
...@@ -592,8 +598,7 @@ static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv, ...@@ -592,8 +598,7 @@ static int soc_camera_g_fmt_vid_cap(struct file *file, void *priv,
static int soc_camera_querycap(struct file *file, void *priv, static int soc_camera_querycap(struct file *file, void *priv,
struct v4l2_capability *cap) struct v4l2_capability *cap)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
WARN_ON(priv != file->private_data); WARN_ON(priv != file->private_data);
...@@ -605,8 +610,7 @@ static int soc_camera_querycap(struct file *file, void *priv, ...@@ -605,8 +610,7 @@ static int soc_camera_querycap(struct file *file, void *priv,
static int soc_camera_streamon(struct file *file, void *priv, static int soc_camera_streamon(struct file *file, void *priv,
enum v4l2_buf_type i) enum v4l2_buf_type i)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
int ret; int ret;
...@@ -615,12 +619,15 @@ static int soc_camera_streamon(struct file *file, void *priv, ...@@ -615,12 +619,15 @@ static int soc_camera_streamon(struct file *file, void *priv,
if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL; return -EINVAL;
if (icd->streamer != file)
return -EBUSY;
mutex_lock(&icd->video_lock); mutex_lock(&icd->video_lock);
v4l2_subdev_call(sd, video, s_stream, 1); v4l2_subdev_call(sd, video, s_stream, 1);
/* This calls buf_queue from host driver's videobuf_queue_ops */ /* 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); mutex_unlock(&icd->video_lock);
...@@ -630,8 +637,7 @@ static int soc_camera_streamon(struct file *file, void *priv, ...@@ -630,8 +637,7 @@ static int soc_camera_streamon(struct file *file, void *priv,
static int soc_camera_streamoff(struct file *file, void *priv, static int soc_camera_streamoff(struct file *file, void *priv,
enum v4l2_buf_type i) enum v4l2_buf_type i)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
WARN_ON(priv != file->private_data); WARN_ON(priv != file->private_data);
...@@ -639,13 +645,16 @@ static int soc_camera_streamoff(struct file *file, void *priv, ...@@ -639,13 +645,16 @@ static int soc_camera_streamoff(struct file *file, void *priv,
if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL; return -EINVAL;
if (icd->streamer != file)
return -EBUSY;
mutex_lock(&icd->video_lock); mutex_lock(&icd->video_lock);
/* /*
* This calls buf_release from host driver's videobuf_queue_ops for all * This calls buf_release from host driver's videobuf_queue_ops for all
* remaining buffers. When the last buffer is freed, stop capture * 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); v4l2_subdev_call(sd, video, s_stream, 0);
...@@ -657,8 +666,7 @@ static int soc_camera_streamoff(struct file *file, void *priv, ...@@ -657,8 +666,7 @@ static int soc_camera_streamoff(struct file *file, void *priv,
static int soc_camera_queryctrl(struct file *file, void *priv, static int soc_camera_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *qc) struct v4l2_queryctrl *qc)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
int i; int i;
...@@ -689,8 +697,7 @@ static int soc_camera_queryctrl(struct file *file, void *priv, ...@@ -689,8 +697,7 @@ static int soc_camera_queryctrl(struct file *file, void *priv,
static int soc_camera_g_ctrl(struct file *file, void *priv, static int soc_camera_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl) struct v4l2_control *ctrl)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
int ret; int ret;
...@@ -709,8 +716,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv, ...@@ -709,8 +716,7 @@ static int soc_camera_g_ctrl(struct file *file, void *priv,
static int soc_camera_s_ctrl(struct file *file, void *priv, static int soc_camera_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl) struct v4l2_control *ctrl)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
int ret; int ret;
...@@ -729,8 +735,7 @@ static int soc_camera_s_ctrl(struct file *file, void *priv, ...@@ -729,8 +735,7 @@ static int soc_camera_s_ctrl(struct file *file, void *priv,
static int soc_camera_cropcap(struct file *file, void *fh, static int soc_camera_cropcap(struct file *file, void *fh,
struct v4l2_cropcap *a) struct v4l2_cropcap *a)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
return ici->ops->cropcap(icd, a); return ici->ops->cropcap(icd, a);
...@@ -739,14 +744,13 @@ static int soc_camera_cropcap(struct file *file, void *fh, ...@@ -739,14 +744,13 @@ static int soc_camera_cropcap(struct file *file, void *fh,
static int soc_camera_g_crop(struct file *file, void *fh, static int soc_camera_g_crop(struct file *file, void *fh,
struct v4l2_crop *a) struct v4l2_crop *a)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
int ret; int ret;
mutex_lock(&icf->vb_vidq.vb_lock); mutex_lock(&icd->vb_vidq.vb_lock);
ret = ici->ops->get_crop(icd, a); ret = ici->ops->get_crop(icd, a);
mutex_unlock(&icf->vb_vidq.vb_lock); mutex_unlock(&icd->vb_vidq.vb_lock);
return ret; return ret;
} }
...@@ -759,8 +763,7 @@ static int soc_camera_g_crop(struct file *file, void *fh, ...@@ -759,8 +763,7 @@ static int soc_camera_g_crop(struct file *file, void *fh,
static int soc_camera_s_crop(struct file *file, void *fh, static int soc_camera_s_crop(struct file *file, void *fh,
struct v4l2_crop *a) struct v4l2_crop *a)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct v4l2_rect *rect = &a->c; struct v4l2_rect *rect = &a->c;
struct v4l2_crop current_crop; struct v4l2_crop current_crop;
...@@ -773,7 +776,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, ...@@ -773,7 +776,7 @@ static int soc_camera_s_crop(struct file *file, void *fh,
rect->width, rect->height, rect->left, rect->top); rect->width, rect->height, rect->left, rect->top);
/* Cropping is allowed during a running capture, guard consistency */ /* 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 */ /* If get_crop fails, we'll let host and / or client drivers decide */
ret = ici->ops->get_crop(icd, &current_crop); ret = ici->ops->get_crop(icd, &current_crop);
...@@ -782,7 +785,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, ...@@ -782,7 +785,7 @@ static int soc_camera_s_crop(struct file *file, void *fh,
if (ret < 0) { if (ret < 0) {
dev_err(&icd->dev, dev_err(&icd->dev,
"S_CROP denied: getting current crop failed\n"); "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.width != current_crop.c.width ||
a->c.height != current_crop.c.height)) { a->c.height != current_crop.c.height)) {
dev_err(&icd->dev, dev_err(&icd->dev,
...@@ -792,7 +795,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, ...@@ -792,7 +795,7 @@ static int soc_camera_s_crop(struct file *file, void *fh,
ret = ici->ops->set_crop(icd, a); ret = ici->ops->set_crop(icd, a);
} }
mutex_unlock(&icf->vb_vidq.vb_lock); mutex_unlock(&icd->vb_vidq.vb_lock);
return ret; return ret;
} }
...@@ -800,8 +803,7 @@ static int soc_camera_s_crop(struct file *file, void *fh, ...@@ -800,8 +803,7 @@ static int soc_camera_s_crop(struct file *file, void *fh,
static int soc_camera_g_parm(struct file *file, void *fh, static int soc_camera_g_parm(struct file *file, void *fh,
struct v4l2_streamparm *a) struct v4l2_streamparm *a)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
if (ici->ops->get_parm) if (ici->ops->get_parm)
...@@ -813,8 +815,7 @@ static int soc_camera_g_parm(struct file *file, void *fh, ...@@ -813,8 +815,7 @@ static int soc_camera_g_parm(struct file *file, void *fh,
static int soc_camera_s_parm(struct file *file, void *fh, static int soc_camera_s_parm(struct file *file, void *fh,
struct v4l2_streamparm *a) struct v4l2_streamparm *a)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent); struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
if (ici->ops->set_parm) if (ici->ops->set_parm)
...@@ -826,8 +827,7 @@ static int soc_camera_s_parm(struct file *file, void *fh, ...@@ -826,8 +827,7 @@ static int soc_camera_s_parm(struct file *file, void *fh,
static int soc_camera_g_chip_ident(struct file *file, void *fh, static int soc_camera_g_chip_ident(struct file *file, void *fh,
struct v4l2_dbg_chip_ident *id) struct v4l2_dbg_chip_ident *id)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
return v4l2_subdev_call(sd, core, g_chip_ident, id); return v4l2_subdev_call(sd, core, g_chip_ident, id);
...@@ -837,8 +837,7 @@ static int soc_camera_g_chip_ident(struct file *file, void *fh, ...@@ -837,8 +837,7 @@ static int soc_camera_g_chip_ident(struct file *file, void *fh,
static int soc_camera_g_register(struct file *file, void *fh, static int soc_camera_g_register(struct file *file, void *fh,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
return v4l2_subdev_call(sd, core, g_register, reg); return v4l2_subdev_call(sd, core, g_register, reg);
...@@ -847,8 +846,7 @@ static int soc_camera_g_register(struct file *file, void *fh, ...@@ -847,8 +846,7 @@ static int soc_camera_g_register(struct file *file, void *fh,
static int soc_camera_s_register(struct file *file, void *fh, static int soc_camera_s_register(struct file *file, void *fh,
struct v4l2_dbg_register *reg) struct v4l2_dbg_register *reg)
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_device *icd = file->private_data;
struct soc_camera_device *icd = icf->icd;
struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
return v4l2_subdev_call(sd, core, s_register, reg); return v4l2_subdev_call(sd, core, s_register, reg);
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
extern struct bus_type soc_camera_bus_type; extern struct bus_type soc_camera_bus_type;
struct file;
struct soc_camera_device { struct soc_camera_device {
struct list_head list; struct list_head list;
struct device dev; struct device dev;
...@@ -41,10 +43,7 @@ struct soc_camera_device { ...@@ -41,10 +43,7 @@ struct soc_camera_device {
/* soc_camera.c private count. Only accessed with .video_lock held */ /* soc_camera.c private count. Only accessed with .video_lock held */
int use_count; int use_count;
struct mutex video_lock; /* Protects device data */ struct mutex video_lock; /* Protects device data */
}; struct file *streamer; /* stream owner */
struct soc_camera_file {
struct soc_camera_device *icd;
struct videobuf_queue vb_vidq; struct videobuf_queue vb_vidq;
}; };
...@@ -79,7 +78,7 @@ struct soc_camera_host_ops { ...@@ -79,7 +78,7 @@ struct soc_camera_host_ops {
int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *); int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *);
void (*init_videobuf)(struct videobuf_queue *, void (*init_videobuf)(struct videobuf_queue *,
struct soc_camera_device *); struct soc_camera_device *);
int (*reqbufs)(struct soc_camera_file *, struct v4l2_requestbuffers *); int (*reqbufs)(struct soc_camera_device *, struct v4l2_requestbuffers *);
int (*querycap)(struct soc_camera_host *, struct v4l2_capability *); int (*querycap)(struct soc_camera_host *, struct v4l2_capability *);
int (*set_bus_param)(struct soc_camera_device *, __u32); int (*set_bus_param)(struct soc_camera_device *, __u32);
int (*get_ctrl)(struct soc_camera_device *, struct v4l2_control *); int (*get_ctrl)(struct soc_camera_device *, struct v4l2_control *);
......
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