summaryrefslogtreecommitdiff
path: root/linux/drivers/media
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2008-04-08 16:28:58 -0300
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-08 16:28:58 -0300
commit3f31e29c6caef98850401b10ee2ba51c01ff969a (patch)
tree4ea68edd38e29d89210454939c973c5059b62030 /linux/drivers/media
parentac057ef9ae37eb5d78117f191f48bf532f7a2435 (diff)
parentc03a147c1c7804df6087513c653e2613e72aa407 (diff)
downloadmediapointer-dvb-s2-3f31e29c6caef98850401b10ee2ba51c01ff969a.tar.gz
mediapointer-dvb-s2-3f31e29c6caef98850401b10ee2ba51c01ff969a.tar.bz2
merge: http://linuxtv.org/hg/~tmerle/v4l-dvb
From: Mauro Carvalho Chehab <mchehab@infradead.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'linux/drivers/media')
-rw-r--r--linux/drivers/media/video/pxa_camera.c37
-rw-r--r--linux/drivers/media/video/soc_camera.c83
2 files changed, 85 insertions, 35 deletions
diff --git a/linux/drivers/media/video/pxa_camera.c b/linux/drivers/media/video/pxa_camera.c
index 4756699d1..bef3c9c79 100644
--- a/linux/drivers/media/video/pxa_camera.c
+++ b/linux/drivers/media/video/pxa_camera.c
@@ -803,20 +803,35 @@ static int pxa_camera_querycap(struct soc_camera_host *ici,
return 0;
}
-/* Should beallocated dynamically too, but we have only one. */
+static spinlock_t *pxa_camera_spinlock_alloc(struct soc_camera_file *icf)
+{
+ struct soc_camera_host *ici =
+ to_soc_camera_host(icf->icd->dev.parent);
+ struct pxa_camera_dev *pcdev = ici->priv;
+
+ return &pcdev->lock;
+}
+
+static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
+ .owner = THIS_MODULE,
+ .add = pxa_camera_add_device,
+ .remove = pxa_camera_remove_device,
+ .set_fmt_cap = pxa_camera_set_fmt_cap,
+ .try_fmt_cap = pxa_camera_try_fmt_cap,
+ .reqbufs = pxa_camera_reqbufs,
+ .poll = pxa_camera_poll,
+ .querycap = pxa_camera_querycap,
+ .try_bus_param = pxa_camera_try_bus_param,
+ .set_bus_param = pxa_camera_set_bus_param,
+ .spinlock_alloc = pxa_camera_spinlock_alloc,
+};
+
+/* Should be allocated dynamically too, but we have only one. */
static struct soc_camera_host pxa_soc_camera_host = {
.drv_name = PXA_CAM_DRV_NAME,
.vbq_ops = &pxa_videobuf_ops,
- .add = pxa_camera_add_device,
- .remove = pxa_camera_remove_device,
.msize = sizeof(struct pxa_buffer),
- .set_fmt_cap = pxa_camera_set_fmt_cap,
- .try_fmt_cap = pxa_camera_try_fmt_cap,
- .reqbufs = pxa_camera_reqbufs,
- .poll = pxa_camera_poll,
- .querycap = pxa_camera_querycap,
- .try_bus_param = pxa_camera_try_bus_param,
- .set_bus_param = pxa_camera_set_bus_param,
+ .ops = &pxa_soc_camera_host_ops,
};
static int pxa_camera_probe(struct platform_device *pdev)
@@ -912,7 +927,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
pxa_soc_camera_host.priv = pcdev;
pxa_soc_camera_host.dev.parent = &pdev->dev;
pxa_soc_camera_host.nr = pdev->id;
- err = soc_camera_host_register(&pxa_soc_camera_host, THIS_MODULE);
+ err = soc_camera_host_register(&pxa_soc_camera_host);
if (err)
goto exit_free_irq;
diff --git a/linux/drivers/media/video/soc_camera.c b/linux/drivers/media/video/soc_camera.c
index 4af38d444..1e9215788 100644
--- a/linux/drivers/media/video/soc_camera.c
+++ b/linux/drivers/media/video/soc_camera.c
@@ -76,12 +76,12 @@ static int soc_camera_try_fmt_cap(struct file *file, void *priv,
}
/* test physical bus parameters */
- ret = ici->try_bus_param(icd, f->fmt.pix.pixelformat);
+ ret = ici->ops->try_bus_param(icd, f->fmt.pix.pixelformat);
if (ret)
return ret;
/* limit format to hardware capabilities */
- ret = ici->try_fmt_cap(icd, f);
+ ret = ici->ops->try_fmt_cap(icd, f);
/* calculate missing fields */
f->fmt.pix.field = field;
@@ -143,7 +143,7 @@ static int soc_camera_reqbufs(struct file *file, void *priv,
if (ret < 0)
return ret;
- return ici->reqbufs(icf, p);
+ return ici->ops->reqbufs(icf, p);
return ret;
}
@@ -184,6 +184,7 @@ static int soc_camera_open(struct inode *inode, struct file *file)
struct soc_camera_device *icd;
struct soc_camera_host *ici;
struct soc_camera_file *icf;
+ spinlock_t *lock;
int ret;
icf = vmalloc(sizeof(*icf));
@@ -203,19 +204,25 @@ static int soc_camera_open(struct inode *inode, struct file *file)
goto emgd;
}
- if (!try_module_get(ici->owner)) {
+ if (!try_module_get(ici->ops->owner)) {
dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
ret = -EINVAL;
goto emgi;
}
- icd->use_count++;
-
icf->icd = icd;
+ icf->lock = ici->ops->spinlock_alloc(icf);
+ if (!icf->lock) {
+ ret = -ENOMEM;
+ goto esla;
+ }
+
+ icd->use_count++;
+
/* Now we really have to activate the camera */
if (icd->use_count == 1) {
- ret = ici->add(icd);
+ ret = ici->ops->add(icd);
if (ret < 0) {
dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
icd->use_count--;
@@ -229,8 +236,8 @@ static int soc_camera_open(struct inode *inode, struct file *file)
dev_dbg(&icd->dev, "camera device open\n");
/* We must pass NULL as dev pointer, then all pci_* dma operations
- * transform to normal dma_* ones. Do we need an irqlock? */
- videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, NULL,
+ * transform to normal dma_* ones. */
+ videobuf_queue_sg_init(&icf->vb_vidq, ici->vbq_ops, NULL, icf->lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
ici->msize, icd);
@@ -238,7 +245,12 @@ static int soc_camera_open(struct inode *inode, struct file *file)
/* All errors are entered with the video_lock held */
eiciadd:
- module_put(ici->owner);
+ lock = icf->lock;
+ icf->lock = NULL;
+ if (ici->ops->spinlock_free)
+ ici->ops->spinlock_free(lock);
+esla:
+ module_put(ici->ops->owner);
emgi:
module_put(icd->ops->owner);
emgd:
@@ -253,16 +265,20 @@ static int soc_camera_close(struct inode *inode, struct file *file)
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct video_device *vdev = icd->vdev;
+ spinlock_t *lock = icf->lock;
mutex_lock(&video_lock);
icd->use_count--;
if (!icd->use_count)
- ici->remove(icd);
+ ici->ops->remove(icd);
+ icf->lock = NULL;
+ if (ici->ops->spinlock_free)
+ ici->ops->spinlock_free(lock);
module_put(icd->ops->owner);
- module_put(ici->owner);
+ module_put(ici->ops->owner);
mutex_unlock(&video_lock);
- vfree(file->private_data);
+ vfree(icf);
dev_dbg(vdev->dev, "camera device close\n");
@@ -312,7 +328,7 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt)
return POLLERR;
}
- return ici->poll(file, pt);
+ return ici->ops->poll(file, pt);
}
@@ -356,7 +372,7 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv,
rect.top = icd->y_current;
rect.width = f->fmt.pix.width;
rect.height = f->fmt.pix.height;
- ret = ici->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect);
+ ret = ici->ops->set_fmt_cap(icd, f->fmt.pix.pixelformat, &rect);
if (ret < 0)
return ret;
@@ -372,7 +388,7 @@ static int soc_camera_s_fmt_cap(struct file *file, void *priv,
icd->width, icd->height);
/* set physical bus parameters */
- return ici->set_bus_param(icd, f->fmt.pix.pixelformat);
+ return ici->ops->set_bus_param(icd, f->fmt.pix.pixelformat);
}
static int soc_camera_enum_fmt_cap(struct file *file, void *priv,
@@ -426,7 +442,7 @@ static int soc_camera_querycap(struct file *file, void *priv,
WARN_ON(priv != file->private_data);
strlcpy(cap->driver, ici->drv_name, sizeof(cap->driver));
- return ici->querycap(ici, cap);
+ return ici->ops->querycap(ici, cap);
}
static int soc_camera_streamon(struct file *file, void *priv,
@@ -579,7 +595,7 @@ static int soc_camera_s_crop(struct file *file, void *fh,
if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
- ret = ici->set_fmt_cap(icd, 0, &a->c);
+ ret = ici->ops->set_fmt_cap(icd, 0, &a->c);
if (!ret) {
icd->width = a->c.width;
icd->height = a->c.height;
@@ -706,7 +722,7 @@ static int soc_camera_probe(struct device *dev)
/* We only call ->add() here to activate and probe the camera.
* We shall ->remove() and deactivate it immediately afterwards. */
- ret = ici->add(icd);
+ ret = ici->ops->add(icd);
if (ret < 0)
return ret;
@@ -720,7 +736,7 @@ static int soc_camera_probe(struct device *dev)
icd->exposure = qctrl ? qctrl->default_value :
(unsigned short)~0;
}
- ici->remove(icd);
+ ici->ops->remove(icd);
return ret;
}
@@ -762,12 +778,27 @@ static void dummy_release(struct device *dev)
{
}
-int soc_camera_host_register(struct soc_camera_host *ici, struct module *owner)
+static spinlock_t *spinlock_alloc(struct soc_camera_file *icf)
+{
+ spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
+
+ if (lock)
+ spin_lock_init(lock);
+
+ return lock;
+}
+
+static void spinlock_free(spinlock_t *lock)
+{
+ kfree(lock);
+}
+
+int soc_camera_host_register(struct soc_camera_host *ici)
{
int ret;
struct soc_camera_host *ix;
- if (!ici->vbq_ops || !ici->add || !ici->remove || !owner)
+ if (!ici->vbq_ops || !ici->ops->add || !ici->ops->remove)
return -EINVAL;
/* Number might be equal to the platform device ID */
@@ -785,7 +816,6 @@ int soc_camera_host_register(struct soc_camera_host *ici, struct module *owner)
list_add_tail(&ici->list, &hosts);
mutex_unlock(&list_lock);
- ici->owner = owner;
ici->dev.release = dummy_release;
ret = device_register(&ici->dev);
@@ -793,6 +823,11 @@ int soc_camera_host_register(struct soc_camera_host *ici, struct module *owner)
if (ret)
goto edevr;
+ if (!ici->ops->spinlock_alloc) {
+ ici->ops->spinlock_alloc = spinlock_alloc;
+ ici->ops->spinlock_free = spinlock_free;
+ }
+
scan_add_host(ici);
return 0;
@@ -819,7 +854,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
if (icd->dev.parent == &ici->dev) {
device_unregister(&icd->dev);
/* Not before device_unregister(), .remove
- * needs parent to call ici->remove() */
+ * needs parent to call ici->ops->remove() */
icd->dev.parent = NULL;
memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj));
}