* [PATCH 1/5] soc-camera: add a free_bus method to struct soc_camera_link
2009-04-15 12:17 [PATCH 0/5] soc-camera: convert to platform device Guennadi Liakhovetski
@ 2009-04-15 12:17 ` Guennadi Liakhovetski
2009-04-16 3:39 ` Eric Miao
2009-04-15 12:17 ` [PATCH 2/5] soc-camera: host-driver cleanup Guennadi Liakhovetski
` (6 subsequent siblings)
7 siblings, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-15 12:17 UTC (permalink / raw)
To: Linux Media Mailing List; +Cc: Sascha Hauer, eric miao, Robert Jarzmik
Currently pcm990 camera bus-width management functions request a GPIO and never
free it again. With this approach the GPIO extender driver cannot be unloaded
once camera drivers have been loaded, also unloading theb i2c-pxa bus driver
produces errors, because the GPIO extender driver cannot unregister properly.
Another problem is, that if camera drivers are once loaded before the GPIO
extender driver, the platform code marks the GPIO unavailable and only a reboot
helps to recover. Adding an explicit free_bus method and using it in mt9m001
and mt9v022 drivers fixes these problems.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
Eric, need your ack for the arch/arm/mach-pxa part. Sascha's wouldn't hurt
either:-)
arch/arm/mach-pxa/pcm990-baseboard.c | 23 ++++++++++++++++-------
drivers/media/video/mt9m001.c | 3 +++
drivers/media/video/mt9v022.c | 3 +++
include/media/soc_camera.h | 1 +
4 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 6c12b5a..9ce1ef2 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -380,12 +380,12 @@ static struct pca953x_platform_data pca9536_data = {
.gpio_base = NR_BUILTIN_GPIO,
};
-static int gpio_bus_switch;
+static int gpio_bus_switch = -EINVAL;
static int pcm990_camera_set_bus_param(struct soc_camera_link *link,
- unsigned long flags)
+ unsigned long flags)
{
- if (gpio_bus_switch <= 0) {
+ if (gpio_bus_switch < 0) {
if (flags == SOCAM_DATAWIDTH_10)
return 0;
else
@@ -404,25 +404,34 @@ static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link)
{
int ret;
- if (!gpio_bus_switch) {
+ if (gpio_bus_switch < 0) {
ret = gpio_request(NR_BUILTIN_GPIO, "camera");
if (!ret) {
gpio_bus_switch = NR_BUILTIN_GPIO;
gpio_direction_output(gpio_bus_switch, 0);
- } else
- gpio_bus_switch = -EINVAL;
+ }
}
- if (gpio_bus_switch > 0)
+ if (gpio_bus_switch >= 0)
return SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_10;
else
return SOCAM_DATAWIDTH_10;
}
+static void pcm990_camera_free_bus(struct soc_camera_link *link)
+{
+ if (gpio_bus_switch < 0)
+ return;
+
+ gpio_free(gpio_bus_switch);
+ gpio_bus_switch = -EINVAL;
+}
+
static struct soc_camera_link iclink = {
.bus_id = 0, /* Must match with the camera ID above */
.query_bus_param = pcm990_camera_query_bus_param,
.set_bus_param = pcm990_camera_set_bus_param,
+ .free_bus = pcm990_camera_free_bus,
};
/* Board I2C devices. */
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index 684f62f..3838ff7 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -604,10 +604,13 @@ ei2c:
static void mt9m001_video_remove(struct soc_camera_device *icd)
{
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr,
icd->dev.parent, icd->vdev);
soc_camera_video_stop(icd);
+ if (icl->free_bus)
+ icl->free_bus(icl);
}
static int mt9m001_probe(struct i2c_client *client,
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index 4d3b481..412b399 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -735,10 +735,13 @@ ei2c:
static void mt9v022_video_remove(struct soc_camera_device *icd)
{
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr,
icd->dev.parent, icd->vdev);
soc_camera_video_stop(icd);
+ if (icl->free_bus)
+ icl->free_bus(icl);
}
static int mt9v022_probe(struct i2c_client *client,
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 3701368..396c325 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -107,6 +107,7 @@ struct soc_camera_link {
*/
int (*set_bus_param)(struct soc_camera_link *, unsigned long flags);
unsigned long (*query_bus_param)(struct soc_camera_link *);
+ void (*free_bus)(struct soc_camera_link *);
};
static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev)
--
1.5.4
^ permalink raw reply related [flat|nested] 46+ messages in thread* Re: [PATCH 1/5] soc-camera: add a free_bus method to struct soc_camera_link
2009-04-15 12:17 ` [PATCH 1/5] soc-camera: add a free_bus method to struct soc_camera_link Guennadi Liakhovetski
@ 2009-04-16 3:39 ` Eric Miao
0 siblings, 0 replies; 46+ messages in thread
From: Eric Miao @ 2009-04-16 3:39 UTC (permalink / raw)
To: Guennadi Liakhovetski
Cc: Linux Media Mailing List, Sascha Hauer, Robert Jarzmik
On Wed, Apr 15, 2009 at 8:17 PM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> Currently pcm990 camera bus-width management functions request a GPIO and never
> free it again. With this approach the GPIO extender driver cannot be unloaded
> once camera drivers have been loaded, also unloading theb i2c-pxa bus driver
> produces errors, because the GPIO extender driver cannot unregister properly.
> Another problem is, that if camera drivers are once loaded before the GPIO
> extender driver, the platform code marks the GPIO unavailable and only a reboot
> helps to recover. Adding an explicit free_bus method and using it in mt9m001
> and mt9v022 drivers fixes these problems.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> ---
>
> Eric, need your ack for the arch/arm/mach-pxa part. Sascha's wouldn't hurt
> either:-)
>
Yes, the mach-pxa/ part looks OK to me.
Acked-by: Eric Miao <eric.miao@marvell.com>
^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH 2/5] soc-camera: host-driver cleanup
2009-04-15 12:17 [PATCH 0/5] soc-camera: convert to platform device Guennadi Liakhovetski
2009-04-15 12:17 ` [PATCH 1/5] soc-camera: add a free_bus method to struct soc_camera_link Guennadi Liakhovetski
@ 2009-04-15 12:17 ` Guennadi Liakhovetski
2009-04-15 20:36 ` Robert Jarzmik
2009-04-15 12:18 ` [PATCH 3/5] soc-camera: remove an extra device generation from struct soc_camera_host Guennadi Liakhovetski
` (5 subsequent siblings)
7 siblings, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-15 12:17 UTC (permalink / raw)
To: Linux Media Mailing List; +Cc: Robert Jarzmik
Embed struct soc_camera_host in platform-specific per host instance objects
instead of allocating them statically in drivers, use platform_[gs]et_drvdata
consistently, use resource_size().
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/media/video/mx1_camera.c | 21 ++++++++-----------
drivers/media/video/mx3_camera.c | 2 +-
drivers/media/video/pxa_camera.c | 29 ++++++++++++---------------
drivers/media/video/sh_mobile_ceu_camera.c | 6 ++--
4 files changed, 26 insertions(+), 32 deletions(-)
diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c
index 86fab56..48dd984 100644
--- a/drivers/media/video/mx1_camera.c
+++ b/drivers/media/video/mx1_camera.c
@@ -102,6 +102,7 @@ struct mx1_buffer {
* Interface. If anyone ever builds hardware to enable more than
* one camera, they will have to modify this driver too */
struct mx1_camera_dev {
+ struct soc_camera_host soc_host;
struct soc_camera_device *icd;
struct mx1_camera_pdata *pdata;
struct mx1_buffer *active;
@@ -633,12 +634,6 @@ static struct soc_camera_host_ops mx1_soc_camera_host_ops = {
.querycap = mx1_camera_querycap,
};
-/* Should be allocated dynamically too, but we have only one. */
-static struct soc_camera_host mx1_soc_camera_host = {
- .drv_name = DRIVER_NAME,
- .ops = &mx1_soc_camera_host_ops,
-};
-
static struct fiq_handler fh = {
.name = "csi_sof"
};
@@ -673,7 +668,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev)
goto exit_put_clk;
}
- dev_set_drvdata(&pdev->dev, pcdev);
+ platform_set_drvdata(pdev, pcdev);
pcdev->res = res;
pcdev->clk = clk;
@@ -746,10 +741,12 @@ static int __init mx1_camera_probe(struct platform_device *pdev)
mxc_set_irq_fiq(irq, 1);
enable_fiq(irq);
- mx1_soc_camera_host.priv = pcdev;
- mx1_soc_camera_host.dev.parent = &pdev->dev;
- mx1_soc_camera_host.nr = pdev->id;
- err = soc_camera_host_register(&mx1_soc_camera_host);
+ pcdev->soc_host.drv_name = DRIVER_NAME;
+ pcdev->soc_host.ops = &mx1_soc_camera_host_ops;
+ pcdev->soc_host.priv = pcdev;
+ pcdev->soc_host.dev.parent = &pdev->dev;
+ pcdev->soc_host.nr = pdev->id;
+ err = soc_camera_host_register(&pcdev->soc_host);
if (err)
goto exit_free_irq;
@@ -787,7 +784,7 @@ static int __exit mx1_camera_remove(struct platform_device *pdev)
clk_put(pcdev->clk);
- soc_camera_host_unregister(&mx1_soc_camera_host);
+ soc_camera_host_unregister(&pcdev->soc_host);
iounmap(pcdev->base);
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index c462b81..22c58dc 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -1106,7 +1106,7 @@ static int mx3_camera_probe(struct platform_device *pdev)
goto eclkget;
}
- dev_set_drvdata(&pdev->dev, mx3_cam);
+ platform_set_drvdata(pdev, mx3_cam);
mx3_cam->pdata = pdev->dev.platform_data;
mx3_cam->platform_flags = mx3_cam->pdata->flags;
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index c639845..ad0d58c 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -202,6 +202,7 @@ struct pxa_buffer {
};
struct pxa_camera_dev {
+ struct soc_camera_host soc_host;
struct device *dev;
/* PXA27x is only supposed to handle one camera on its Quick Capture
* interface. If anyone ever builds hardware to enable more than
@@ -1552,12 +1553,6 @@ static struct soc_camera_host_ops pxa_soc_camera_host_ops = {
.set_bus_param = pxa_camera_set_bus_param,
};
-/* 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,
- .ops = &pxa_soc_camera_host_ops,
-};
-
static int pxa_camera_probe(struct platform_device *pdev)
{
struct pxa_camera_dev *pcdev;
@@ -1586,7 +1581,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
goto exit_kfree;
}
- dev_set_drvdata(&pdev->dev, pcdev);
+ platform_set_drvdata(pdev, pcdev);
pcdev->res = res;
pcdev->pdata = pdev->dev.platform_data;
@@ -1616,13 +1611,13 @@ static int pxa_camera_probe(struct platform_device *pdev)
/*
* Request the regions.
*/
- if (!request_mem_region(res->start, res->end - res->start + 1,
+ if (!request_mem_region(res->start, resource_size(res),
PXA_CAM_DRV_NAME)) {
err = -EBUSY;
goto exit_clk;
}
- base = ioremap(res->start, res->end - res->start + 1);
+ base = ioremap(res->start, resource_size(res));
if (!base) {
err = -ENOMEM;
goto exit_release;
@@ -1670,10 +1665,12 @@ static int pxa_camera_probe(struct platform_device *pdev)
goto exit_free_dma;
}
- 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);
+ pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME;
+ pcdev->soc_host.ops = &pxa_soc_camera_host_ops;
+ pcdev->soc_host.priv = pcdev;
+ pcdev->soc_host.dev.parent = &pdev->dev;
+ pcdev->soc_host.nr = pdev->id;
+ err = soc_camera_host_register(&pcdev->soc_host);
if (err)
goto exit_free_irq;
@@ -1690,7 +1687,7 @@ exit_free_dma_y:
exit_iounmap:
iounmap(base);
exit_release:
- release_mem_region(res->start, res->end - res->start + 1);
+ release_mem_region(res->start, resource_size(res));
exit_clk:
clk_put(pcdev->clk);
exit_kfree:
@@ -1711,12 +1708,12 @@ static int __devexit pxa_camera_remove(struct platform_device *pdev)
pxa_free_dma(pcdev->dma_chans[2]);
free_irq(pcdev->irq, pcdev);
- soc_camera_host_unregister(&pxa_soc_camera_host);
+ soc_camera_host_unregister(&pcdev->soc_host);
iounmap(pcdev->base);
res = pcdev->res;
- release_mem_region(res->start, res->end - res->start + 1);
+ release_mem_region(res->start, resource_size(res));
kfree(pcdev);
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index b5e37a5..8e4a8fc 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -840,7 +840,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
goto exit_kfree;
}
- base = ioremap_nocache(res->start, res->end - res->start + 1);
+ base = ioremap_nocache(res->start, resource_size(res));
if (!base) {
err = -ENXIO;
dev_err(&pdev->dev, "Unable to ioremap CEU registers.\n");
@@ -856,7 +856,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
if (res) {
err = dma_declare_coherent_memory(&pdev->dev, res->start,
res->start,
- (res->end - res->start) + 1,
+ resource_size(res),
DMA_MEMORY_MAP |
DMA_MEMORY_EXCLUSIVE);
if (!err) {
@@ -865,7 +865,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
goto exit_iounmap;
}
- pcdev->video_limit = (res->end - res->start) + 1;
+ pcdev->video_limit = resource_size(res);
}
/* request irq */
--
1.5.4
^ permalink raw reply related [flat|nested] 46+ messages in thread* Re: [PATCH 2/5] soc-camera: host-driver cleanup
2009-04-15 12:17 ` [PATCH 2/5] soc-camera: host-driver cleanup Guennadi Liakhovetski
@ 2009-04-15 20:36 ` Robert Jarzmik
0 siblings, 0 replies; 46+ messages in thread
From: Robert Jarzmik @ 2009-04-15 20:36 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: Linux Media Mailing List
Guennadi Liakhovetski <g.liakhovetski@gmx.de> writes:
> Embed struct soc_camera_host in platform-specific per host instance objects
> instead of allocating them statically in drivers, use platform_[gs]et_drvdata
> consistently, use resource_size().
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
I you want it for pxa_camera part :
Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>
Cheers.
--
Robert
^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH 3/5] soc-camera: remove an extra device generation from struct soc_camera_host
2009-04-15 12:17 [PATCH 0/5] soc-camera: convert to platform device Guennadi Liakhovetski
2009-04-15 12:17 ` [PATCH 1/5] soc-camera: add a free_bus method to struct soc_camera_link Guennadi Liakhovetski
2009-04-15 12:17 ` [PATCH 2/5] soc-camera: host-driver cleanup Guennadi Liakhovetski
@ 2009-04-15 12:18 ` Guennadi Liakhovetski
2009-04-15 12:18 ` [PATCH 4/5] soc-camera: simplify register access routines in multiple sensor drivers Guennadi Liakhovetski
` (4 subsequent siblings)
7 siblings, 0 replies; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-15 12:18 UTC (permalink / raw)
To: Linux Media Mailing List; +Cc: Robert Jarzmik
Make camera devices direct children of host platform devices, move the
inheritance management into the soc_camera.c core driver.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/media/video/mx1_camera.c | 35 +++++-----
drivers/media/video/mx3_camera.c | 40 ++++++------
drivers/media/video/pxa_camera.c | 97 ++++++++++++++--------------
drivers/media/video/sh_mobile_ceu_camera.c | 21 +++---
drivers/media/video/soc_camera.c | 35 +++-------
include/media/soc_camera.h | 4 +-
6 files changed, 107 insertions(+), 125 deletions(-)
diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c
index 48dd984..2d07520 100644
--- a/drivers/media/video/mx1_camera.c
+++ b/drivers/media/video/mx1_camera.c
@@ -106,7 +106,6 @@ struct mx1_camera_dev {
struct soc_camera_device *icd;
struct mx1_camera_pdata *pdata;
struct mx1_buffer *active;
- struct device *dev;
struct resource *res;
struct clk *clk;
struct list_head capture;
@@ -220,7 +219,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev)
int ret;
if (unlikely(!pcdev->active)) {
- dev_err(pcdev->dev, "DMA End IRQ with no active buffer\n");
+ dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n");
return -EFAULT;
}
@@ -230,7 +229,7 @@ static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev)
vbuf->size, pcdev->res->start +
CSIRXR, DMA_MODE_READ);
if (unlikely(ret))
- dev_err(pcdev->dev, "Failed to setup DMA sg list\n");
+ dev_err(pcdev->soc_host.dev, "Failed to setup DMA sg list\n");
return ret;
}
@@ -339,14 +338,14 @@ static void mx1_camera_dma_irq(int channel, void *data)
imx_dma_disable(channel);
if (unlikely(!pcdev->active)) {
- dev_err(pcdev->dev, "DMA End IRQ with no active buffer\n");
+ dev_err(pcdev->soc_host.dev, "DMA End IRQ with no active buffer\n");
goto out;
}
vb = &pcdev->active->vb;
buf = container_of(vb, struct mx1_buffer, vb);
WARN_ON(buf->inwork || list_empty(&vb->queue));
- dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
+ dev_dbg(pcdev->soc_host.dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
vb, vb->baddr, vb->bsize);
mx1_camera_wakeup(pcdev, vb, buf);
@@ -367,7 +366,7 @@ static void mx1_camera_init_videobuf(struct videobuf_queue *q,
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct mx1_camera_dev *pcdev = ici->priv;
- videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, pcdev->dev,
+ videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, ici->dev,
&pcdev->lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_NONE,
@@ -386,7 +385,7 @@ static int mclk_get_divisor(struct mx1_camera_dev *pcdev)
* they get a nice Oops */
div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1;
- dev_dbg(pcdev->dev, "System clock %lukHz, target freq %dkHz, "
+ dev_dbg(pcdev->soc_host.dev, "System clock %lukHz, target freq %dkHz, "
"divisor %lu\n", lcdclk / 1000, mclk / 1000, div);
return div;
@@ -396,7 +395,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev)
{
unsigned int csicr1 = CSICR1_EN;
- dev_dbg(pcdev->dev, "Activate device\n");
+ dev_dbg(pcdev->soc_host.dev, "Activate device\n");
clk_enable(pcdev->clk);
@@ -412,7 +411,7 @@ static void mx1_camera_activate(struct mx1_camera_dev *pcdev)
static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev)
{
- dev_dbg(pcdev->dev, "Deactivate device\n");
+ dev_dbg(pcdev->soc_host.dev, "Deactivate device\n");
/* Disable all CSI interface */
__raw_writel(0x00, pcdev->base + CSICR1);
@@ -551,7 +550,7 @@ static int mx1_camera_set_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
if (!xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat);
+ dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat);
return -EINVAL;
}
@@ -668,7 +667,6 @@ static int __init mx1_camera_probe(struct platform_device *pdev)
goto exit_put_clk;
}
- platform_set_drvdata(pdev, pcdev);
pcdev->res = res;
pcdev->clk = clk;
@@ -702,16 +700,15 @@ static int __init mx1_camera_probe(struct platform_device *pdev)
}
pcdev->irq = irq;
pcdev->base = base;
- pcdev->dev = &pdev->dev;
/* request dma */
pcdev->dma_chan = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_HIGH);
if (pcdev->dma_chan < 0) {
- dev_err(pcdev->dev, "Can't request DMA for MX1 CSI\n");
+ dev_err(&pdev->dev, "Can't request DMA for MX1 CSI\n");
err = -EBUSY;
goto exit_iounmap;
}
- dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chan);
+ dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chan);
imx_dma_setup_handlers(pcdev->dma_chan, mx1_camera_dma_irq, NULL,
pcdev);
@@ -724,7 +721,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev)
/* request irq */
err = claim_fiq(&fh);
if (err) {
- dev_err(pcdev->dev, "Camera interrupt register failed \n");
+ dev_err(&pdev->dev, "Camera interrupt register failed \n");
goto exit_free_dma;
}
@@ -744,7 +741,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev)
pcdev->soc_host.drv_name = DRIVER_NAME;
pcdev->soc_host.ops = &mx1_soc_camera_host_ops;
pcdev->soc_host.priv = pcdev;
- pcdev->soc_host.dev.parent = &pdev->dev;
+ pcdev->soc_host.dev = &pdev->dev;
pcdev->soc_host.nr = pdev->id;
err = soc_camera_host_register(&pcdev->soc_host);
if (err)
@@ -774,7 +771,9 @@ exit:
static int __exit mx1_camera_remove(struct platform_device *pdev)
{
- struct mx1_camera_dev *pcdev = platform_get_drvdata(pdev);
+ struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
+ struct mx1_camera_dev *pcdev = container_of(soc_host,
+ struct mx1_camera_dev, soc_host);
struct resource *res;
imx_dma_free(pcdev->dma_chan);
@@ -784,7 +783,7 @@ static int __exit mx1_camera_remove(struct platform_device *pdev)
clk_put(pcdev->clk);
- soc_camera_host_unregister(&pcdev->soc_host);
+ soc_camera_host_unregister(soc_host);
iounmap(pcdev->base);
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index 22c58dc..cb13faa 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -87,7 +87,6 @@ struct mx3_camera_buffer {
* @soc_host: embedded soc_host object
*/
struct mx3_camera_dev {
- struct device *dev;
/*
* i.MX3x is only supposed to handle one camera on its Camera Sensor
* Interface. If anyone ever builds hardware to enable more than one
@@ -431,7 +430,7 @@ static void mx3_camera_init_videobuf(struct videobuf_queue *q,
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct mx3_camera_dev *mx3_cam = ici->priv;
- videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, mx3_cam->dev,
+ videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, ici->dev,
&mx3_cam->lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_NONE,
@@ -599,7 +598,8 @@ static int test_platform_param(struct mx3_camera_dev *mx3_cam,
*flags |= SOCAM_DATAWIDTH_4;
break;
default:
- dev_info(mx3_cam->dev, "Unsupported bus width %d\n", buswidth);
+ dev_info(mx3_cam->soc_host.dev, "Unsupported bus width %d\n",
+ buswidth);
return -EINVAL;
}
@@ -614,7 +614,7 @@ static int mx3_camera_try_bus_param(struct soc_camera_device *icd,
unsigned long bus_flags, camera_flags;
int ret = test_platform_param(mx3_cam, depth, &bus_flags);
- dev_dbg(&ici->dev, "requested bus width %d bit: %d\n", depth, ret);
+ dev_dbg(ici->dev, "requested bus width %d bit: %d\n", depth, ret);
if (ret < 0)
return ret;
@@ -637,7 +637,7 @@ static bool chan_filter(struct dma_chan *chan, void *arg)
if (!rq)
return false;
- pdata = rq->mx3_cam->dev->platform_data;
+ pdata = rq->mx3_cam->soc_host.dev->platform_data;
return rq->id == chan->chan_id &&
pdata->dma_dev == chan->device->dev;
@@ -697,7 +697,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = buswidth;
xlate++;
- dev_dbg(&ici->dev, "Providing format %s using %s\n",
+ dev_dbg(ici->dev, "Providing format %s using %s\n",
mx3_camera_formats[0].name,
icd->formats[idx].name);
}
@@ -709,7 +709,7 @@ static int mx3_camera_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = buswidth;
xlate++;
- dev_dbg(&ici->dev, "Providing format %s using %s\n",
+ dev_dbg(ici->dev, "Providing format %s using %s\n",
mx3_camera_formats[0].name,
icd->formats[idx].name);
}
@@ -722,7 +722,7 @@ passthrough:
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = buswidth;
xlate++;
- dev_dbg(&ici->dev,
+ dev_dbg(ici->dev,
"Providing format %s in pass-through mode\n",
icd->formats[idx].name);
}
@@ -829,7 +829,7 @@ static int mx3_camera_set_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
if (!xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat);
+ dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat);
return -EINVAL;
}
@@ -866,7 +866,7 @@ static int mx3_camera_try_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (pixfmt && !xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+ dev_warn(ici->dev, "Format %x not found\n", pixfmt);
return -EINVAL;
}
@@ -933,11 +933,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (!xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+ dev_warn(ici->dev, "Format %x not found\n", pixfmt);
return -EINVAL;
}
- dev_dbg(&ici->dev, "requested bus width %d bit: %d\n",
+ dev_dbg(ici->dev, "requested bus width %d bit: %d\n",
icd->buswidth, ret);
if (ret < 0)
@@ -947,7 +947,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
if (!common_flags) {
- dev_dbg(&ici->dev, "no common flags: camera %lx, host %lx\n",
+ dev_dbg(ici->dev, "no common flags: camera %lx, host %lx\n",
camera_flags, bus_flags);
return -EINVAL;
}
@@ -1054,7 +1054,7 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
csi_reg_write(mx3_cam, sens_conf | dw, CSI_SENS_CONF);
- dev_dbg(&ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw);
+ dev_dbg(ici->dev, "Set SENS_CONF to %x\n", sens_conf | dw);
return 0;
}
@@ -1106,8 +1106,6 @@ static int mx3_camera_probe(struct platform_device *pdev)
goto eclkget;
}
- platform_set_drvdata(pdev, mx3_cam);
-
mx3_cam->pdata = pdev->dev.platform_data;
mx3_cam->platform_flags = mx3_cam->pdata->flags;
if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 |
@@ -1139,14 +1137,14 @@ static int mx3_camera_probe(struct platform_device *pdev)
}
mx3_cam->base = base;
- mx3_cam->dev = &pdev->dev;
soc_host = &mx3_cam->soc_host;
soc_host->drv_name = MX3_CAM_DRV_NAME;
soc_host->ops = &mx3_soc_camera_host_ops;
soc_host->priv = mx3_cam;
- soc_host->dev.parent = &pdev->dev;
+ soc_host->dev = &pdev->dev;
soc_host->nr = pdev->id;
+
err = soc_camera_host_register(soc_host);
if (err)
goto ecamhostreg;
@@ -1169,11 +1167,13 @@ egetres:
static int __devexit mx3_camera_remove(struct platform_device *pdev)
{
- struct mx3_camera_dev *mx3_cam = platform_get_drvdata(pdev);
+ struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
+ struct mx3_camera_dev *mx3_cam = container_of(soc_host,
+ struct mx3_camera_dev, soc_host);
clk_put(mx3_cam->clk);
- soc_camera_host_unregister(&mx3_cam->soc_host);
+ soc_camera_host_unregister(soc_host);
iounmap(mx3_cam->base);
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index ad0d58c..2da5eef 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -203,7 +203,6 @@ struct pxa_buffer {
struct pxa_camera_dev {
struct soc_camera_host soc_host;
- struct device *dev;
/* PXA27x is only supposed to handle one camera on its Quick Capture
* interface. If anyone ever builds hardware to enable more than
* one camera, they will have to modify this driver too */
@@ -262,7 +261,6 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
{
struct soc_camera_device *icd = vq->priv_data;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
- struct pxa_camera_dev *pcdev = ici->priv;
struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
int i;
@@ -279,7 +277,7 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
for (i = 0; i < ARRAY_SIZE(buf->dmas); i++) {
if (buf->dmas[i].sg_cpu)
- dma_free_coherent(pcdev->dev, buf->dmas[i].sg_size,
+ dma_free_coherent(ici->dev, buf->dmas[i].sg_size,
buf->dmas[i].sg_cpu,
buf->dmas[i].sg_dma);
buf->dmas[i].sg_cpu = NULL;
@@ -339,14 +337,14 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
int dma_len = 0, xfer_len = 0;
if (pxa_dma->sg_cpu)
- dma_free_coherent(pcdev->dev, pxa_dma->sg_size,
+ dma_free_coherent(pcdev->soc_host.dev, pxa_dma->sg_size,
pxa_dma->sg_cpu, pxa_dma->sg_dma);
sglen = calculate_dma_sglen(*sg_first, dma->sglen,
*sg_first_ofs, size);
pxa_dma->sg_size = (sglen + 1) * sizeof(struct pxa_dma_desc);
- pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->dev, pxa_dma->sg_size,
+ pxa_dma->sg_cpu = dma_alloc_coherent(pcdev->soc_host.dev, pxa_dma->sg_size,
&pxa_dma->sg_dma, GFP_KERNEL);
if (!pxa_dma->sg_cpu)
return -ENOMEM;
@@ -354,7 +352,7 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
pxa_dma->sglen = sglen;
offset = *sg_first_ofs;
- dev_dbg(pcdev->dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n",
+ dev_dbg(pcdev->soc_host.dev, "DMA: sg_first=%p, sglen=%d, ofs=%d, dma.desc=%x\n",
*sg_first, sglen, *sg_first_ofs, pxa_dma->sg_dma);
@@ -377,7 +375,7 @@ static int pxa_init_dma_channel(struct pxa_camera_dev *pcdev,
pxa_dma->sg_cpu[i].ddadr =
pxa_dma->sg_dma + (i + 1) * sizeof(struct pxa_dma_desc);
- dev_vdbg(pcdev->dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n",
+ dev_vdbg(pcdev->soc_host.dev, "DMA: desc.%08x->@phys=0x%08x, len=%d\n",
pxa_dma->sg_dma + i * sizeof(struct pxa_dma_desc),
sg_dma_address(sg) + offset, xfer_len);
offset = 0;
@@ -489,7 +487,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
ret = pxa_init_dma_channel(pcdev, buf, dma, 0, CIBR0, size_y,
&sg, &next_ofs);
if (ret) {
- dev_err(pcdev->dev,
+ dev_err(pcdev->soc_host.dev,
"DMA initialization for Y/RGB failed\n");
goto fail;
}
@@ -499,7 +497,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
ret = pxa_init_dma_channel(pcdev, buf, dma, 1, CIBR1,
size_u, &sg, &next_ofs);
if (ret) {
- dev_err(pcdev->dev,
+ dev_err(pcdev->soc_host.dev,
"DMA initialization for U failed\n");
goto fail_u;
}
@@ -509,7 +507,7 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
ret = pxa_init_dma_channel(pcdev, buf, dma, 2, CIBR2,
size_v, &sg, &next_ofs);
if (ret) {
- dev_err(pcdev->dev,
+ dev_err(pcdev->soc_host.dev,
"DMA initialization for V failed\n");
goto fail_v;
}
@@ -523,10 +521,10 @@ static int pxa_videobuf_prepare(struct videobuf_queue *vq,
return 0;
fail_v:
- dma_free_coherent(pcdev->dev, buf->dmas[1].sg_size,
+ dma_free_coherent(pcdev->soc_host.dev, buf->dmas[1].sg_size,
buf->dmas[1].sg_cpu, buf->dmas[1].sg_dma);
fail_u:
- dma_free_coherent(pcdev->dev, buf->dmas[0].sg_size,
+ dma_free_coherent(pcdev->soc_host.dev, buf->dmas[0].sg_size,
buf->dmas[0].sg_cpu, buf->dmas[0].sg_dma);
fail:
free_buffer(vq, buf);
@@ -550,7 +548,7 @@ static void pxa_dma_start_channels(struct pxa_camera_dev *pcdev)
active = pcdev->active;
for (i = 0; i < pcdev->channels; i++) {
- dev_dbg(pcdev->dev, "%s (channel=%d) ddadr=%08x\n", __func__,
+ dev_dbg(pcdev->soc_host.dev, "%s (channel=%d) ddadr=%08x\n", __func__,
i, active->dmas[i].sg_dma);
DDADR(pcdev->dma_chans[i]) = active->dmas[i].sg_dma;
DCSR(pcdev->dma_chans[i]) = DCSR_RUN;
@@ -562,7 +560,7 @@ static void pxa_dma_stop_channels(struct pxa_camera_dev *pcdev)
int i;
for (i = 0; i < pcdev->channels; i++) {
- dev_dbg(pcdev->dev, "%s (channel=%d)\n", __func__, i);
+ dev_dbg(pcdev->soc_host.dev, "%s (channel=%d)\n", __func__, i);
DCSR(pcdev->dma_chans[i]) = 0;
}
}
@@ -598,7 +596,7 @@ static void pxa_camera_start_capture(struct pxa_camera_dev *pcdev)
{
unsigned long cicr0, cifr;
- dev_dbg(pcdev->dev, "%s\n", __func__);
+ dev_dbg(pcdev->soc_host.dev, "%s\n", __func__);
/* Reset the FIFOs */
cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F;
__raw_writel(cifr, pcdev->base + CIFR);
@@ -618,7 +616,7 @@ static void pxa_camera_stop_capture(struct pxa_camera_dev *pcdev)
__raw_writel(cicr0, pcdev->base + CICR0);
pcdev->active = NULL;
- dev_dbg(pcdev->dev, "%s\n", __func__);
+ dev_dbg(pcdev->soc_host.dev, "%s\n", __func__);
}
static void pxa_videobuf_queue(struct videobuf_queue *vq,
@@ -687,7 +685,7 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
do_gettimeofday(&vb->ts);
vb->field_count++;
wake_up(&vb->done);
- dev_dbg(pcdev->dev, "%s dequeud buffer (vb=0x%p)\n", __func__, vb);
+ dev_dbg(pcdev->soc_host.dev, "%s dequeud buffer (vb=0x%p)\n", __func__, vb);
if (list_empty(&pcdev->capture)) {
pxa_camera_stop_capture(pcdev);
@@ -723,7 +721,7 @@ static void pxa_camera_check_link_miss(struct pxa_camera_dev *pcdev)
for (i = 0; i < pcdev->channels; i++)
if (DDADR(pcdev->dma_chans[i]) != DDADR_STOP)
is_dma_stopped = 0;
- dev_dbg(pcdev->dev, "%s : top queued buffer=%p, dma_stopped=%d\n",
+ dev_dbg(pcdev->soc_host.dev, "%s : top queued buffer=%p, dma_stopped=%d\n",
__func__, pcdev->active, is_dma_stopped);
if (pcdev->active && is_dma_stopped)
pxa_camera_start_capture(pcdev);
@@ -748,12 +746,12 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
overrun |= CISR_IFO_1 | CISR_IFO_2;
if (status & DCSR_BUSERR) {
- dev_err(pcdev->dev, "DMA Bus Error IRQ!\n");
+ dev_err(pcdev->soc_host.dev, "DMA Bus Error IRQ!\n");
goto out;
}
if (!(status & (DCSR_ENDINTR | DCSR_STARTINTR))) {
- dev_err(pcdev->dev, "Unknown DMA IRQ source, "
+ dev_err(pcdev->soc_host.dev, "Unknown DMA IRQ source, "
"status: 0x%08x\n", status);
goto out;
}
@@ -777,7 +775,7 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
buf = container_of(vb, struct pxa_buffer, vb);
WARN_ON(buf->inwork || list_empty(&vb->queue));
- dev_dbg(pcdev->dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n",
+ dev_dbg(pcdev->soc_host.dev, "%s channel=%d %s%s(vb=0x%p) dma.desc=%x\n",
__func__, channel, status & DCSR_STARTINTR ? "SOF " : "",
status & DCSR_ENDINTR ? "EOF " : "", vb, DDADR(channel));
@@ -788,7 +786,7 @@ static void pxa_camera_dma_irq(int channel, struct pxa_camera_dev *pcdev,
*/
if (camera_status & overrun &&
!list_is_last(pcdev->capture.next, &pcdev->capture)) {
- dev_dbg(pcdev->dev, "FIFO overrun! CISR: %x\n",
+ dev_dbg(pcdev->soc_host.dev, "FIFO overrun! CISR: %x\n",
camera_status);
pxa_camera_stop_capture(pcdev);
pxa_camera_start_capture(pcdev);
@@ -855,7 +853,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
/* mclk <= ciclk / 4 (27.4.2) */
if (mclk > lcdclk / 4) {
mclk = lcdclk / 4;
- dev_warn(pcdev->dev, "Limiting master clock to %lu\n", mclk);
+ dev_warn(pcdev->soc_host.dev, "Limiting master clock to %lu\n", mclk);
}
/* We verify mclk != 0, so if anyone breaks it, here comes their Oops */
@@ -865,7 +863,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
pcdev->mclk = lcdclk / (2 * (div + 1));
- dev_dbg(pcdev->dev, "LCD clock %luHz, target freq %luHz, "
+ dev_dbg(pcdev->soc_host.dev, "LCD clock %luHz, target freq %luHz, "
"divisor %u\n", lcdclk, mclk, div);
return div;
@@ -885,12 +883,12 @@ static void pxa_camera_activate(struct pxa_camera_dev *pcdev)
struct pxacamera_platform_data *pdata = pcdev->pdata;
u32 cicr4 = 0;
- dev_dbg(pcdev->dev, "Registered platform device at %p data %p\n",
+ dev_dbg(pcdev->soc_host.dev, "Registered platform device at %p data %p\n",
pcdev, pdata);
if (pdata && pdata->init) {
- dev_dbg(pcdev->dev, "%s: Init gpios\n", __func__);
- pdata->init(pcdev->dev);
+ dev_dbg(pcdev->soc_host.dev, "%s: Init gpios\n", __func__);
+ pdata->init(pcdev->soc_host.dev);
}
/* disable all interrupts */
@@ -932,7 +930,7 @@ static irqreturn_t pxa_camera_irq(int irq, void *data)
struct videobuf_buffer *vb;
status = __raw_readl(pcdev->base + CISR);
- dev_dbg(pcdev->dev, "Camera interrupt status 0x%lx\n", status);
+ dev_dbg(pcdev->soc_host.dev, "Camera interrupt status 0x%lx\n", status);
if (!status)
return IRQ_NONE;
@@ -1260,7 +1258,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = buswidth;
xlate++;
- dev_dbg(&ici->dev, "Providing format %s using %s\n",
+ dev_dbg(ici->dev, "Providing format %s using %s\n",
pxa_camera_formats[0].name,
icd->formats[idx].name);
}
@@ -1275,7 +1273,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = buswidth;
xlate++;
- dev_dbg(&ici->dev, "Providing format %s packed\n",
+ dev_dbg(ici->dev, "Providing format %s packed\n",
icd->formats[idx].name);
}
break;
@@ -1287,7 +1285,7 @@ static int pxa_camera_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = icd->formats[idx].depth;
xlate++;
- dev_dbg(&ici->dev,
+ dev_dbg(ici->dev,
"Providing format %s in pass-through mode\n",
icd->formats[idx].name);
}
@@ -1316,11 +1314,11 @@ static int pxa_camera_set_crop(struct soc_camera_device *icd,
icd->sense = NULL;
if (ret < 0) {
- dev_warn(&ici->dev, "Failed to crop to %ux%u@%u:%u\n",
+ dev_warn(ici->dev, "Failed to crop to %ux%u@%u:%u\n",
rect->width, rect->height, rect->left, rect->top);
} else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
if (sense.pixel_clock > sense.pixel_clock_max) {
- dev_err(&ici->dev,
+ dev_err(ici->dev,
"pixel clock %lu set by the camera too high!",
sense.pixel_clock);
return -EIO;
@@ -1348,7 +1346,7 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
if (!xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pix->pixelformat);
+ dev_warn(ici->dev, "Format %x not found\n", pix->pixelformat);
return -EINVAL;
}
@@ -1364,11 +1362,11 @@ static int pxa_camera_set_fmt(struct soc_camera_device *icd,
icd->sense = NULL;
if (ret < 0) {
- dev_warn(&ici->dev, "Failed to configure for format %x\n",
+ dev_warn(ici->dev, "Failed to configure for format %x\n",
pix->pixelformat);
} else if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {
if (sense.pixel_clock > sense.pixel_clock_max) {
- dev_err(&ici->dev,
+ dev_err(ici->dev,
"pixel clock %lu set by the camera too high!",
sense.pixel_clock);
return -EIO;
@@ -1396,7 +1394,7 @@ static int pxa_camera_try_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (!xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+ dev_warn(ici->dev, "Format %x not found\n", pixfmt);
return -EINVAL;
}
@@ -1581,7 +1579,6 @@ static int pxa_camera_probe(struct platform_device *pdev)
goto exit_kfree;
}
- platform_set_drvdata(pdev, pcdev);
pcdev->res = res;
pcdev->pdata = pdev->dev.platform_data;
@@ -1602,7 +1599,6 @@ static int pxa_camera_probe(struct platform_device *pdev)
pcdev->mclk = 20000000;
}
- pcdev->dev = &pdev->dev;
pcdev->mclk_divisor = mclk_get_divisor(pcdev);
INIT_LIST_HEAD(&pcdev->capture);
@@ -1629,29 +1625,29 @@ static int pxa_camera_probe(struct platform_device *pdev)
err = pxa_request_dma("CI_Y", DMA_PRIO_HIGH,
pxa_camera_dma_irq_y, pcdev);
if (err < 0) {
- dev_err(pcdev->dev, "Can't request DMA for Y\n");
+ dev_err(&pdev->dev, "Can't request DMA for Y\n");
goto exit_iounmap;
}
pcdev->dma_chans[0] = err;
- dev_dbg(pcdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
+ dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chans[0]);
err = pxa_request_dma("CI_U", DMA_PRIO_HIGH,
pxa_camera_dma_irq_u, pcdev);
if (err < 0) {
- dev_err(pcdev->dev, "Can't request DMA for U\n");
+ dev_err(&pdev->dev, "Can't request DMA for U\n");
goto exit_free_dma_y;
}
pcdev->dma_chans[1] = err;
- dev_dbg(pcdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
+ dev_dbg(&pdev->dev, "got DMA channel (U) %d\n", pcdev->dma_chans[1]);
err = pxa_request_dma("CI_V", DMA_PRIO_HIGH,
pxa_camera_dma_irq_v, pcdev);
if (err < 0) {
- dev_err(pcdev->dev, "Can't request DMA for V\n");
+ dev_err(&pdev->dev, "Can't request DMA for V\n");
goto exit_free_dma_u;
}
pcdev->dma_chans[2] = err;
- dev_dbg(pcdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
+ dev_dbg(&pdev->dev, "got DMA channel (V) %d\n", pcdev->dma_chans[2]);
DRCMR(68) = pcdev->dma_chans[0] | DRCMR_MAPVLD;
DRCMR(69) = pcdev->dma_chans[1] | DRCMR_MAPVLD;
@@ -1661,15 +1657,16 @@ static int pxa_camera_probe(struct platform_device *pdev)
err = request_irq(pcdev->irq, pxa_camera_irq, 0, PXA_CAM_DRV_NAME,
pcdev);
if (err) {
- dev_err(pcdev->dev, "Camera interrupt register failed \n");
+ dev_err(&pdev->dev, "Camera interrupt register failed \n");
goto exit_free_dma;
}
pcdev->soc_host.drv_name = PXA_CAM_DRV_NAME;
pcdev->soc_host.ops = &pxa_soc_camera_host_ops;
pcdev->soc_host.priv = pcdev;
- pcdev->soc_host.dev.parent = &pdev->dev;
+ pcdev->soc_host.dev = &pdev->dev;
pcdev->soc_host.nr = pdev->id;
+
err = soc_camera_host_register(&pcdev->soc_host);
if (err)
goto exit_free_irq;
@@ -1698,7 +1695,9 @@ exit:
static int __devexit pxa_camera_remove(struct platform_device *pdev)
{
- struct pxa_camera_dev *pcdev = platform_get_drvdata(pdev);
+ struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
+ struct pxa_camera_dev *pcdev = container_of(soc_host,
+ struct pxa_camera_dev, soc_host);
struct resource *res;
clk_put(pcdev->clk);
@@ -1708,7 +1707,7 @@ static int __devexit pxa_camera_remove(struct platform_device *pdev)
pxa_free_dma(pcdev->dma_chans[2]);
free_irq(pcdev->irq, pcdev);
- soc_camera_host_unregister(&pcdev->soc_host);
+ soc_camera_host_unregister(soc_host);
iounmap(pcdev->base);
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index 8e4a8fc..d369e84 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -81,7 +81,6 @@ struct sh_mobile_ceu_buffer {
};
struct sh_mobile_ceu_dev {
- struct device *dev;
struct soc_camera_host ici;
struct soc_camera_device *icd;
@@ -617,7 +616,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, int idx,
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = icd->formats[idx].depth;
xlate++;
- dev_dbg(&ici->dev, "Providing format %s using %s\n",
+ dev_dbg(ici->dev, "Providing format %s using %s\n",
sh_mobile_ceu_formats[k].name,
icd->formats[idx].name);
}
@@ -630,7 +629,7 @@ add_single_format:
xlate->cam_fmt = icd->formats + idx;
xlate->buswidth = icd->formats[idx].depth;
xlate++;
- dev_dbg(&ici->dev,
+ dev_dbg(ici->dev,
"Providing format %s in pass-through mode\n",
icd->formats[idx].name);
}
@@ -657,7 +656,7 @@ static int sh_mobile_ceu_set_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (!xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+ dev_warn(ici->dev, "Format %x not found\n", pixfmt);
return -EINVAL;
}
@@ -684,7 +683,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
if (!xlate) {
- dev_warn(&ici->dev, "Format %x not found\n", pixfmt);
+ dev_warn(ici->dev, "Format %x not found\n", pixfmt);
return -EINVAL;
}
@@ -782,7 +781,7 @@ static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q,
videobuf_queue_dma_contig_init(q,
&sh_mobile_ceu_videobuf_ops,
- &ici->dev, &pcdev->lock,
+ ici->dev, &pcdev->lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
pcdev->is_interlaced ?
V4L2_FIELD_INTERLACED : V4L2_FIELD_NONE,
@@ -829,7 +828,6 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
goto exit;
}
- platform_set_drvdata(pdev, pcdev);
INIT_LIST_HEAD(&pcdev->capture);
spin_lock_init(&pcdev->lock);
@@ -850,7 +848,6 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
pcdev->irq = irq;
pcdev->base = base;
pcdev->video_limit = 0; /* only enabled if second resource exists */
- pcdev->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (res) {
@@ -885,7 +882,7 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
}
pcdev->ici.priv = pcdev;
- pcdev->ici.dev.parent = &pdev->dev;
+ pcdev->ici.dev = &pdev->dev;
pcdev->ici.nr = pdev->id;
pcdev->ici.drv_name = dev_name(&pdev->dev);
pcdev->ici.ops = &sh_mobile_ceu_host_ops;
@@ -913,9 +910,11 @@ exit:
static int sh_mobile_ceu_remove(struct platform_device *pdev)
{
- struct sh_mobile_ceu_dev *pcdev = platform_get_drvdata(pdev);
+ struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
+ struct sh_mobile_ceu_dev *pcdev = container_of(soc_host,
+ struct sh_mobile_ceu_dev, ici);
- soc_camera_host_unregister(&pcdev->ici);
+ soc_camera_host_unregister(soc_host);
clk_put(pcdev->clk);
free_irq(pcdev->irq, pcdev);
if (platform_get_resource(pdev, IORESOURCE_MEM, 1))
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 0e890cc..03a6c29 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -279,7 +279,7 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf,
return ret;
} else if (!icd->current_fmt ||
icd->current_fmt->fourcc != pix->pixelformat) {
- dev_err(&ici->dev,
+ dev_err(ici->dev,
"Host driver hasn't set up current format correctly!\n");
return -EINVAL;
}
@@ -794,7 +794,7 @@ static void scan_add_host(struct soc_camera_host *ici)
list_for_each_entry(icd, &devices, list) {
if (icd->iface == ici->nr) {
- icd->dev.parent = &ici->dev;
+ icd->dev.parent = ici->dev;
device_register_link(icd);
}
}
@@ -818,7 +818,7 @@ static int scan_add_device(struct soc_camera_device *icd)
list_for_each_entry(ici, &hosts, list) {
if (icd->iface == ici->nr) {
ret = 1;
- icd->dev.parent = &ici->dev;
+ icd->dev.parent = ici->dev;
break;
}
}
@@ -952,7 +952,6 @@ static void dummy_release(struct device *dev)
int soc_camera_host_register(struct soc_camera_host *ici)
{
- int ret;
struct soc_camera_host *ix;
if (!ici || !ici->ops ||
@@ -965,12 +964,10 @@ int soc_camera_host_register(struct soc_camera_host *ici)
!ici->ops->reqbufs ||
!ici->ops->add ||
!ici->ops->remove ||
- !ici->ops->poll)
+ !ici->ops->poll ||
+ !ici->dev)
return -EINVAL;
- /* Number might be equal to the platform device ID */
- dev_set_name(&ici->dev, "camera_host%d", ici->nr);
-
mutex_lock(&list_lock);
list_for_each_entry(ix, &hosts, list) {
if (ix->nr == ici->nr) {
@@ -979,26 +976,14 @@ int soc_camera_host_register(struct soc_camera_host *ici)
}
}
+ dev_set_drvdata(ici->dev, ici);
+
list_add_tail(&ici->list, &hosts);
mutex_unlock(&list_lock);
- ici->dev.release = dummy_release;
-
- ret = device_register(&ici->dev);
-
- if (ret)
- goto edevr;
-
scan_add_host(ici);
return 0;
-
-edevr:
- mutex_lock(&list_lock);
- list_del(&ici->list);
- mutex_unlock(&list_lock);
-
- return ret;
}
EXPORT_SYMBOL(soc_camera_host_register);
@@ -1012,7 +997,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
list_del(&ici->list);
list_for_each_entry(icd, &devices, list) {
- if (icd->dev.parent == &ici->dev) {
+ if (icd->dev.parent == ici->dev) {
device_unregister(&icd->dev);
/* Not before device_unregister(), .remove
* needs parent to call ici->ops->remove() */
@@ -1023,7 +1008,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
mutex_unlock(&list_lock);
- device_unregister(&ici->dev);
+ dev_set_drvdata(ici->dev, NULL);
}
EXPORT_SYMBOL(soc_camera_host_unregister);
@@ -1130,7 +1115,7 @@ int soc_camera_video_start(struct soc_camera_device *icd)
vdev = video_device_alloc();
if (!vdev)
goto evidallocd;
- dev_dbg(&ici->dev, "Allocated video_device %p\n", vdev);
+ dev_dbg(ici->dev, "Allocated video_device %p\n", vdev);
strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 396c325..bef5e81 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -60,7 +60,7 @@ struct soc_camera_file {
struct soc_camera_host {
struct list_head list;
- struct device dev;
+ struct device *dev;
unsigned char nr; /* Host number */
void *priv;
const char *drv_name;
@@ -117,7 +117,7 @@ static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev)
static inline struct soc_camera_host *to_soc_camera_host(struct device *dev)
{
- return container_of(dev, struct soc_camera_host, dev);
+ return dev_get_drvdata(dev);
}
extern int soc_camera_host_register(struct soc_camera_host *ici);
--
1.5.4
^ permalink raw reply related [flat|nested] 46+ messages in thread* [PATCH 4/5] soc-camera: simplify register access routines in multiple sensor drivers
2009-04-15 12:17 [PATCH 0/5] soc-camera: convert to platform device Guennadi Liakhovetski
` (2 preceding siblings ...)
2009-04-15 12:18 ` [PATCH 3/5] soc-camera: remove an extra device generation from struct soc_camera_host Guennadi Liakhovetski
@ 2009-04-15 12:18 ` Guennadi Liakhovetski
2009-04-15 20:36 ` Robert Jarzmik
2009-04-15 12:20 ` [PATCH 5/5] soc-camera: Convert to a platform driver Guennadi Liakhovetski
` (3 subsequent siblings)
7 siblings, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-15 12:18 UTC (permalink / raw)
To: Linux Media Mailing List; +Cc: Robert Jarzmik
Register access routines only need the I2C client, not the soc-camera device
context.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/media/video/mt9m001.c | 105 +++++++++++++++++---------------
drivers/media/video/mt9m111.c | 73 ++++++++++++----------
drivers/media/video/mt9t031.c | 135 +++++++++++++++++++++-------------------
drivers/media/video/mt9v022.c | 135 +++++++++++++++++++++--------------------
4 files changed, 236 insertions(+), 212 deletions(-)
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index 3838ff7..459c04c 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -75,53 +75,50 @@ struct mt9m001 {
unsigned char autoexposure;
};
-static int reg_read(struct soc_camera_device *icd, const u8 reg)
+static int reg_read(struct i2c_client *client, const u8 reg)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct i2c_client *client = mt9m001->client;
s32 data = i2c_smbus_read_word_data(client, reg);
return data < 0 ? data : swab16(data);
}
-static int reg_write(struct soc_camera_device *icd, const u8 reg,
+static int reg_write(struct i2c_client *client, const u8 reg,
const u16 data)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- return i2c_smbus_write_word_data(mt9m001->client, reg, swab16(data));
+ return i2c_smbus_write_word_data(client, reg, swab16(data));
}
-static int reg_set(struct soc_camera_device *icd, const u8 reg,
+static int reg_set(struct i2c_client *client, const u8 reg,
const u16 data)
{
int ret;
- ret = reg_read(icd, reg);
+ ret = reg_read(client, reg);
if (ret < 0)
return ret;
- return reg_write(icd, reg, ret | data);
+ return reg_write(client, reg, ret | data);
}
-static int reg_clear(struct soc_camera_device *icd, const u8 reg,
+static int reg_clear(struct i2c_client *client, const u8 reg,
const u16 data)
{
int ret;
- ret = reg_read(icd, reg);
+ ret = reg_read(client, reg);
if (ret < 0)
return ret;
- return reg_write(icd, reg, ret & ~data);
+ return reg_write(client, reg, ret & ~data);
}
static int mt9m001_init(struct soc_camera_device *icd)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(icd->control);
+ struct soc_camera_link *icl = client->dev.platform_data;
int ret;
dev_dbg(icd->vdev->parent, "%s\n", __func__);
if (icl->power) {
- ret = icl->power(&mt9m001->client->dev, 1);
+ ret = icl->power(&client->dev, 1);
if (ret < 0) {
dev_err(icd->vdev->parent,
"Platform failed to power-on the camera.\n");
@@ -131,49 +128,53 @@ static int mt9m001_init(struct soc_camera_device *icd)
/* The camera could have been already on, we reset it additionally */
if (icl->reset)
- ret = icl->reset(&mt9m001->client->dev);
+ ret = icl->reset(&client->dev);
else
ret = -ENODEV;
if (ret < 0) {
/* Either no platform reset, or platform reset failed */
- ret = reg_write(icd, MT9M001_RESET, 1);
+ ret = reg_write(client, MT9M001_RESET, 1);
if (!ret)
- ret = reg_write(icd, MT9M001_RESET, 0);
+ ret = reg_write(client, MT9M001_RESET, 0);
}
/* Disable chip, synchronous option update */
if (!ret)
- ret = reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
+ ret = reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
return ret;
}
static int mt9m001_release(struct soc_camera_device *icd)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(icd->control);
+ struct soc_camera_link *icl = client->dev.platform_data;
/* Disable the chip */
- reg_write(icd, MT9M001_OUTPUT_CONTROL, 0);
+ reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
if (icl->power)
- icl->power(&mt9m001->client->dev, 0);
+ icl->power(&client->dev, 0);
return 0;
}
static int mt9m001_start_capture(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
+
/* Switch to master "normal" mode */
- if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 2) < 0)
+ if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0)
return -EIO;
return 0;
}
static int mt9m001_stop_capture(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
+
/* Stop sensor readout */
- if (reg_write(icd, MT9M001_OUTPUT_CONTROL, 0) < 0)
+ if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0)
return -EIO;
return 0;
}
@@ -222,28 +223,29 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
static int mt9m001_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
int ret;
const u16 hblank = 9, vblank = 25;
/* Blanking and start values - default... */
- ret = reg_write(icd, MT9M001_HORIZONTAL_BLANKING, hblank);
+ ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank);
if (!ret)
- ret = reg_write(icd, MT9M001_VERTICAL_BLANKING, vblank);
+ ret = reg_write(client, MT9M001_VERTICAL_BLANKING, vblank);
/* The caller provides a supported format, as verified per
* call to icd->try_fmt() */
if (!ret)
- ret = reg_write(icd, MT9M001_COLUMN_START, rect->left);
+ ret = reg_write(client, MT9M001_COLUMN_START, rect->left);
if (!ret)
- ret = reg_write(icd, MT9M001_ROW_START, rect->top);
+ ret = reg_write(client, MT9M001_ROW_START, rect->top);
if (!ret)
- ret = reg_write(icd, MT9M001_WINDOW_WIDTH, rect->width - 1);
+ ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect->width - 1);
if (!ret)
- ret = reg_write(icd, MT9M001_WINDOW_HEIGHT,
+ ret = reg_write(client, MT9M001_WINDOW_HEIGHT,
rect->height + icd->y_skip_top - 1);
if (!ret && mt9m001->autoexposure) {
- ret = reg_write(icd, MT9M001_SHUTTER_WIDTH,
+ ret = reg_write(client, MT9M001_SHUTTER_WIDTH,
rect->height + icd->y_skip_top + vblank);
if (!ret) {
const struct v4l2_queryctrl *qctrl =
@@ -312,16 +314,16 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd,
static int mt9m001_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match.addr != mt9m001->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
reg->size = 2;
- reg->val = reg_read(icd, reg->reg);
+ reg->val = reg_read(client, reg->reg);
if (reg->val > 0xffff)
return -EIO;
@@ -332,15 +334,15 @@ static int mt9m001_get_register(struct soc_camera_device *icd,
static int mt9m001_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match.addr != mt9m001->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
- if (reg_write(icd, reg->reg, reg->val) < 0)
+ if (reg_write(client, reg->reg, reg->val) < 0)
return -EIO;
return 0;
@@ -416,12 +418,13 @@ static struct soc_camera_ops mt9m001_ops = {
static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
int data;
switch (ctrl->id) {
case V4L2_CID_VFLIP:
- data = reg_read(icd, MT9M001_READ_OPTIONS2);
+ data = reg_read(client, MT9M001_READ_OPTIONS2);
if (data < 0)
return -EIO;
ctrl->value = !!(data & 0x8000);
@@ -435,6 +438,7 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro
static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
const struct v4l2_queryctrl *qctrl;
int data;
@@ -447,9 +451,9 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
switch (ctrl->id) {
case V4L2_CID_VFLIP:
if (ctrl->value)
- data = reg_set(icd, MT9M001_READ_OPTIONS2, 0x8000);
+ data = reg_set(client, MT9M001_READ_OPTIONS2, 0x8000);
else
- data = reg_clear(icd, MT9M001_READ_OPTIONS2, 0x8000);
+ data = reg_clear(client, MT9M001_READ_OPTIONS2, 0x8000);
if (data < 0)
return -EIO;
break;
@@ -463,7 +467,7 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
dev_dbg(&icd->dev, "Setting gain %d\n", data);
- data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
+ data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
if (data < 0)
return -EIO;
} else {
@@ -481,8 +485,8 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
data = ((gain - 64) * 7 + 28) / 56 + 96;
dev_dbg(&icd->dev, "Setting gain from %d to %d\n",
- reg_read(icd, MT9M001_GLOBAL_GAIN), data);
- data = reg_write(icd, MT9M001_GLOBAL_GAIN, data);
+ reg_read(client, MT9M001_GLOBAL_GAIN), data);
+ data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
if (data < 0)
return -EIO;
}
@@ -500,8 +504,8 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
range / 2) / range + 1;
dev_dbg(&icd->dev, "Setting shutter width from %d to %lu\n",
- reg_read(icd, MT9M001_SHUTTER_WIDTH), shutter);
- if (reg_write(icd, MT9M001_SHUTTER_WIDTH, shutter) < 0)
+ reg_read(client, MT9M001_SHUTTER_WIDTH), shutter);
+ if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0)
return -EIO;
icd->exposure = ctrl->value;
mt9m001->autoexposure = 0;
@@ -510,7 +514,7 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
case V4L2_CID_EXPOSURE_AUTO:
if (ctrl->value) {
const u16 vblank = 25;
- if (reg_write(icd, MT9M001_SHUTTER_WIDTH, icd->height +
+ if (reg_write(client, MT9M001_SHUTTER_WIDTH, icd->height +
icd->y_skip_top + vblank) < 0)
return -EIO;
qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
@@ -529,8 +533,9 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
* this wasn't our capture interface, so, we wait for the right one */
static int mt9m001_video_probe(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+ struct soc_camera_link *icl = client->dev.platform_data;
s32 data;
int ret;
unsigned long flags;
@@ -542,11 +547,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
return -ENODEV;
/* Enable the chip */
- data = reg_write(icd, MT9M001_CHIP_ENABLE, 1);
+ data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
dev_dbg(&icd->dev, "write: %d\n", data);
/* Read out the chip version register */
- data = reg_read(icd, MT9M001_CHIP_VERSION);
+ data = reg_read(client, MT9M001_CHIP_VERSION);
/* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
switch (data) {
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index cdd1ddb..fc5e2de 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -113,10 +113,10 @@
* mt9m111: Camera control register addresses (0x200..0x2ff not implemented)
*/
-#define reg_read(reg) mt9m111_reg_read(icd, MT9M111_##reg)
-#define reg_write(reg, val) mt9m111_reg_write(icd, MT9M111_##reg, (val))
-#define reg_set(reg, val) mt9m111_reg_set(icd, MT9M111_##reg, (val))
-#define reg_clear(reg, val) mt9m111_reg_clear(icd, MT9M111_##reg, (val))
+#define reg_read(reg) mt9m111_reg_read(client, MT9M111_##reg)
+#define reg_write(reg, val) mt9m111_reg_write(client, MT9M111_##reg, (val))
+#define reg_set(reg, val) mt9m111_reg_set(client, MT9M111_##reg, (val))
+#define reg_clear(reg, val) mt9m111_reg_clear(client, MT9M111_##reg, (val))
#define MT9M111_MIN_DARK_ROWS 8
#define MT9M111_MIN_DARK_COLS 24
@@ -184,58 +184,55 @@ static int reg_page_map_set(struct i2c_client *client, const u16 reg)
return ret;
}
-static int mt9m111_reg_read(struct soc_camera_device *icd, const u16 reg)
+static int mt9m111_reg_read(struct i2c_client *client, const u16 reg)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct i2c_client *client = mt9m111->client;
int ret;
ret = reg_page_map_set(client, reg);
if (!ret)
ret = swab16(i2c_smbus_read_word_data(client, (reg & 0xff)));
- dev_dbg(&icd->dev, "read reg.%03x -> %04x\n", reg, ret);
+ dev_dbg(&client->dev, "read reg.%03x -> %04x\n", reg, ret);
return ret;
}
-static int mt9m111_reg_write(struct soc_camera_device *icd, const u16 reg,
+static int mt9m111_reg_write(struct i2c_client *client, const u16 reg,
const u16 data)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct i2c_client *client = mt9m111->client;
int ret;
ret = reg_page_map_set(client, reg);
if (!ret)
- ret = i2c_smbus_write_word_data(mt9m111->client, (reg & 0xff),
+ ret = i2c_smbus_write_word_data(client, (reg & 0xff),
swab16(data));
- dev_dbg(&icd->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
+ dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
return ret;
}
-static int mt9m111_reg_set(struct soc_camera_device *icd, const u16 reg,
+static int mt9m111_reg_set(struct i2c_client *client, const u16 reg,
const u16 data)
{
int ret;
- ret = mt9m111_reg_read(icd, reg);
+ ret = mt9m111_reg_read(client, reg);
if (ret >= 0)
- ret = mt9m111_reg_write(icd, reg, ret | data);
+ ret = mt9m111_reg_write(client, reg, ret | data);
return ret;
}
-static int mt9m111_reg_clear(struct soc_camera_device *icd, const u16 reg,
+static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg,
const u16 data)
{
int ret;
- ret = mt9m111_reg_read(icd, reg);
- return mt9m111_reg_write(icd, reg, ret & ~data);
+ ret = mt9m111_reg_read(client, reg);
+ return mt9m111_reg_write(client, reg, ret & ~data);
}
static int mt9m111_set_context(struct soc_camera_device *icd,
enum mt9m111_context ctxt)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B
| MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B
| MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B
@@ -252,6 +249,7 @@ static int mt9m111_set_context(struct soc_camera_device *icd,
static int mt9m111_setup_rect(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
int ret, is_raw_format;
int width = rect->width;
@@ -296,6 +294,7 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd,
static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
int ret;
ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt);
@@ -357,12 +356,13 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
static int mt9m111_enable(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
+ struct soc_camera_link *icl = client->dev.platform_data;
int ret;
if (icl->power) {
- ret = icl->power(&mt9m111->client->dev, 1);
+ ret = icl->power(&client->dev, 1);
if (ret < 0) {
dev_err(icd->vdev->parent,
"Platform failed to power-on the camera.\n");
@@ -378,8 +378,9 @@ static int mt9m111_enable(struct soc_camera_device *icd)
static int mt9m111_disable(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
+ struct soc_camera_link *icl = client->dev.platform_data;
int ret;
ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE);
@@ -387,15 +388,15 @@ static int mt9m111_disable(struct soc_camera_device *icd)
mt9m111->powered = 0;
if (icl->power)
- icl->power(&mt9m111->client->dev, 0);
+ icl->power(&client->dev, 0);
return ret;
}
static int mt9m111_reset(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(icd->control);
+ struct soc_camera_link *icl = client->dev.platform_data;
int ret;
ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
@@ -406,7 +407,7 @@ static int mt9m111_reset(struct soc_camera_device *icd)
| MT9M111_RESET_RESET_SOC);
if (icl->reset)
- icl->reset(&mt9m111->client->dev);
+ icl->reset(&client->dev);
return ret;
}
@@ -562,15 +563,14 @@ static int mt9m111_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
int val;
-
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
return -EINVAL;
- if (reg->match.addr != mt9m111->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
- val = mt9m111_reg_read(icd, reg->reg);
+ val = mt9m111_reg_read(client, reg->reg);
reg->size = 2;
reg->val = (u64)val;
@@ -583,15 +583,15 @@ static int mt9m111_get_register(struct soc_camera_device *icd,
static int mt9m111_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
return -EINVAL;
- if (reg->match.addr != mt9m111->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
- if (mt9m111_reg_write(icd, reg->reg, reg->val) < 0)
+ if (mt9m111_reg_write(client, reg->reg, reg->val) < 0)
return -EIO;
return 0;
@@ -672,6 +672,7 @@ static struct soc_camera_ops mt9m111_ops = {
static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
int ret;
@@ -692,6 +693,7 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
static int mt9m111_get_global_gain(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
int data;
data = reg_read(GLOBAL_GAIN);
@@ -703,6 +705,7 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd)
static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
u16 val;
if (gain > 63 * 2 * 2)
@@ -721,6 +724,7 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
int ret;
@@ -737,6 +741,7 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
int ret;
@@ -754,6 +759,7 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
static int mt9m111_get_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
int data;
@@ -898,6 +904,7 @@ static int mt9m111_release(struct soc_camera_device *icd)
*/
static int mt9m111_video_probe(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
s32 data;
int ret;
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
index 2b0927b..f72aeb7 100644
--- a/drivers/media/video/mt9t031.c
+++ b/drivers/media/video/mt9t031.c
@@ -76,64 +76,61 @@ struct mt9t031 {
u16 yskip;
};
-static int reg_read(struct soc_camera_device *icd, const u8 reg)
+static int reg_read(struct i2c_client *client, const u8 reg)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
- struct i2c_client *client = mt9t031->client;
s32 data = i2c_smbus_read_word_data(client, reg);
return data < 0 ? data : swab16(data);
}
-static int reg_write(struct soc_camera_device *icd, const u8 reg,
+static int reg_write(struct i2c_client *client, const u8 reg,
const u16 data)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
- return i2c_smbus_write_word_data(mt9t031->client, reg, swab16(data));
+ return i2c_smbus_write_word_data(client, reg, swab16(data));
}
-static int reg_set(struct soc_camera_device *icd, const u8 reg,
+static int reg_set(struct i2c_client *client, const u8 reg,
const u16 data)
{
int ret;
- ret = reg_read(icd, reg);
+ ret = reg_read(client, reg);
if (ret < 0)
return ret;
- return reg_write(icd, reg, ret | data);
+ return reg_write(client, reg, ret | data);
}
-static int reg_clear(struct soc_camera_device *icd, const u8 reg,
+static int reg_clear(struct i2c_client *client, const u8 reg,
const u16 data)
{
int ret;
- ret = reg_read(icd, reg);
+ ret = reg_read(client, reg);
if (ret < 0)
return ret;
- return reg_write(icd, reg, ret & ~data);
+ return reg_write(client, reg, ret & ~data);
}
-static int set_shutter(struct soc_camera_device *icd, const u32 data)
+static int set_shutter(struct i2c_client *client, const u32 data)
{
int ret;
- ret = reg_write(icd, MT9T031_SHUTTER_WIDTH_UPPER, data >> 16);
+ ret = reg_write(client, MT9T031_SHUTTER_WIDTH_UPPER, data >> 16);
if (ret >= 0)
- ret = reg_write(icd, MT9T031_SHUTTER_WIDTH, data & 0xffff);
+ ret = reg_write(client, MT9T031_SHUTTER_WIDTH, data & 0xffff);
return ret;
}
-static int get_shutter(struct soc_camera_device *icd, u32 *data)
+static int get_shutter(struct i2c_client *client, u32 *data)
{
int ret;
- ret = reg_read(icd, MT9T031_SHUTTER_WIDTH_UPPER);
+ ret = reg_read(client, MT9T031_SHUTTER_WIDTH_UPPER);
*data = ret << 16;
if (ret >= 0)
- ret = reg_read(icd, MT9T031_SHUTTER_WIDTH);
+ ret = reg_read(client, MT9T031_SHUTTER_WIDTH);
*data |= ret & 0xffff;
return ret < 0 ? ret : 0;
@@ -141,12 +138,12 @@ static int get_shutter(struct soc_camera_device *icd, u32 *data)
static int mt9t031_init(struct soc_camera_device *icd)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
- struct soc_camera_link *icl = mt9t031->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(icd->control);
+ struct soc_camera_link *icl = client->dev.platform_data;
int ret;
if (icl->power) {
- ret = icl->power(&mt9t031->client->dev, 1);
+ ret = icl->power(&client->dev, 1);
if (ret < 0) {
dev_err(icd->vdev->parent,
"Platform failed to power-on the camera.\n");
@@ -155,44 +152,48 @@ static int mt9t031_init(struct soc_camera_device *icd)
}
/* Disable chip output, synchronous option update */
- ret = reg_write(icd, MT9T031_RESET, 1);
+ ret = reg_write(client, MT9T031_RESET, 1);
if (ret >= 0)
- ret = reg_write(icd, MT9T031_RESET, 0);
+ ret = reg_write(client, MT9T031_RESET, 0);
if (ret >= 0)
- ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2);
+ ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
if (ret < 0 && icl->power)
- icl->power(&mt9t031->client->dev, 0);
+ icl->power(&client->dev, 0);
return ret >= 0 ? 0 : -EIO;
}
static int mt9t031_release(struct soc_camera_device *icd)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
- struct soc_camera_link *icl = mt9t031->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(icd->control);
+ struct soc_camera_link *icl = client->dev.platform_data;
/* Disable the chip */
- reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2);
+ reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
if (icl->power)
- icl->power(&mt9t031->client->dev, 0);
+ icl->power(&client->dev, 0);
return 0;
}
static int mt9t031_start_capture(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
+
/* Switch to master "normal" mode */
- if (reg_set(icd, MT9T031_OUTPUT_CONTROL, 2) < 0)
+ if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
return -EIO;
return 0;
}
static int mt9t031_stop_capture(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
+
/* Stop sensor readout */
- if (reg_clear(icd, MT9T031_OUTPUT_CONTROL, 2) < 0)
+ if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
return -EIO;
return 0;
}
@@ -200,14 +201,16 @@ static int mt9t031_stop_capture(struct soc_camera_device *icd)
static int mt9t031_set_bus_param(struct soc_camera_device *icd,
unsigned long flags)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
+
/* The caller should have queried our parameters, check anyway */
if (flags & ~MT9T031_BUS_PARAM)
return -EINVAL;
if (flags & SOCAM_PCLK_SAMPLE_FALLING)
- reg_clear(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
+ reg_clear(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
else
- reg_set(icd, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
+ reg_set(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
return 0;
}
@@ -235,6 +238,7 @@ static void recalculate_limits(struct soc_camera_device *icd,
static int mt9t031_set_params(struct soc_camera_device *icd,
struct v4l2_rect *rect, u16 xskip, u16 yskip)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
int ret;
u16 xbin, ybin, width, height, left, top;
@@ -277,22 +281,22 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
}
/* Disable register update, reconfigure atomically */
- ret = reg_set(icd, MT9T031_OUTPUT_CONTROL, 1);
+ ret = reg_set(client, MT9T031_OUTPUT_CONTROL, 1);
if (ret < 0)
return ret;
/* Blanking and start values - default... */
- ret = reg_write(icd, MT9T031_HORIZONTAL_BLANKING, hblank);
+ ret = reg_write(client, MT9T031_HORIZONTAL_BLANKING, hblank);
if (ret >= 0)
- ret = reg_write(icd, MT9T031_VERTICAL_BLANKING, vblank);
+ ret = reg_write(client, MT9T031_VERTICAL_BLANKING, vblank);
if (yskip != mt9t031->yskip || xskip != mt9t031->xskip) {
/* Binning, skipping */
if (ret >= 0)
- ret = reg_write(icd, MT9T031_COLUMN_ADDRESS_MODE,
+ ret = reg_write(client, MT9T031_COLUMN_ADDRESS_MODE,
((xbin - 1) << 4) | (xskip - 1));
if (ret >= 0)
- ret = reg_write(icd, MT9T031_ROW_ADDRESS_MODE,
+ ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE,
((ybin - 1) << 4) | (yskip - 1));
}
dev_dbg(&icd->dev, "new physical left %u, top %u\n", left, top);
@@ -300,16 +304,16 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
/* The caller provides a supported format, as guaranteed by
* icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */
if (ret >= 0)
- ret = reg_write(icd, MT9T031_COLUMN_START, left);
+ ret = reg_write(client, MT9T031_COLUMN_START, left);
if (ret >= 0)
- ret = reg_write(icd, MT9T031_ROW_START, top);
+ ret = reg_write(client, MT9T031_ROW_START, top);
if (ret >= 0)
- ret = reg_write(icd, MT9T031_WINDOW_WIDTH, width - 1);
+ ret = reg_write(client, MT9T031_WINDOW_WIDTH, width - 1);
if (ret >= 0)
- ret = reg_write(icd, MT9T031_WINDOW_HEIGHT,
+ ret = reg_write(client, MT9T031_WINDOW_HEIGHT,
height + icd->y_skip_top - 1);
if (ret >= 0 && mt9t031->autoexposure) {
- ret = set_shutter(icd, height + icd->y_skip_top + vblank);
+ ret = set_shutter(client, height + icd->y_skip_top + vblank);
if (ret >= 0) {
const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
const struct v4l2_queryctrl *qctrl =
@@ -324,7 +328,7 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
/* Re-enable register update, commit all changes */
if (ret >= 0)
- ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1);
+ ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 1);
return ret < 0 ? ret : 0;
}
@@ -417,15 +421,15 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd,
static int mt9t031_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match.addr != mt9t031->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
- reg->val = reg_read(icd, reg->reg);
+ reg->val = reg_read(client, reg->reg);
if (reg->val > 0xffff)
return -EIO;
@@ -436,15 +440,15 @@ static int mt9t031_get_register(struct soc_camera_device *icd,
static int mt9t031_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match.addr != mt9t031->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
- if (reg_write(icd, reg->reg, reg->val) < 0)
+ if (reg_write(client, reg->reg, reg->val) < 0)
return -EIO;
return 0;
@@ -528,18 +532,19 @@ static struct soc_camera_ops mt9t031_ops = {
static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
int data;
switch (ctrl->id) {
case V4L2_CID_VFLIP:
- data = reg_read(icd, MT9T031_READ_MODE_2);
+ data = reg_read(client, MT9T031_READ_MODE_2);
if (data < 0)
return -EIO;
ctrl->value = !!(data & 0x8000);
break;
case V4L2_CID_HFLIP:
- data = reg_read(icd, MT9T031_READ_MODE_2);
+ data = reg_read(client, MT9T031_READ_MODE_2);
if (data < 0)
return -EIO;
ctrl->value = !!(data & 0x4000);
@@ -553,6 +558,7 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro
static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
const struct v4l2_queryctrl *qctrl;
int data;
@@ -565,17 +571,17 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
switch (ctrl->id) {
case V4L2_CID_VFLIP:
if (ctrl->value)
- data = reg_set(icd, MT9T031_READ_MODE_2, 0x8000);
+ data = reg_set(client, MT9T031_READ_MODE_2, 0x8000);
else
- data = reg_clear(icd, MT9T031_READ_MODE_2, 0x8000);
+ data = reg_clear(client, MT9T031_READ_MODE_2, 0x8000);
if (data < 0)
return -EIO;
break;
case V4L2_CID_HFLIP:
if (ctrl->value)
- data = reg_set(icd, MT9T031_READ_MODE_2, 0x4000);
+ data = reg_set(client, MT9T031_READ_MODE_2, 0x4000);
else
- data = reg_clear(icd, MT9T031_READ_MODE_2, 0x4000);
+ data = reg_clear(client, MT9T031_READ_MODE_2, 0x4000);
if (data < 0)
return -EIO;
break;
@@ -589,7 +595,7 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) / range;
dev_dbg(&icd->dev, "Setting gain %d\n", data);
- data = reg_write(icd, MT9T031_GLOBAL_GAIN, data);
+ data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
if (data < 0)
return -EIO;
} else {
@@ -609,8 +615,8 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
data = (((gain - 64 + 7) * 32) & 0xff00) | 0x60;
dev_dbg(&icd->dev, "Setting gain from 0x%x to 0x%x\n",
- reg_read(icd, MT9T031_GLOBAL_GAIN), data);
- data = reg_write(icd, MT9T031_GLOBAL_GAIN, data);
+ reg_read(client, MT9T031_GLOBAL_GAIN), data);
+ data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
if (data < 0)
return -EIO;
}
@@ -628,10 +634,10 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
range / 2) / range + 1;
u32 old;
- get_shutter(icd, &old);
+ get_shutter(client, &old);
dev_dbg(&icd->dev, "Setting shutter width from %u to %u\n",
old, shutter);
- if (set_shutter(icd, shutter) < 0)
+ if (set_shutter(client, shutter) < 0)
return -EIO;
icd->exposure = ctrl->value;
mt9t031->autoexposure = 0;
@@ -641,7 +647,7 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
if (ctrl->value) {
const u16 vblank = MT9T031_VERTICAL_BLANK;
const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
- if (set_shutter(icd, icd->height +
+ if (set_shutter(client, icd->height +
icd->y_skip_top + vblank) < 0)
return -EIO;
qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
@@ -661,6 +667,7 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
* this wasn't our capture interface, so, we wait for the right one */
static int mt9t031_video_probe(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
s32 data;
int ret;
@@ -672,11 +679,11 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
return -ENODEV;
/* Enable the chip */
- data = reg_write(icd, MT9T031_CHIP_ENABLE, 1);
+ data = reg_write(client, MT9T031_CHIP_ENABLE, 1);
dev_dbg(&icd->dev, "write: %d\n", data);
/* Read out the chip version register */
- data = reg_read(icd, MT9T031_CHIP_VERSION);
+ data = reg_read(client, MT9T031_CHIP_VERSION);
switch (data) {
case 0x1621:
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index 412b399..be20d31 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -91,51 +91,49 @@ struct mt9v022 {
u16 chip_control;
};
-static int reg_read(struct soc_camera_device *icd, const u8 reg)
+static int reg_read(struct i2c_client *client, const u8 reg)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct i2c_client *client = mt9v022->client;
s32 data = i2c_smbus_read_word_data(client, reg);
return data < 0 ? data : swab16(data);
}
-static int reg_write(struct soc_camera_device *icd, const u8 reg,
+static int reg_write(struct i2c_client *client, const u8 reg,
const u16 data)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- return i2c_smbus_write_word_data(mt9v022->client, reg, swab16(data));
+ return i2c_smbus_write_word_data(client, reg, swab16(data));
}
-static int reg_set(struct soc_camera_device *icd, const u8 reg,
+static int reg_set(struct i2c_client *client, const u8 reg,
const u16 data)
{
int ret;
- ret = reg_read(icd, reg);
+ ret = reg_read(client, reg);
if (ret < 0)
return ret;
- return reg_write(icd, reg, ret | data);
+ return reg_write(client, reg, ret | data);
}
-static int reg_clear(struct soc_camera_device *icd, const u8 reg,
+static int reg_clear(struct i2c_client *client, const u8 reg,
const u16 data)
{
int ret;
- ret = reg_read(icd, reg);
+ ret = reg_read(client, reg);
if (ret < 0)
return ret;
- return reg_write(icd, reg, ret & ~data);
+ return reg_write(client, reg, ret & ~data);
}
static int mt9v022_init(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+ struct soc_camera_link *icl = client->dev.platform_data;
int ret;
if (icl->power) {
- ret = icl->power(&mt9v022->client->dev, 1);
+ ret = icl->power(&client->dev, 1);
if (ret < 0) {
dev_err(icd->vdev->parent,
"Platform failed to power-on the camera.\n");
@@ -148,27 +146,27 @@ static int mt9v022_init(struct soc_camera_device *icd)
* if available. Soft reset is done in video_probe().
*/
if (icl->reset)
- icl->reset(&mt9v022->client->dev);
+ icl->reset(&client->dev);
/* Almost the default mode: master, parallel, simultaneous, and an
* undocumented bit 0x200, which is present in table 7, but not in 8,
* plus snapshot mode to disable scan for now */
mt9v022->chip_control |= 0x10;
- ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
+ ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
if (!ret)
- ret = reg_write(icd, MT9V022_READ_MODE, 0x300);
+ ret = reg_write(client, MT9V022_READ_MODE, 0x300);
/* All defaults */
if (!ret)
/* AEC, AGC on */
- ret = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x3);
+ ret = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x3);
if (!ret)
- ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
+ ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
if (!ret)
/* default - auto */
- ret = reg_clear(icd, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
+ ret = reg_clear(client, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
if (!ret)
- ret = reg_write(icd, MT9V022_DIGITAL_TEST_PATTERN, 0);
+ ret = reg_write(client, MT9V022_DIGITAL_TEST_PATTERN, 0);
return ret;
}
@@ -186,10 +184,11 @@ static int mt9v022_release(struct soc_camera_device *icd)
static int mt9v022_start_capture(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
/* Switch to master "normal" mode */
mt9v022->chip_control &= ~0x10;
- if (reg_write(icd, MT9V022_CHIP_CONTROL,
+ if (reg_write(client, MT9V022_CHIP_CONTROL,
mt9v022->chip_control) < 0)
return -EIO;
return 0;
@@ -197,10 +196,11 @@ static int mt9v022_start_capture(struct soc_camera_device *icd)
static int mt9v022_stop_capture(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
/* Switch to snapshot mode */
mt9v022->chip_control |= 0x10;
- if (reg_write(icd, MT9V022_CHIP_CONTROL,
+ if (reg_write(client, MT9V022_CHIP_CONTROL,
mt9v022->chip_control) < 0)
return -EIO;
return 0;
@@ -209,8 +209,9 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd)
static int mt9v022_set_bus_param(struct soc_camera_device *icd,
unsigned long flags)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+ struct soc_camera_link *icl = client->dev.platform_data;
unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
int ret;
u16 pixclk = 0;
@@ -243,14 +244,14 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd,
if (!(flags & SOCAM_VSYNC_ACTIVE_HIGH))
pixclk |= 0x2;
- ret = reg_write(icd, MT9V022_PIXCLK_FV_LV, pixclk);
+ ret = reg_write(client, MT9V022_PIXCLK_FV_LV, pixclk);
if (ret < 0)
return ret;
if (!(flags & SOCAM_MASTER))
mt9v022->chip_control &= ~0x8;
- ret = reg_write(icd, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
+ ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
if (ret < 0)
return ret;
@@ -282,35 +283,36 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
static int mt9v022_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
int ret;
/* Like in example app. Contradicts the datasheet though */
- ret = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
+ ret = reg_read(client, MT9V022_AEC_AGC_ENABLE);
if (ret >= 0) {
if (ret & 1) /* Autoexposure */
- ret = reg_write(icd, MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
+ ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
rect->height + icd->y_skip_top + 43);
else
- ret = reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH,
+ ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
rect->height + icd->y_skip_top + 43);
}
/* Setup frame format: defaults apart from width and height */
if (!ret)
- ret = reg_write(icd, MT9V022_COLUMN_START, rect->left);
+ ret = reg_write(client, MT9V022_COLUMN_START, rect->left);
if (!ret)
- ret = reg_write(icd, MT9V022_ROW_START, rect->top);
+ ret = reg_write(client, MT9V022_ROW_START, rect->top);
if (!ret)
/* Default 94, Phytec driver says:
* "width + horizontal blank >= 660" */
- ret = reg_write(icd, MT9V022_HORIZONTAL_BLANKING,
+ ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING,
rect->width > 660 - 43 ? 43 :
660 - rect->width);
if (!ret)
- ret = reg_write(icd, MT9V022_VERTICAL_BLANKING, 45);
+ ret = reg_write(client, MT9V022_VERTICAL_BLANKING, 45);
if (!ret)
- ret = reg_write(icd, MT9V022_WINDOW_WIDTH, rect->width);
+ ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect->width);
if (!ret)
- ret = reg_write(icd, MT9V022_WINDOW_HEIGHT,
+ ret = reg_write(client, MT9V022_WINDOW_HEIGHT,
rect->height + icd->y_skip_top);
if (ret < 0)
@@ -396,16 +398,16 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd,
static int mt9v022_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match.addr != mt9v022->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
reg->size = 2;
- reg->val = reg_read(icd, reg->reg);
+ reg->val = reg_read(client, reg->reg);
if (reg->val > 0xffff)
return -EIO;
@@ -416,15 +418,15 @@ static int mt9v022_get_register(struct soc_camera_device *icd,
static int mt9v022_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
- if (reg->match.addr != mt9v022->client->addr)
+ if (reg->match.addr != client->addr)
return -ENODEV;
- if (reg_write(icd, reg->reg, reg->val) < 0)
+ if (reg_write(client, reg->reg, reg->val) < 0)
return -EIO;
return 0;
@@ -517,29 +519,30 @@ static struct soc_camera_ops mt9v022_ops = {
static int mt9v022_get_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
int data;
switch (ctrl->id) {
case V4L2_CID_VFLIP:
- data = reg_read(icd, MT9V022_READ_MODE);
+ data = reg_read(client, MT9V022_READ_MODE);
if (data < 0)
return -EIO;
ctrl->value = !!(data & 0x10);
break;
case V4L2_CID_HFLIP:
- data = reg_read(icd, MT9V022_READ_MODE);
+ data = reg_read(client, MT9V022_READ_MODE);
if (data < 0)
return -EIO;
ctrl->value = !!(data & 0x20);
break;
case V4L2_CID_EXPOSURE_AUTO:
- data = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
+ data = reg_read(client, MT9V022_AEC_AGC_ENABLE);
if (data < 0)
return -EIO;
ctrl->value = !!(data & 0x1);
break;
case V4L2_CID_AUTOGAIN:
- data = reg_read(icd, MT9V022_AEC_AGC_ENABLE);
+ data = reg_read(client, MT9V022_AEC_AGC_ENABLE);
if (data < 0)
return -EIO;
ctrl->value = !!(data & 0x2);
@@ -552,6 +555,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
int data;
+ struct i2c_client *client = to_i2c_client(icd->control);
const struct v4l2_queryctrl *qctrl;
qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
@@ -562,17 +566,17 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
switch (ctrl->id) {
case V4L2_CID_VFLIP:
if (ctrl->value)
- data = reg_set(icd, MT9V022_READ_MODE, 0x10);
+ data = reg_set(client, MT9V022_READ_MODE, 0x10);
else
- data = reg_clear(icd, MT9V022_READ_MODE, 0x10);
+ data = reg_clear(client, MT9V022_READ_MODE, 0x10);
if (data < 0)
return -EIO;
break;
case V4L2_CID_HFLIP:
if (ctrl->value)
- data = reg_set(icd, MT9V022_READ_MODE, 0x20);
+ data = reg_set(client, MT9V022_READ_MODE, 0x20);
else
- data = reg_clear(icd, MT9V022_READ_MODE, 0x20);
+ data = reg_clear(client, MT9V022_READ_MODE, 0x20);
if (data < 0)
return -EIO;
break;
@@ -593,12 +597,12 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
/* The user wants to set gain manually, hope, she
* knows, what she's doing... Switch AGC off. */
- if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
+ if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
return -EIO;
dev_info(&icd->dev, "Setting gain from %d to %lu\n",
- reg_read(icd, MT9V022_ANALOG_GAIN), gain);
- if (reg_write(icd, MT9V022_ANALOG_GAIN, gain) < 0)
+ reg_read(client, MT9V022_ANALOG_GAIN), gain);
+ if (reg_write(client, MT9V022_ANALOG_GAIN, gain) < 0)
return -EIO;
icd->gain = ctrl->value;
}
@@ -614,13 +618,13 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
/* The user wants to set shutter width manually, hope,
* she knows, what she's doing... Switch AEC off. */
- if (reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1) < 0)
+ if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1) < 0)
return -EIO;
dev_dbg(&icd->dev, "Shutter width from %d to %lu\n",
- reg_read(icd, MT9V022_TOTAL_SHUTTER_WIDTH),
+ reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH),
shutter);
- if (reg_write(icd, MT9V022_TOTAL_SHUTTER_WIDTH,
+ if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
shutter) < 0)
return -EIO;
icd->exposure = ctrl->value;
@@ -628,17 +632,17 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
break;
case V4L2_CID_AUTOGAIN:
if (ctrl->value)
- data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x2);
+ data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x2);
else
- data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x2);
+ data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2);
if (data < 0)
return -EIO;
break;
case V4L2_CID_EXPOSURE_AUTO:
if (ctrl->value)
- data = reg_set(icd, MT9V022_AEC_AGC_ENABLE, 0x1);
+ data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x1);
else
- data = reg_clear(icd, MT9V022_AEC_AGC_ENABLE, 0x1);
+ data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1);
if (data < 0)
return -EIO;
break;
@@ -650,8 +654,9 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
* this wasn't our capture interface, so, we wait for the right one */
static int mt9v022_video_probe(struct soc_camera_device *icd)
{
+ struct i2c_client *client = to_i2c_client(icd->control);
struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+ struct soc_camera_link *icl = client->dev.platform_data;
s32 data;
int ret;
unsigned long flags;
@@ -661,7 +666,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
return -ENODEV;
/* Read out the chip version register */
- data = reg_read(icd, MT9V022_CHIP_VERSION);
+ data = reg_read(client, MT9V022_CHIP_VERSION);
/* must be 0x1311 or 0x1313 */
if (data != 0x1311 && data != 0x1313) {
@@ -672,12 +677,12 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
}
/* Soft reset */
- ret = reg_write(icd, MT9V022_RESET, 1);
+ ret = reg_write(client, MT9V022_RESET, 1);
if (ret < 0)
goto ei2c;
/* 15 clock cycles */
udelay(200);
- if (reg_read(icd, MT9V022_RESET)) {
+ if (reg_read(client, MT9V022_RESET)) {
dev_err(&icd->dev, "Resetting MT9V022 failed!\n");
goto ei2c;
}
@@ -685,11 +690,11 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
/* Set monochrome or colour sensor type */
if (sensor_type && (!strcmp("colour", sensor_type) ||
!strcmp("color", sensor_type))) {
- ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
+ ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
mt9v022->model = V4L2_IDENT_MT9V022IX7ATC;
icd->formats = mt9v022_colour_formats;
} else {
- ret = reg_write(icd, MT9V022_PIXEL_OPERATION_MODE, 0x11);
+ ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11);
mt9v022->model = V4L2_IDENT_MT9V022IX7ATM;
icd->formats = mt9v022_monochrome_formats;
}
--
1.5.4
^ permalink raw reply related [flat|nested] 46+ messages in thread* [PATCH 5/5] soc-camera: Convert to a platform driver
2009-04-15 12:17 [PATCH 0/5] soc-camera: convert to platform device Guennadi Liakhovetski
` (3 preceding siblings ...)
2009-04-15 12:18 ` [PATCH 4/5] soc-camera: simplify register access routines in multiple sensor drivers Guennadi Liakhovetski
@ 2009-04-15 12:20 ` Guennadi Liakhovetski
2009-04-15 20:36 ` Robert Jarzmik
2009-04-16 2:19 ` Dongsoo, Nathaniel Kim
2009-04-15 20:36 ` [PATCH 0/5] soc-camera: convert to platform device Robert Jarzmik
` (2 subsequent siblings)
7 siblings, 2 replies; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-15 12:20 UTC (permalink / raw)
To: Linux Media Mailing List; +Cc: Robert Jarzmik
Convert soc-camera core to a platform driver. With this approach I2C
devices are no longer statically registered in platform code, instead they
are registered dynamically by the soc-camera core, when a match with a
host driver is found. With this patch all platforms and all soc-camera
device drivers are converted too. This is a preparatory step for the
v4l-subdev conversion.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
Ok, here goes the bad guy. Hit it hard, hit it as hard as you can.
Robert, I addressed your wishes from your previous comments, but kept the
semicolon rearrangement hunk. I think, it is better not to terminate a
define with a semicolon, if you like, we can make this a separate patch.
arch/arm/mach-mx3/pcm037.c | 25 ++-
arch/arm/mach-pxa/em-x270.c | 21 ++-
arch/arm/mach-pxa/mioa701.c | 35 ++--
arch/arm/mach-pxa/pcm990-baseboard.c | 52 ++++-
arch/sh/boards/board-ap325rxa.c | 55 +++--
arch/sh/boards/mach-migor/setup.c | 77 ++++--
drivers/media/video/mt9m001.c | 113 ++++-----
drivers/media/video/mt9m111.c | 152 ++++++------
drivers/media/video/mt9t031.c | 113 ++++-----
drivers/media/video/mt9v022.c | 118 +++++-----
drivers/media/video/mx3_camera.c | 27 ++-
drivers/media/video/ov772x.c | 148 +++++++-----
drivers/media/video/pxa_camera.c | 27 ++-
drivers/media/video/sh_mobile_ceu_camera.c | 13 +-
drivers/media/video/soc_camera.c | 364 +++++++++++++++-------------
drivers/media/video/soc_camera_platform.c | 112 +++++----
drivers/media/video/tw9910.c | 106 +++++----
include/media/soc_camera.h | 30 ++-
include/media/soc_camera_platform.h | 5 +-
19 files changed, 894 insertions(+), 699 deletions(-)
diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c
index 6bfd29a..00ce1eb 100644
--- a/arch/arm/mach-mx3/pcm037.c
+++ b/arch/arm/mach-mx3/pcm037.c
@@ -241,9 +241,17 @@ static int pcm037_camera_power(struct device *dev, int on)
return 0;
}
+static struct i2c_board_info pcm037_i2c_2_devices[] = {
+ {
+ I2C_BOARD_INFO("mt9t031", 0x5d),
+ },
+};
+
static struct soc_camera_link iclink = {
- .bus_id = 0, /* Must match with the camera ID */
- .power = pcm037_camera_power,
+ .bus_id = 0, /* Must match with the camera ID */
+ .power = pcm037_camera_power,
+ .board_info = &pcm037_i2c_2_devices[0],
+ .i2c_adapter_id = 2,
};
static struct i2c_board_info pcm037_i2c_devices[] = {
@@ -256,9 +264,10 @@ static struct i2c_board_info pcm037_i2c_devices[] = {
}
};
-static struct i2c_board_info pcm037_i2c_2_devices[] = {
- {
- I2C_BOARD_INFO("mt9t031", 0x5d),
+static struct platform_device pcm037_camera = {
+ .name = "soc-camera-pdrv",
+ .id = 0,
+ .dev = {
.platform_data = &iclink,
},
};
@@ -338,6 +347,9 @@ static struct platform_device *devices[] __initdata = {
&pcm037_flash,
&pcm037_eth,
&pcm037_sram_device,
+#if defined(CONFIG_I2C_IMX) || defined(CONFIG_I2C_IMX_MODULE)
+ &pcm037_camera,
+#endif
};
static struct ipu_platform_data mx3_ipu_data = {
@@ -395,9 +407,6 @@ static void __init mxc_board_init(void)
i2c_register_board_info(1, pcm037_i2c_devices,
ARRAY_SIZE(pcm037_i2c_devices));
- i2c_register_board_info(2, pcm037_i2c_2_devices,
- ARRAY_SIZE(pcm037_i2c_2_devices));
-
mxc_register_device(&mxc_i2c_device1, &pcm037_i2c_1_data);
mxc_register_device(&mxc_i2c_device2, &pcm037_i2c_2_data);
#endif
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 920dfb8..d4eb0c7 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -847,14 +847,23 @@ static int em_x270_sensor_power(struct device *dev, int on)
return 0;
}
-static struct soc_camera_link iclink = {
- .bus_id = 0,
- .power = em_x270_sensor_power,
-};
-
static struct i2c_board_info em_x270_i2c_cam_info[] = {
{
I2C_BOARD_INFO("mt9m111", 0x48),
+ },
+};
+
+static struct soc_camera_link iclink = {
+ .bus_id = 0,
+ .power = em_x270_sensor_power,
+ .board_info = &em_x270_i2c_cam_info[0],
+ .i2c_adapter_id = 0,
+};
+
+static struct platform_device em_x270_camera = {
+ .name = "soc-camera-pdrv",
+ .id = -1,
+ .dev = {
.platform_data = &iclink,
},
};
@@ -866,8 +875,8 @@ static struct i2c_pxa_platform_data em_x270_i2c_info = {
static void __init em_x270_init_camera(void)
{
pxa_set_i2c_info(&em_x270_i2c_info);
- i2c_register_board_info(0, ARRAY_AND_SIZE(em_x270_i2c_cam_info));
pxa_set_camera_info(&em_x270_camera_platform_data);
+ platform_device_register(&em_x270_camera);
}
#else
static inline void em_x270_init_camera(void) {}
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index 97c93a7..444818b 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -724,19 +724,21 @@ struct pxacamera_platform_data mioa701_pxacamera_platform_data = {
.mclk_10khz = 5000,
};
-static struct soc_camera_link iclink = {
- .bus_id = 0, /* Must match id in pxa27x_device_camera in device.c */
-};
-
-/* Board I2C devices. */
+/*
+ * Board I2C devices
+ */
static struct i2c_board_info __initdata mioa701_i2c_devices[] = {
{
- /* Must initialize before the camera(s) */
I2C_BOARD_INFO("mt9m111", 0x5d),
- .platform_data = &iclink,
},
};
+static struct soc_camera_link iclink = {
+ .bus_id = 0, /* Match id in pxa27x_device_camera in device.c */
+ .board_info = &mioa701_i2c_devices[0],
+ .i2c_adapter_id = 0,
+};
+
struct i2c_pxa_platform_data i2c_pdata = {
.fast_mode = 1,
};
@@ -754,20 +756,21 @@ static struct platform_device var = { \
.platform_data = pdata, \
.parent = tparent, \
}, \
-};
+}
#define MIO_SIMPLE_DEV(var, strname, pdata) \
MIO_PARENT_DEV(var, strname, NULL, pdata)
-MIO_SIMPLE_DEV(mioa701_gpio_keys, "gpio-keys", &mioa701_gpio_keys_data)
+MIO_SIMPLE_DEV(mioa701_gpio_keys, "gpio-keys", &mioa701_gpio_keys_data);
MIO_PARENT_DEV(mioa701_backlight, "pwm-backlight", &pxa27x_device_pwm0.dev,
&mioa701_backlight_data);
-MIO_SIMPLE_DEV(mioa701_led, "leds-gpio", &gpio_led_info)
-MIO_SIMPLE_DEV(pxa2xx_pcm, "pxa2xx-pcm", NULL)
-MIO_SIMPLE_DEV(pxa2xx_ac97, "pxa2xx-ac97", NULL)
-MIO_PARENT_DEV(mio_wm9713_codec, "wm9713-codec", &pxa2xx_ac97.dev, NULL)
-MIO_SIMPLE_DEV(mioa701_sound, "mioa701-wm9713", NULL)
-MIO_SIMPLE_DEV(mioa701_board, "mioa701-board", NULL)
+MIO_SIMPLE_DEV(mioa701_led, "leds-gpio", &gpio_led_info);
+MIO_SIMPLE_DEV(pxa2xx_pcm, "pxa2xx-pcm", NULL);
+MIO_SIMPLE_DEV(pxa2xx_ac97, "pxa2xx-ac97", NULL);
+MIO_PARENT_DEV(mio_wm9713_codec, "wm9713-codec", &pxa2xx_ac97.dev, NULL);
+MIO_SIMPLE_DEV(mioa701_sound, "mioa701-wm9713", NULL);
+MIO_SIMPLE_DEV(mioa701_board, "mioa701-board", NULL);
MIO_SIMPLE_DEV(gpio_vbus, "gpio-vbus", &gpio_vbus_data);
+MIO_SIMPLE_DEV(mioa701_camera, "soc-camera-pdrv",&iclink[0]);
static struct platform_device *devices[] __initdata = {
&mioa701_gpio_keys,
@@ -780,6 +783,7 @@ static struct platform_device *devices[] __initdata = {
&power_dev,
&strataflash,
&gpio_vbus,
+ &mioa701_camera,
&mioa701_board,
};
@@ -825,7 +829,6 @@ static void __init mioa701_machine_init(void)
pxa_set_i2c_info(&i2c_pdata);
pxa_set_camera_info(&mioa701_pxacamera_platform_data);
- i2c_register_board_info(0, ARRAY_AND_SIZE(mioa701_i2c_devices));
}
static void mioa701_machine_exit(void)
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 9ce1ef2..619b90e 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -427,25 +427,54 @@ static void pcm990_camera_free_bus(struct soc_camera_link *link)
gpio_bus_switch = -EINVAL;
}
-static struct soc_camera_link iclink = {
- .bus_id = 0, /* Must match with the camera ID above */
- .query_bus_param = pcm990_camera_query_bus_param,
- .set_bus_param = pcm990_camera_set_bus_param,
- .free_bus = pcm990_camera_free_bus,
-};
-
/* Board I2C devices. */
static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
{
/* Must initialize before the camera(s) */
I2C_BOARD_INFO("pca9536", 0x41),
.platform_data = &pca9536_data,
- }, {
+ },
+};
+
+static struct i2c_board_info __initdata pcm990_camera_i2c[] = {
+ {
I2C_BOARD_INFO("mt9v022", 0x48),
- .platform_data = &iclink, /* With extender */
}, {
I2C_BOARD_INFO("mt9m001", 0x5d),
- .platform_data = &iclink, /* With extender */
+ },
+};
+
+static struct soc_camera_link iclink[] = {
+ {
+ .bus_id = 0, /* Must match with the camera ID */
+ .board_info = &pcm990_camera_i2c[0],
+ .i2c_adapter_id = 0,
+ .query_bus_param = pcm990_camera_query_bus_param,
+ .set_bus_param = pcm990_camera_set_bus_param,
+ .free_bus = pcm990_camera_free_bus,
+ }, {
+ .bus_id = 0, /* Must match with the camera ID */
+ .board_info = &pcm990_camera_i2c[1],
+ .i2c_adapter_id = 0,
+ .query_bus_param = pcm990_camera_query_bus_param,
+ .set_bus_param = pcm990_camera_set_bus_param,
+ .free_bus = pcm990_camera_free_bus,
+ },
+};
+
+static struct platform_device pcm990_camera[] = {
+ {
+ .name = "soc-camera-pdrv",
+ .id = 0,
+ .dev = {
+ .platform_data = &iclink[0],
+ },
+ }, {
+ .name = "soc-camera-pdrv",
+ .id = 1,
+ .dev = {
+ .platform_data = &iclink[1],
+ },
},
};
#endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */
@@ -501,6 +530,9 @@ void __init pcm990_baseboard_init(void)
pxa_set_camera_info(&pcm990_pxacamera_platform_data);
i2c_register_board_info(0, ARRAY_AND_SIZE(pcm990_i2c_devices));
+
+ platform_device_register(&pcm990_camera[0]);
+ platform_device_register(&pcm990_camera[1]);
#endif
printk(KERN_INFO "PCM-990 Evaluation baseboard initialized\n");
diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c
index e27655b..37c9139 100644
--- a/arch/sh/boards/board-ap325rxa.c
+++ b/arch/sh/boards/board-ap325rxa.c
@@ -228,12 +228,6 @@ static struct platform_device lcdc_device = {
},
};
-static void camera_power(int val)
-{
- gpio_set_value(GPIO_PTZ5, val); /* RST_CAM/RSTB */
- mdelay(10);
-}
-
#ifdef CONFIG_I2C
static unsigned char camera_ncm03j_magic[] =
{
@@ -255,23 +249,28 @@ static unsigned char camera_ncm03j_magic[] =
0x63, 0xD4, 0x64, 0xEA, 0xD6, 0x0F,
};
-static int camera_set_capture(struct soc_camera_platform_info *info,
- int enable)
+static int ap325rxa_camera_power(struct device *dev, int on)
{
- struct i2c_adapter *a = i2c_get_adapter(0);
+ gpio_set_value(GPIO_PTZ5, on); /* RST_CAM/RSTB */
+ mdelay(10);
+ return 0;
+}
+
+static int ap325rxa_camera_set_capture(struct soc_camera_platform_info *info,
+ int enable)
+{
+ struct i2c_adapter *a = i2c_get_adapter(info->link.i2c_adapter_id);
struct i2c_msg msg;
int ret = 0;
int i;
- camera_power(0);
if (!enable)
- return 0; /* no disable for now */
+ return ap325rxa_camera_power(NULL, 0); /* no disable for now */
- camera_power(1);
for (i = 0; i < ARRAY_SIZE(camera_ncm03j_magic); i += 2) {
u_int8_t buf[8];
- msg.addr = 0x6e;
+ msg.addr = info->link.board_info->addr;
msg.buf = buf;
msg.len = 2;
msg.flags = 0;
@@ -285,8 +284,11 @@ static int camera_set_capture(struct soc_camera_platform_info *info,
return ret;
}
+static struct i2c_board_info __initdata ap325rxa_camera_i2c = {
+ I2C_BOARD_INFO("soc_camera_platform", 0x6e),
+};
+
static struct soc_camera_platform_info camera_info = {
- .iface = 0,
.format_name = "UYVY",
.format_depth = 16,
.format = {
@@ -296,22 +298,29 @@ static struct soc_camera_platform_info camera_info = {
.height = 480,
},
.bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
- SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
- .set_capture = camera_set_capture,
+ SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
+ .set_capture = ap325rxa_camera_set_capture,
+ .link = {
+ .bus_id = 0,
+ .board_info = &ap325rxa_camera_i2c,
+ .i2c_adapter_id = 0,
+ .power = ap325rxa_camera_power,
+ },
};
-static struct platform_device camera_device = {
- .name = "soc_camera_platform",
- .dev = {
- .platform_data = &camera_info,
+static struct platform_device ap325rxa_camera = {
+ .name = "soc-camera-pdrv",
+ .id = -1,
+ .dev = {
+ .platform_data = &camera_info.link,
},
};
#endif /* CONFIG_I2C */
static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
.flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
- SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER |
- SOCAM_DATAWIDTH_8,
+ SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH |
+ SOCAM_MASTER | SOCAM_DATAWIDTH_8,
};
static struct resource ceu_resources[] = {
@@ -360,7 +369,7 @@ static struct platform_device *ap325rxa_devices[] __initdata = {
&lcdc_device,
&ceu_device,
#ifdef CONFIG_I2C
- &camera_device,
+ &ap325rxa_camera,
#endif
&nand_flash_device,
&sdcard_cn3_device,
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index 4fd6a72..b8cb246 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -383,21 +383,6 @@ static struct platform_device migor_ceu_device = {
},
};
-static struct ov772x_camera_info ov7725_info = {
- .buswidth = SOCAM_DATAWIDTH_8,
- .link = {
- .power = ov7725_power,
- },
-};
-
-static struct tw9910_video_info tw9910_info = {
- .buswidth = SOCAM_DATAWIDTH_8,
- .mpout = TW9910_MPO_FIELD,
- .link = {
- .power = tw9910_power,
- }
-};
-
struct spi_gpio_platform_data sdcard_cn9_platform_data = {
.sck = GPIO_PTD0,
.mosi = GPIO_PTD1,
@@ -412,16 +397,6 @@ static struct platform_device sdcard_cn9_device = {
},
};
-static struct platform_device *migor_devices[] __initdata = {
- &smc91x_eth_device,
- &sh_keysc_device,
- &migor_lcdc_device,
- &migor_ceu_device,
- &migor_nor_flash_device,
- &migor_nand_flash_device,
- &sdcard_cn9_device,
-};
-
static struct i2c_board_info migor_i2c_devices[] = {
{
I2C_BOARD_INFO("rs5c372b", 0x32),
@@ -430,16 +405,64 @@ static struct i2c_board_info migor_i2c_devices[] = {
I2C_BOARD_INFO("migor_ts", 0x51),
.irq = 38, /* IRQ6 */
},
+};
+
+static struct i2c_board_info migor_camera_i2c[] = {
{
I2C_BOARD_INFO("ov772x", 0x21),
- .platform_data = &ov7725_info,
},
{
I2C_BOARD_INFO("tw9910", 0x45),
- .platform_data = &tw9910_info,
},
};
+static struct ov772x_camera_info ov7725_info = {
+ .buswidth = SOCAM_DATAWIDTH_8,
+ .link = {
+ .power = ov7725_power,
+ .board_info = &migor_camera_i2c[0],
+ .i2c_adapter_id = 0,
+ },
+};
+
+static struct tw9910_video_info tw9910_info = {
+ .buswidth = SOCAM_DATAWIDTH_8,
+ .mpout = TW9910_MPO_FIELD,
+ .link = {
+ .power = tw9910_power,
+ .board_info = &migor_camera_i2c[1],
+ .i2c_adapter_id = 0,
+ }
+};
+
+static struct platform_device migor_camera[] = {
+ {
+ .name = "soc-camera-pdrv",
+ .id = 0,
+ .dev = {
+ .platform_data = &ov7725_info.link,
+ },
+ }, {
+ .name = "soc-camera-pdrv",
+ .id = 1,
+ .dev = {
+ .platform_data = &tw9910_info.link,
+ },
+ },
+};
+
+static struct platform_device *migor_devices[] __initdata = {
+ &smc91x_eth_device,
+ &sh_keysc_device,
+ &migor_lcdc_device,
+ &migor_ceu_device,
+ &migor_nor_flash_device,
+ &migor_nand_flash_device,
+ &sdcard_cn9_device,
+ &migor_camera[0],
+ &migor_camera[1],
+};
+
static struct spi_board_info migor_spi_devices[] = {
{
.modalias = "mmc_spi",
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index 459c04c..b0f4ad5 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -69,8 +69,6 @@ static const struct soc_camera_data_format mt9m001_monochrome_formats[] = {
};
struct mt9m001 {
- struct i2c_client *client;
- struct soc_camera_device icd;
int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
unsigned char autoexposure;
};
@@ -111,11 +109,11 @@ static int reg_clear(struct i2c_client *client, const u8 reg,
static int mt9m001_init(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret;
- dev_dbg(icd->vdev->parent, "%s\n", __func__);
+ dev_dbg(&icd->dev, "%s\n", __func__);
if (icl->power) {
ret = icl->power(&client->dev, 1);
@@ -147,8 +145,8 @@ static int mt9m001_init(struct soc_camera_device *icd)
static int mt9m001_release(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
/* Disable the chip */
reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
@@ -161,7 +159,7 @@ static int mt9m001_release(struct soc_camera_device *icd)
static int mt9m001_start_capture(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
/* Switch to master "normal" mode */
if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0)
@@ -171,7 +169,7 @@ static int mt9m001_start_capture(struct soc_camera_device *icd)
static int mt9m001_stop_capture(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
/* Stop sensor readout */
if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0)
@@ -182,8 +180,7 @@ static int mt9m001_stop_capture(struct soc_camera_device *icd)
static int mt9m001_set_bus_param(struct soc_camera_device *icd,
unsigned long flags)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK;
/* Only one width bit may be set */
@@ -205,8 +202,7 @@ static int mt9m001_set_bus_param(struct soc_camera_device *icd,
static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
/* MT9M001 has all capture_format parameters fixed */
unsigned long flags = SOCAM_PCLK_SAMPLE_FALLING |
SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
@@ -223,8 +219,8 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
static int mt9m001_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
int ret;
const u16 hblank = 9, vblank = 25;
@@ -296,12 +292,13 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd,
static int mt9m001_get_chip_id(struct soc_camera_device *icd,
struct v4l2_dbg_chip_ident *id)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL;
- if (id->match.addr != mt9m001->client->addr)
+ if (id->match.addr != client->addr)
return -ENODEV;
id->ident = mt9m001->model;
@@ -314,7 +311,7 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd,
static int mt9m001_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
@@ -334,7 +331,7 @@ static int mt9m001_get_register(struct soc_camera_device *icd,
static int mt9m001_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
@@ -387,15 +384,11 @@ static const struct v4l2_queryctrl mt9m001_controls[] = {
}
};
-static int mt9m001_video_probe(struct soc_camera_device *);
-static void mt9m001_video_remove(struct soc_camera_device *);
static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *);
static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *);
static struct soc_camera_ops mt9m001_ops = {
.owner = THIS_MODULE,
- .probe = mt9m001_video_probe,
- .remove = mt9m001_video_remove,
.init = mt9m001_init,
.release = mt9m001_release,
.start_capture = mt9m001_start_capture,
@@ -418,8 +411,8 @@ static struct soc_camera_ops mt9m001_ops = {
static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
int data;
switch (ctrl->id) {
@@ -438,8 +431,8 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro
static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
const struct v4l2_queryctrl *qctrl;
int data;
@@ -531,11 +524,11 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
/* Interface active, can use i2c. If it fails, it can indeed mean, that
* this wasn't our capture interface, so, we wait for the right one */
-static int mt9m001_video_probe(struct soc_camera_device *icd)
+static int mt9m001_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
s32 data;
int ret;
unsigned long flags;
@@ -546,6 +539,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
return -ENODEV;
+ /* Switch master clock on */
+ ret = soc_camera_video_start(icd, &client->dev);
+ if (ret)
+ return ret;
+
/* Enable the chip */
data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
dev_dbg(&icd->dev, "write: %d\n", data);
@@ -553,6 +551,8 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
/* Read out the chip version register */
data = reg_read(client, MT9M001_CHIP_VERSION);
+ soc_camera_video_stop(icd);
+
/* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
switch (data) {
case 0x8411:
@@ -565,10 +565,9 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
icd->formats = mt9m001_monochrome_formats;
break;
default:
- ret = -ENODEV;
dev_err(&icd->dev,
"No MT9M001 chip detected, register read %x\n", data);
- goto ei2c;
+ return -ENODEV;
}
icd->num_formats = 0;
@@ -594,26 +593,17 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
data == 0x8431 ? "C12STM" : "C12ST");
- /* Now that we know the model, we can start video */
- ret = soc_camera_video_start(icd);
- if (ret)
- goto eisis;
-
return 0;
-
-eisis:
-ei2c:
- return ret;
}
static void mt9m001_video_remove(struct soc_camera_device *icd)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
- dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr,
+ dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
icd->dev.parent, icd->vdev);
- soc_camera_video_stop(icd);
+ icd->ops = NULL;
if (icl->free_bus)
icl->free_bus(icl);
}
@@ -622,11 +612,17 @@ static int mt9m001_probe(struct i2c_client *client,
const struct i2c_device_id *did)
{
struct mt9m001 *mt9m001;
- struct soc_camera_device *icd;
+ struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct soc_camera_link *icl;
int ret;
+ if (!icd) {
+ dev_err(&client->dev, "MT9M001: missing soc-camera data!\n");
+ return -EINVAL;
+ }
+
+ icl = to_soc_camera_link(icd);
if (!icl) {
dev_err(&client->dev, "MT9M001 driver needs platform data\n");
return -EINVAL;
@@ -642,13 +638,10 @@ static int mt9m001_probe(struct i2c_client *client,
if (!mt9m001)
return -ENOMEM;
- mt9m001->client = client;
i2c_set_clientdata(client, mt9m001);
/* Second stage probe - when a capture adapter is there */
- icd = &mt9m001->icd;
icd->ops = &mt9m001_ops;
- icd->control = &client->dev;
icd->x_min = 20;
icd->y_min = 12;
icd->x_current = 20;
@@ -658,27 +651,27 @@ static int mt9m001_probe(struct i2c_client *client,
icd->height_min = 32;
icd->height_max = 1024;
icd->y_skip_top = 1;
- icd->iface = icl->bus_id;
/* Simulated autoexposure. If enabled, we calculate shutter width
* ourselves in the driver based on vertical blanking and frame width */
mt9m001->autoexposure = 1;
- ret = soc_camera_device_register(icd);
- if (ret)
- goto eisdr;
-
- return 0;
+ ret = mt9m001_video_probe(icd, client);
+ if (ret) {
+ i2c_set_clientdata(client, NULL);
+ kfree(mt9m001);
+ }
-eisdr:
- kfree(mt9m001);
return ret;
}
static int mt9m001_remove(struct i2c_client *client)
{
struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
- soc_camera_device_unregister(&mt9m001->icd);
+ mt9m001_video_remove(icd);
+ i2c_set_clientdata(client, NULL);
+ client->driver = NULL;
kfree(mt9m001);
return 0;
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index fc5e2de..330753a 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -148,8 +148,6 @@ enum mt9m111_context {
};
struct mt9m111 {
- struct i2c_client *client;
- struct soc_camera_device icd;
int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */
enum mt9m111_context context;
struct v4l2_rect rect;
@@ -203,7 +201,7 @@ static int mt9m111_reg_write(struct i2c_client *client, const u16 reg,
ret = reg_page_map_set(client, reg);
if (!ret)
- ret = i2c_smbus_write_word_data(client, (reg & 0xff),
+ ret = i2c_smbus_write_word_data(client, reg & 0xff,
swab16(data));
dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
return ret;
@@ -232,7 +230,7 @@ static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg,
static int mt9m111_set_context(struct soc_camera_device *icd,
enum mt9m111_context ctxt)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B
| MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B
| MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B
@@ -249,8 +247,8 @@ static int mt9m111_set_context(struct soc_camera_device *icd,
static int mt9m111_setup_rect(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret, is_raw_format;
int width = rect->width;
int height = rect->height;
@@ -294,7 +292,7 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd,
static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int ret;
ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt);
@@ -315,7 +313,8 @@ static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd)
static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int val = 0;
if (mt9m111->swap_rgb_red_blue)
@@ -329,7 +328,8 @@ static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd)
static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int val = 0;
if (mt9m111->swap_rgb_red_blue)
@@ -343,7 +343,8 @@ static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd)
static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int val = 0;
if (mt9m111->swap_yuv_cb_cr)
@@ -356,9 +357,9 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
static int mt9m111_enable(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
if (icl->power) {
@@ -378,9 +379,9 @@ static int mt9m111_enable(struct soc_camera_device *icd)
static int mt9m111_disable(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE);
@@ -395,8 +396,8 @@ static int mt9m111_disable(struct soc_camera_device *icd)
static int mt9m111_reset(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret;
ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
@@ -424,8 +425,7 @@ static int mt9m111_stop_capture(struct soc_camera_device *icd)
static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |
SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
@@ -441,7 +441,8 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
static int mt9m111_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
@@ -456,7 +457,8 @@ static int mt9m111_set_crop(struct soc_camera_device *icd,
static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
switch (pixfmt) {
@@ -506,7 +508,8 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
static int mt9m111_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
struct v4l2_pix_format *pix = &f->fmt.pix;
struct v4l2_rect rect = {
.left = mt9m111->rect.left,
@@ -544,12 +547,13 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd,
static int mt9m111_get_chip_id(struct soc_camera_device *icd,
struct v4l2_dbg_chip_ident *id)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL;
- if (id->match.addr != mt9m111->client->addr)
+ if (id->match.addr != client->addr)
return -ENODEV;
id->ident = mt9m111->model;
@@ -562,8 +566,8 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd,
static int mt9m111_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int val;
- struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
return -EINVAL;
@@ -583,7 +587,7 @@ static int mt9m111_get_register(struct soc_camera_device *icd,
static int mt9m111_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
return -EINVAL;
@@ -635,8 +639,6 @@ static const struct v4l2_queryctrl mt9m111_controls[] = {
}
};
-static int mt9m111_video_probe(struct soc_camera_device *);
-static void mt9m111_video_remove(struct soc_camera_device *);
static int mt9m111_get_control(struct soc_camera_device *,
struct v4l2_control *);
static int mt9m111_set_control(struct soc_camera_device *,
@@ -647,8 +649,6 @@ static int mt9m111_release(struct soc_camera_device *icd);
static struct soc_camera_ops mt9m111_ops = {
.owner = THIS_MODULE,
- .probe = mt9m111_video_probe,
- .remove = mt9m111_video_remove,
.init = mt9m111_init,
.resume = mt9m111_resume,
.release = mt9m111_release,
@@ -672,8 +672,8 @@ static struct soc_camera_ops mt9m111_ops = {
static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
if (mt9m111->context == HIGHPOWER) {
@@ -693,7 +693,7 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
static int mt9m111_get_global_gain(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int data;
data = reg_read(GLOBAL_GAIN);
@@ -705,7 +705,7 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd)
static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
u16 val;
if (gain > 63 * 2 * 2)
@@ -724,8 +724,8 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
if (on)
@@ -741,8 +741,8 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
if (on)
@@ -759,8 +759,8 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
static int mt9m111_get_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int data;
switch (ctrl->id) {
@@ -803,7 +803,8 @@ static int mt9m111_get_control(struct soc_camera_device *icd,
static int mt9m111_set_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
const struct v4l2_queryctrl *qctrl;
int ret;
@@ -841,7 +842,8 @@ static int mt9m111_set_control(struct soc_camera_device *icd,
static int mt9m111_restore_state(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
mt9m111_set_context(icd, mt9m111->context);
mt9m111_set_pixfmt(icd, mt9m111->pixfmt);
@@ -856,7 +858,8 @@ static int mt9m111_restore_state(struct soc_camera_device *icd)
static int mt9m111_resume(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret = 0;
if (mt9m111->powered) {
@@ -871,7 +874,8 @@ static int mt9m111_resume(struct soc_camera_device *icd)
static int mt9m111_init(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
mt9m111->context = HIGHPOWER;
@@ -902,10 +906,10 @@ static int mt9m111_release(struct soc_camera_device *icd)
* Interface active, can use i2c. If it fails, it can indeed mean, that
* this wasn't our capture interface, so, we wait for the right one
*/
-static int mt9m111_video_probe(struct soc_camera_device *icd)
+static int mt9m111_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
s32 data;
int ret;
@@ -917,6 +921,11 @@ static int mt9m111_video_probe(struct soc_camera_device *icd)
to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
return -ENODEV;
+ /* Switch master clock on */
+ ret = soc_camera_video_start(icd, &client->dev);
+ if (ret)
+ return ret;
+
ret = mt9m111_enable(icd);
if (ret)
goto ei2c;
@@ -945,40 +954,42 @@ static int mt9m111_video_probe(struct soc_camera_device *icd)
dev_info(&icd->dev, "Detected a MT9M11x chip ID %x\n", data);
- ret = soc_camera_video_start(icd);
- if (ret)
- goto eisis;
-
mt9m111->autoexposure = 1;
mt9m111->autowhitebalance = 1;
mt9m111->swap_rgb_even_odd = 1;
mt9m111->swap_rgb_red_blue = 1;
- return 0;
-eisis:
ei2c:
+ soc_camera_video_stop(icd);
+
return ret;
}
static void mt9m111_video_remove(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
- dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m111->client->addr,
- mt9m111->icd.dev.parent, mt9m111->icd.vdev);
- soc_camera_video_stop(&mt9m111->icd);
+ dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
+ icd->dev.parent, icd->vdev);
+ icd->ops = NULL;
}
static int mt9m111_probe(struct i2c_client *client,
const struct i2c_device_id *did)
{
struct mt9m111 *mt9m111;
- struct soc_camera_device *icd;
+ struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct soc_camera_link *icl;
int ret;
+ if (!icd) {
+ dev_err(&client->dev, "MT9M11x: missing soc-camera data!\n");
+ return -EINVAL;
+ }
+
+ icl = to_soc_camera_link(icd);
if (!icl) {
dev_err(&client->dev, "MT9M11x driver needs platform data\n");
return -EINVAL;
@@ -994,13 +1005,10 @@ static int mt9m111_probe(struct i2c_client *client,
if (!mt9m111)
return -ENOMEM;
- mt9m111->client = client;
i2c_set_clientdata(client, mt9m111);
/* Second stage probe - when a capture adapter is there */
- icd = &mt9m111->icd;
icd->ops = &mt9m111_ops;
- icd->control = &client->dev;
icd->x_min = MT9M111_MIN_DARK_COLS;
icd->y_min = MT9M111_MIN_DARK_ROWS;
icd->x_current = icd->x_min;
@@ -1010,22 +1018,24 @@ static int mt9m111_probe(struct i2c_client *client,
icd->height_min = MT9M111_MIN_DARK_COLS;
icd->height_max = MT9M111_MAX_HEIGHT;
icd->y_skip_top = 0;
- icd->iface = icl->bus_id;
- ret = soc_camera_device_register(icd);
- if (ret)
- goto eisdr;
- return 0;
+ ret = mt9m111_video_probe(icd, client);
+ if (ret) {
+ i2c_set_clientdata(client, NULL);
+ kfree(mt9m111);
+ }
-eisdr:
- kfree(mt9m111);
return ret;
}
static int mt9m111_remove(struct i2c_client *client)
{
struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
- soc_camera_device_unregister(&mt9m111->icd);
+ struct soc_camera_device *icd = client->dev.platform_data;
+
+ mt9m111_video_remove(icd);
+ i2c_set_clientdata(client, NULL);
+ client->driver = NULL;
kfree(mt9m111);
return 0;
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
index f72aeb7..da09906 100644
--- a/drivers/media/video/mt9t031.c
+++ b/drivers/media/video/mt9t031.c
@@ -68,8 +68,6 @@ static const struct soc_camera_data_format mt9t031_colour_formats[] = {
};
struct mt9t031 {
- struct i2c_client *client;
- struct soc_camera_device icd;
int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */
unsigned char autoexposure;
u16 xskip;
@@ -138,8 +136,8 @@ static int get_shutter(struct i2c_client *client, u32 *data)
static int mt9t031_init(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret;
if (icl->power) {
@@ -166,8 +164,8 @@ static int mt9t031_init(struct soc_camera_device *icd)
static int mt9t031_release(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
/* Disable the chip */
reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
@@ -180,7 +178,7 @@ static int mt9t031_release(struct soc_camera_device *icd)
static int mt9t031_start_capture(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
/* Switch to master "normal" mode */
if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
@@ -190,7 +188,7 @@ static int mt9t031_start_capture(struct soc_camera_device *icd)
static int mt9t031_stop_capture(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
/* Stop sensor readout */
if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
@@ -201,7 +199,7 @@ static int mt9t031_stop_capture(struct soc_camera_device *icd)
static int mt9t031_set_bus_param(struct soc_camera_device *icd,
unsigned long flags)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
/* The caller should have queried our parameters, check anyway */
if (flags & ~MT9T031_BUS_PARAM)
@@ -217,8 +215,7 @@ static int mt9t031_set_bus_param(struct soc_camera_device *icd,
static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
- struct soc_camera_link *icl = mt9t031->client->dev.platform_data;
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM);
}
@@ -238,8 +235,8 @@ static void recalculate_limits(struct soc_camera_device *icd,
static int mt9t031_set_params(struct soc_camera_device *icd,
struct v4l2_rect *rect, u16 xskip, u16 yskip)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
int ret;
u16 xbin, ybin, width, height, left, top;
const u16 hblank = MT9T031_HORIZONTAL_BLANK,
@@ -336,7 +333,8 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
static int mt9t031_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
/* CROP - no change in scaling, or in limits */
return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip);
@@ -345,7 +343,8 @@ static int mt9t031_set_crop(struct soc_camera_device *icd,
static int mt9t031_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
int ret;
u16 xskip, yskip;
struct v4l2_rect rect = {
@@ -403,12 +402,13 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd,
static int mt9t031_get_chip_id(struct soc_camera_device *icd,
struct v4l2_dbg_chip_ident *id)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL;
- if (id->match.addr != mt9t031->client->addr)
+ if (id->match.addr != client->addr)
return -ENODEV;
id->ident = mt9t031->model;
@@ -421,7 +421,7 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd,
static int mt9t031_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
@@ -440,7 +440,7 @@ static int mt9t031_get_register(struct soc_camera_device *icd,
static int mt9t031_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
@@ -501,15 +501,11 @@ static const struct v4l2_queryctrl mt9t031_controls[] = {
}
};
-static int mt9t031_video_probe(struct soc_camera_device *);
-static void mt9t031_video_remove(struct soc_camera_device *);
static int mt9t031_get_control(struct soc_camera_device *, struct v4l2_control *);
static int mt9t031_set_control(struct soc_camera_device *, struct v4l2_control *);
static struct soc_camera_ops mt9t031_ops = {
.owner = THIS_MODULE,
- .probe = mt9t031_video_probe,
- .remove = mt9t031_video_remove,
.init = mt9t031_init,
.release = mt9t031_release,
.start_capture = mt9t031_start_capture,
@@ -532,8 +528,8 @@ static struct soc_camera_ops mt9t031_ops = {
static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
int data;
switch (ctrl->id) {
@@ -558,8 +554,8 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro
static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
const struct v4l2_queryctrl *qctrl;
int data;
@@ -665,10 +661,10 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
/* Interface active, can use i2c. If it fails, it can indeed mean, that
* this wasn't our capture interface, so, we wait for the right one */
-static int mt9t031_video_probe(struct soc_camera_device *icd)
+static int mt9t031_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
s32 data;
int ret;
@@ -678,6 +674,11 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
return -ENODEV;
+ /* Switch master clock on */
+ ret = soc_camera_video_start(icd, &client->dev);
+ if (ret)
+ return ret;
+
/* Enable the chip */
data = reg_write(client, MT9T031_CHIP_ENABLE, 1);
dev_dbg(&icd->dev, "write: %d\n", data);
@@ -685,6 +686,8 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
/* Read out the chip version register */
data = reg_read(client, MT9T031_CHIP_VERSION);
+ soc_camera_video_stop(icd);
+
switch (data) {
case 0x1621:
mt9t031->model = V4L2_IDENT_MT9T031;
@@ -692,44 +695,40 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats);
break;
default:
- ret = -ENODEV;
dev_err(&icd->dev,
"No MT9T031 chip detected, register read %x\n", data);
- goto ei2c;
+ return -ENODEV;
}
dev_info(&icd->dev, "Detected a MT9T031 chip ID %x\n", data);
- /* Now that we know the model, we can start video */
- ret = soc_camera_video_start(icd);
- if (ret)
- goto evstart;
-
return 0;
-
-evstart:
-ei2c:
- return ret;
}
static void mt9t031_video_remove(struct soc_camera_device *icd)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
- dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9t031->client->addr,
+ dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
icd->dev.parent, icd->vdev);
- soc_camera_video_stop(icd);
+ icd->ops = NULL;
}
static int mt9t031_probe(struct i2c_client *client,
const struct i2c_device_id *did)
{
struct mt9t031 *mt9t031;
- struct soc_camera_device *icd;
+ struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct soc_camera_link *icl;
int ret;
+ if (!icd) {
+ dev_err(&client->dev, "MT9T031: missing soc-camera data!\n");
+ return -EINVAL;
+ }
+
+ icl = to_soc_camera_link(icd);
if (!icl) {
dev_err(&client->dev, "MT9T031 driver needs platform data\n");
return -EINVAL;
@@ -745,13 +744,10 @@ static int mt9t031_probe(struct i2c_client *client,
if (!mt9t031)
return -ENOMEM;
- mt9t031->client = client;
i2c_set_clientdata(client, mt9t031);
/* Second stage probe - when a capture adapter is there */
- icd = &mt9t031->icd;
icd->ops = &mt9t031_ops;
- icd->control = &client->dev;
icd->x_min = MT9T031_COLUMN_SKIP;
icd->y_min = MT9T031_ROW_SKIP;
icd->x_current = icd->x_min;
@@ -761,7 +757,6 @@ static int mt9t031_probe(struct i2c_client *client,
icd->height_min = MT9T031_MIN_HEIGHT;
icd->height_max = MT9T031_MAX_HEIGHT;
icd->y_skip_top = 0;
- icd->iface = icl->bus_id;
/* Simulated autoexposure. If enabled, we calculate shutter width
* ourselves in the driver based on vertical blanking and frame width */
mt9t031->autoexposure = 1;
@@ -769,24 +764,24 @@ static int mt9t031_probe(struct i2c_client *client,
mt9t031->xskip = 1;
mt9t031->yskip = 1;
- ret = soc_camera_device_register(icd);
- if (ret)
- goto eisdr;
-
- return 0;
+ ret = mt9t031_video_probe(icd, client);
+ if (ret) {
+ icd->ops = NULL;
+ i2c_set_clientdata(client, NULL);
+ kfree(mt9t031);
+ }
-eisdr:
- i2c_set_clientdata(client, NULL);
- kfree(mt9t031);
return ret;
}
static int mt9t031_remove(struct i2c_client *client)
{
struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
- soc_camera_device_unregister(&mt9t031->icd);
+ mt9t031_video_remove(icd);
i2c_set_clientdata(client, NULL);
+ client->driver = NULL;
kfree(mt9t031);
return 0;
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index be20d31..1683af1 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -85,8 +85,6 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = {
};
struct mt9v022 {
- struct i2c_client *client;
- struct soc_camera_device icd;
int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
u16 chip_control;
};
@@ -127,9 +125,9 @@ static int reg_clear(struct i2c_client *client, const u8 reg,
static int mt9v022_init(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
int ret;
if (icl->power) {
@@ -173,19 +171,19 @@ static int mt9v022_init(struct soc_camera_device *icd)
static int mt9v022_release(struct soc_camera_device *icd)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
if (icl->power)
- icl->power(&mt9v022->client->dev, 0);
+ icl->power(&client->dev, 0);
return 0;
}
static int mt9v022_start_capture(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
/* Switch to master "normal" mode */
mt9v022->chip_control &= ~0x10;
if (reg_write(client, MT9V022_CHIP_CONTROL,
@@ -196,8 +194,8 @@ static int mt9v022_start_capture(struct soc_camera_device *icd)
static int mt9v022_stop_capture(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
/* Switch to snapshot mode */
mt9v022->chip_control |= 0x10;
if (reg_write(client, MT9V022_CHIP_CONTROL,
@@ -209,9 +207,9 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd)
static int mt9v022_set_bus_param(struct soc_camera_device *icd,
unsigned long flags)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
int ret;
u16 pixclk = 0;
@@ -263,8 +261,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd,
static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
unsigned int width_flag;
if (icl->query_bus_param)
@@ -283,7 +280,7 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
static int mt9v022_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int ret;
/* Like in example app. Contradicts the datasheet though */
@@ -326,7 +323,8 @@ static int mt9v022_set_crop(struct soc_camera_device *icd,
static int mt9v022_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
struct v4l2_pix_format *pix = &f->fmt.pix;
struct v4l2_rect rect = {
.left = icd->x_current,
@@ -380,12 +378,13 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd,
static int mt9v022_get_chip_id(struct soc_camera_device *icd,
struct v4l2_dbg_chip_ident *id)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL;
- if (id->match.addr != mt9v022->client->addr)
+ if (id->match.addr != client->addr)
return -ENODEV;
id->ident = mt9v022->model;
@@ -398,7 +397,7 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd,
static int mt9v022_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
@@ -418,7 +417,7 @@ static int mt9v022_get_register(struct soc_camera_device *icd,
static int mt9v022_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
@@ -487,15 +486,11 @@ static const struct v4l2_queryctrl mt9v022_controls[] = {
}
};
-static int mt9v022_video_probe(struct soc_camera_device *);
-static void mt9v022_video_remove(struct soc_camera_device *);
static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *);
static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *);
static struct soc_camera_ops mt9v022_ops = {
.owner = THIS_MODULE,
- .probe = mt9v022_video_probe,
- .remove = mt9v022_video_remove,
.init = mt9v022_init,
.release = mt9v022_release,
.start_capture = mt9v022_start_capture,
@@ -519,7 +514,7 @@ static struct soc_camera_ops mt9v022_ops = {
static int mt9v022_get_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int data;
switch (ctrl->id) {
@@ -555,7 +550,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
int data;
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
const struct v4l2_queryctrl *qctrl;
qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
@@ -652,11 +647,11 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
/* Interface active, can use i2c. If it fails, it can indeed mean, that
* this wasn't our capture interface, so, we wait for the right one */
-static int mt9v022_video_probe(struct soc_camera_device *icd)
+static int mt9v022_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
s32 data;
int ret;
unsigned long flags;
@@ -665,6 +660,11 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
return -ENODEV;
+ /* Switch master clock on */
+ ret = soc_camera_video_start(icd, &client->dev);
+ if (ret)
+ return ret;
+
/* Read out the chip version register */
data = reg_read(client, MT9V022_CHIP_VERSION);
@@ -684,6 +684,8 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
udelay(200);
if (reg_read(client, MT9V022_RESET)) {
dev_err(&icd->dev, "Resetting MT9V022 failed!\n");
+ if (ret > 0)
+ ret = -EIO;
goto ei2c;
}
@@ -700,7 +702,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
}
if (ret < 0)
- goto eisis;
+ goto ei2c;
icd->num_formats = 0;
@@ -722,29 +724,24 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
if (flags & SOCAM_DATAWIDTH_8)
icd->num_formats++;
- ret = soc_camera_video_start(icd);
- if (ret < 0)
- goto eisis;
-
dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n",
data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ?
"monochrome" : "colour");
- return 0;
-
-eisis:
ei2c:
+ soc_camera_video_stop(icd);
+
return ret;
}
static void mt9v022_video_remove(struct soc_camera_device *icd)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
- dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr,
+ dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
icd->dev.parent, icd->vdev);
- soc_camera_video_stop(icd);
+ icd->ops = NULL;
if (icl->free_bus)
icl->free_bus(icl);
}
@@ -753,11 +750,17 @@ static int mt9v022_probe(struct i2c_client *client,
const struct i2c_device_id *did)
{
struct mt9v022 *mt9v022;
- struct soc_camera_device *icd;
+ struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct soc_camera_link *icl;
int ret;
+ if (!icd) {
+ dev_err(&client->dev, "MT9V022: missing soc-camera data!\n");
+ return -EINVAL;
+ }
+
+ icl = to_soc_camera_link(icd);
if (!icl) {
dev_err(&client->dev, "MT9V022 driver needs platform data\n");
return -EINVAL;
@@ -774,12 +777,9 @@ static int mt9v022_probe(struct i2c_client *client,
return -ENOMEM;
mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
- mt9v022->client = client;
i2c_set_clientdata(client, mt9v022);
- icd = &mt9v022->icd;
icd->ops = &mt9v022_ops;
- icd->control = &client->dev;
icd->x_min = 1;
icd->y_min = 4;
icd->x_current = 1;
@@ -789,24 +789,24 @@ static int mt9v022_probe(struct i2c_client *client,
icd->height_min = 32;
icd->height_max = 480;
icd->y_skip_top = 1;
- icd->iface = icl->bus_id;
-
- ret = soc_camera_device_register(icd);
- if (ret)
- goto eisdr;
- return 0;
+ ret = mt9v022_video_probe(icd, client);
+ if (ret) {
+ i2c_set_clientdata(client, NULL);
+ kfree(mt9v022);
+ }
-eisdr:
- kfree(mt9v022);
return ret;
}
static int mt9v022_remove(struct i2c_client *client)
{
struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
- soc_camera_device_unregister(&mt9v022->icd);
+ mt9v022_video_remove(icd);
+ i2c_set_clientdata(client, NULL);
+ client->driver = NULL;
kfree(mt9v022);
return 0;
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index cb13faa..ed752c5 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -502,18 +502,19 @@ static int mx3_camera_add_device(struct soc_camera_device *icd)
mx3_camera_activate(mx3_cam, icd);
ret = icd->ops->init(icd);
- if (ret < 0) {
- clk_disable(mx3_cam->clk);
+ if (ret < 0)
goto einit;
- }
mx3_cam->icd = icd;
+ dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n",
+ icd->devnum);
+
+ return 0;
+
einit:
+ clk_disable(mx3_cam->clk);
ebusy:
- if (!ret)
- dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n",
- icd->devnum);
return ret;
}
@@ -946,9 +947,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
camera_flags = icd->ops->query_bus_param(icd);
common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
+ dev_dbg(ici->dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n",
+ camera_flags, bus_flags, common_flags);
if (!common_flags) {
- dev_dbg(ici->dev, "no common flags: camera %lx, host %lx\n",
- camera_flags, bus_flags);
+ dev_dbg(ici->dev, "no common flags");
return -EINVAL;
}
@@ -1001,8 +1003,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
SOCAM_DATAWIDTH_4;
ret = icd->ops->set_bus_param(icd, common_flags);
- if (ret < 0)
+ if (ret < 0) {
+ dev_dbg(ici->dev, "camera set_bus_param(%lx) returned %d\n",
+ common_flags, ret);
return ret;
+ }
/*
* So far only gated clock mode is supported. Add a line
@@ -1130,8 +1135,9 @@ static int mx3_camera_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&mx3_cam->capture);
spin_lock_init(&mx3_cam->lock);
- base = ioremap(res->start, res->end - res->start + 1);
+ base = ioremap(res->start, resource_size(res));
if (!base) {
+ pr_err("Couldn't map %x@%x\n", resource_size(res), res->start);
err = -ENOMEM;
goto eioremap;
}
@@ -1218,3 +1224,4 @@ module_exit(mx3_camera_exit);
MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver");
MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" MX3_CAM_DRV_NAME);
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
index c0d9112..48f4d64 100644
--- a/drivers/media/video/ov772x.c
+++ b/drivers/media/video/ov772x.c
@@ -399,8 +399,6 @@ struct ov772x_win_size {
struct ov772x_priv {
struct ov772x_camera_info *info;
- struct i2c_client *client;
- struct soc_camera_device icd;
const struct ov772x_color_format *fmt;
const struct ov772x_win_size *win;
int model;
@@ -619,53 +617,56 @@ static int ov772x_reset(struct i2c_client *client)
static int ov772x_init(struct soc_camera_device *icd)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = dev_get_drvdata(&icd->dev);
int ret = 0;
- if (priv->info->link.power) {
- ret = priv->info->link.power(&priv->client->dev, 1);
+ if (icl->power) {
+ ret = icl->power(&client->dev, 1);
if (ret < 0)
return ret;
}
- if (priv->info->link.reset)
- ret = priv->info->link.reset(&priv->client->dev);
+ if (icl->reset)
+ ret = icl->reset(&client->dev);
return ret;
}
static int ov772x_release(struct soc_camera_device *icd)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = dev_get_drvdata(&icd->dev);
int ret = 0;
- if (priv->info->link.power)
- ret = priv->info->link.power(&priv->client->dev, 0);
+ if (icl->power)
+ ret = icl->power(&client->dev, 0);
return ret;
}
static int ov772x_start_capture(struct soc_camera_device *icd)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
if (!priv->win || !priv->fmt) {
dev_err(&icd->dev, "norm or win select error\n");
return -EPERM;
}
- ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0);
+ ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0);
dev_dbg(&icd->dev,
- "format %s, win %s\n", priv->fmt->name, priv->win->name);
+ "format %s, win %s\n", priv->fmt->name, priv->win->name);
return 0;
}
static int ov772x_stop_capture(struct soc_camera_device *icd)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
- ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
return 0;
}
@@ -677,8 +678,9 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd,
static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
- struct soc_camera_link *icl = &priv->info->link;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
+ struct soc_camera_link *icl = dev_get_drvdata(&icd->dev);
unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
@@ -689,7 +691,8 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
static int ov772x_get_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
switch (ctrl->id) {
case V4L2_CID_VFLIP:
@@ -705,7 +708,8 @@ static int ov772x_get_control(struct soc_camera_device *icd,
static int ov772x_set_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
int ret = 0;
u8 val;
@@ -715,14 +719,14 @@ static int ov772x_set_control(struct soc_camera_device *icd,
priv->flag_vflip = ctrl->value;
if (priv->info->flags & OV772X_FLAG_VFLIP)
val ^= VFLIP_IMG;
- ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val);
+ ret = ov772x_mask_set(client, COM3, VFLIP_IMG, val);
break;
case V4L2_CID_HFLIP:
val = ctrl->value ? HFLIP_IMG : 0x00;
priv->flag_hflip = ctrl->value;
if (priv->info->flags & OV772X_FLAG_HFLIP)
val ^= HFLIP_IMG;
- ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val);
+ ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val);
break;
}
@@ -730,9 +734,10 @@ static int ov772x_set_control(struct soc_camera_device *icd,
}
static int ov772x_get_chip_id(struct soc_camera_device *icd,
- struct v4l2_dbg_chip_ident *id)
+ struct v4l2_dbg_chip_ident *id)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
id->ident = priv->model;
id->revision = 0;
@@ -744,14 +749,14 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd,
static int ov772x_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
- int ret;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ int ret;
reg->size = 1;
if (reg->reg > 0xff)
return -EINVAL;
- ret = i2c_smbus_read_byte_data(priv->client, reg->reg);
+ ret = i2c_smbus_read_byte_data(client, reg->reg);
if (ret < 0)
return ret;
@@ -763,13 +768,13 @@ static int ov772x_get_register(struct soc_camera_device *icd,
static int ov772x_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->reg > 0xff ||
reg->val > 0xff)
return -EINVAL;
- return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val);
+ return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
}
#endif
@@ -793,9 +798,11 @@ ov772x_select_win(u32 width, u32 height)
return win;
}
-static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
- u32 pixfmt)
+static int ov772x_set_params(struct soc_camera_device *icd,
+ u32 width, u32 height, u32 pixfmt)
{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
int ret = -EINVAL;
u8 val;
int i;
@@ -821,7 +828,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
/*
* reset hardware
*/
- ov772x_reset(priv->client);
+ ov772x_reset(client);
/*
* Edge Ctrl
@@ -835,17 +842,17 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
* Remove it when manual mode.
*/
- ret = ov772x_mask_set(priv->client, DSPAUTO, EDGE_ACTRL, 0x00);
+ ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00);
if (ret < 0)
goto ov772x_set_fmt_error;
- ret = ov772x_mask_set(priv->client,
+ ret = ov772x_mask_set(client,
EDGE_TRSHLD, EDGE_THRESHOLD_MASK,
priv->info->edgectrl.threshold);
if (ret < 0)
goto ov772x_set_fmt_error;
- ret = ov772x_mask_set(priv->client,
+ ret = ov772x_mask_set(client,
EDGE_STRNGT, EDGE_STRENGTH_MASK,
priv->info->edgectrl.strength);
if (ret < 0)
@@ -857,13 +864,13 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
*
* set upper and lower limit
*/
- ret = ov772x_mask_set(priv->client,
+ ret = ov772x_mask_set(client,
EDGE_UPPER, EDGE_UPPER_MASK,
priv->info->edgectrl.upper);
if (ret < 0)
goto ov772x_set_fmt_error;
- ret = ov772x_mask_set(priv->client,
+ ret = ov772x_mask_set(client,
EDGE_LOWER, EDGE_LOWER_MASK,
priv->info->edgectrl.lower);
if (ret < 0)
@@ -873,7 +880,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
/*
* set size format
*/
- ret = ov772x_write_array(priv->client, priv->win->regs);
+ ret = ov772x_write_array(client, priv->win->regs);
if (ret < 0)
goto ov772x_set_fmt_error;
@@ -882,7 +889,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
*/
val = priv->fmt->dsp3;
if (val) {
- ret = ov772x_mask_set(priv->client,
+ ret = ov772x_mask_set(client,
DSP_CTRL3, UV_MASK, val);
if (ret < 0)
goto ov772x_set_fmt_error;
@@ -901,7 +908,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
if (priv->flag_hflip)
val ^= HFLIP_IMG;
- ret = ov772x_mask_set(priv->client,
+ ret = ov772x_mask_set(client,
COM3, SWAP_MASK | IMG_MASK, val);
if (ret < 0)
goto ov772x_set_fmt_error;
@@ -910,7 +917,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
* set COM7
*/
val = priv->win->com7_bit | priv->fmt->com7;
- ret = ov772x_mask_set(priv->client,
+ ret = ov772x_mask_set(client,
COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK),
val);
if (ret < 0)
@@ -920,7 +927,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
ov772x_set_fmt_error:
- ov772x_reset(priv->client);
+ ov772x_reset(client);
priv->win = NULL;
priv->fmt = NULL;
@@ -930,22 +937,22 @@ ov772x_set_fmt_error:
static int ov772x_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
if (!priv->fmt)
return -EINVAL;
- return ov772x_set_params(priv, rect->width, rect->height,
+ return ov772x_set_params(icd, rect->width, rect->height,
priv->fmt->fourcc);
}
static int ov772x_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
struct v4l2_pix_format *pix = &f->fmt.pix;
- return ov772x_set_params(priv, pix->width, pix->height,
+ return ov772x_set_params(icd, pix->width, pix->height,
pix->pixelformat);
}
@@ -967,11 +974,13 @@ static int ov772x_try_fmt(struct soc_camera_device *icd,
return 0;
}
-static int ov772x_video_probe(struct soc_camera_device *icd)
+static int ov772x_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
u8 pid, ver;
const char *devname;
+ int ret;
/*
* We must have a parent by now. And it cannot be a wrong one.
@@ -993,11 +1002,18 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
icd->formats = ov772x_fmt_lists;
icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists);
+ /* Switch master clock on */
+ ret = soc_camera_video_start(icd, &client->dev);
+ if (ret)
+ return ret;
+
/*
* check and show product ID and manufacturer ID
*/
- pid = i2c_smbus_read_byte_data(priv->client, PID);
- ver = i2c_smbus_read_byte_data(priv->client, VER);
+ pid = i2c_smbus_read_byte_data(client, PID);
+ ver = i2c_smbus_read_byte_data(client, VER);
+
+ soc_camera_video_stop(icd);
switch (VERSION(pid, ver)) {
case OV7720:
@@ -1019,21 +1035,19 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
devname,
pid,
ver,
- i2c_smbus_read_byte_data(priv->client, MIDH),
- i2c_smbus_read_byte_data(priv->client, MIDL));
+ i2c_smbus_read_byte_data(client, MIDH),
+ i2c_smbus_read_byte_data(client, MIDL));
- return soc_camera_video_start(icd);
+ return 0;
}
static void ov772x_video_remove(struct soc_camera_device *icd)
{
- soc_camera_video_stop(icd);
+ icd->ops = NULL;
}
static struct soc_camera_ops ov772x_ops = {
.owner = THIS_MODULE,
- .probe = ov772x_video_probe,
- .remove = ov772x_video_remove,
.init = ov772x_init,
.release = ov772x_release,
.start_capture = ov772x_start_capture,
@@ -1063,13 +1077,21 @@ static int ov772x_probe(struct i2c_client *client,
{
struct ov772x_priv *priv;
struct ov772x_camera_info *info;
- struct soc_camera_device *icd;
+ struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct soc_camera_link *icl;
int ret;
- info = client->dev.platform_data;
- if (!info)
+ if (!icd) {
+ dev_err(&client->dev, "MT9M001: missing soc-camera data!\n");
return -EINVAL;
+ }
+
+ icl = dev_get_drvdata(&icd->dev);
+ if (!icl)
+ return -EINVAL;
+
+ info = container_of(icl, struct ov772x_camera_info, link);
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_err(&adapter->dev,
@@ -1083,18 +1105,13 @@ static int ov772x_probe(struct i2c_client *client,
return -ENOMEM;
priv->info = info;
- priv->client = client;
i2c_set_clientdata(client, priv);
- icd = &priv->icd;
icd->ops = &ov772x_ops;
- icd->control = &client->dev;
icd->width_max = MAX_WIDTH;
icd->height_max = MAX_HEIGHT;
- icd->iface = priv->info->link.bus_id;
-
- ret = soc_camera_device_register(icd);
+ ret = ov772x_video_probe(icd, client);
if (ret) {
i2c_set_clientdata(client, NULL);
kfree(priv);
@@ -1106,8 +1123,9 @@ static int ov772x_probe(struct i2c_client *client,
static int ov772x_remove(struct i2c_client *client)
{
struct ov772x_priv *priv = i2c_get_clientdata(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
- soc_camera_device_unregister(&priv->icd);
+ ov772x_video_remove(icd);
i2c_set_clientdata(client, NULL);
kfree(priv);
return 0;
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 2da5eef..63964d0 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -841,7 +841,8 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q,
sizeof(struct pxa_buffer), icd);
}
-static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
+static u32 mclk_get_divisor(struct platform_device *pdev,
+ struct pxa_camera_dev *pcdev)
{
unsigned long mclk = pcdev->mclk;
u32 div;
@@ -853,7 +854,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
/* mclk <= ciclk / 4 (27.4.2) */
if (mclk > lcdclk / 4) {
mclk = lcdclk / 4;
- dev_warn(pcdev->soc_host.dev, "Limiting master clock to %lu\n", mclk);
+ dev_warn(&pdev->dev, "Limiting master clock to %lu\n", mclk);
}
/* We verify mclk != 0, so if anyone breaks it, here comes their Oops */
@@ -863,8 +864,8 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
pcdev->mclk = lcdclk / (2 * (div + 1));
- dev_dbg(pcdev->soc_host.dev, "LCD clock %luHz, target freq %luHz, "
- "divisor %u\n", lcdclk, mclk, div);
+ dev_dbg(&pdev->dev, "LCD clock %luHz, target freq %luHz, divisor %u\n",
+ lcdclk, mclk, div);
return div;
}
@@ -969,15 +970,20 @@ static int pxa_camera_add_device(struct soc_camera_device *icd)
goto ebusy;
}
- dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
- icd->devnum);
-
pxa_camera_activate(pcdev);
ret = icd->ops->init(icd);
+ if (ret < 0)
+ goto einit;
+
+ pcdev->icd = icd;
- if (!ret)
- pcdev->icd = icd;
+ dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
+ icd->devnum);
+ return 0;
+
+einit:
+ pxa_camera_deactivate(pcdev);
ebusy:
return ret;
}
@@ -1599,7 +1605,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
pcdev->mclk = 20000000;
}
- pcdev->mclk_divisor = mclk_get_divisor(pcdev);
+ pcdev->mclk_divisor = mclk_get_divisor(pdev, pcdev);
INIT_LIST_HEAD(&pcdev->capture);
spin_lock_init(&pcdev->lock);
@@ -1746,3 +1752,4 @@ module_exit(pxa_camera_exit);
MODULE_DESCRIPTION("PXA27x SoC Camera Host driver");
MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" PXA_CAM_DRV_NAME);
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index d369e84..ac9b467 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -360,11 +360,13 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
"SuperH Mobile CEU driver attached to camera %d\n",
icd->devnum);
+ clk_enable(pcdev->clk);
+
ret = icd->ops->init(icd);
- if (ret)
+ if (ret) {
+ clk_disable(pcdev->clk);
goto err;
-
- clk_enable(pcdev->clk);
+ }
ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
while (ceu_read(pcdev, CSTSR) & 1)
@@ -398,10 +400,10 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
}
spin_unlock_irqrestore(&pcdev->lock, flags);
- clk_disable(pcdev->clk);
-
icd->ops->release(icd);
+ clk_disable(pcdev->clk);
+
dev_info(&icd->dev,
"SuperH Mobile CEU driver detached from camera %d\n",
icd->devnum);
@@ -948,3 +950,4 @@ module_exit(sh_mobile_ceu_exit);
MODULE_DESCRIPTION("SuperH Mobile CEU driver");
MODULE_AUTHOR("Magnus Damm");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sh_mobile_ceu");
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 03a6c29..d2b765d 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -16,19 +16,21 @@
* published by the Free Software Foundation.
*/
-#include <linux/module.h>
-#include <linux/init.h>
#include <linux/device.h>
-#include <linux/list.h>
#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/list.h>
#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/vmalloc.h>
+#include <media/soc_camera.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-dev.h>
#include <media/videobuf-core.h>
-#include <media/soc_camera.h>
/* Default to VGA resolution */
#define DEFAULT_WIDTH 640
@@ -36,7 +38,7 @@
static LIST_HEAD(hosts);
static LIST_HEAD(devices);
-static DEFINE_MUTEX(list_lock);
+static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */
const struct soc_camera_data_format *soc_camera_format_by_fourcc(
struct soc_camera_device *icd, unsigned int fourcc)
@@ -207,6 +209,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv,
return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK);
}
+/* Always entered with .video_lock held */
static int soc_camera_init_user_formats(struct soc_camera_device *icd)
{
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
@@ -255,9 +258,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd)
return 0;
}
+/* Always entered with .video_lock held */
static void soc_camera_free_user_formats(struct soc_camera_device *icd)
{
+ icd->current_fmt = NULL;
vfree(icd->user_formats);
+ icd->user_formats = NULL;
}
/* Called with .vb_lock held */
@@ -308,10 +314,6 @@ static int soc_camera_open(struct file *file)
struct soc_camera_file *icf;
int ret;
- icf = vmalloc(sizeof(*icf));
- if (!icf)
- return -ENOMEM;
-
/*
* It is safe to dereference these pointers now as long as a user has
* the video device open - we are protected by the held cdev reference.
@@ -319,8 +321,17 @@ static int soc_camera_open(struct file *file)
vdev = video_devdata(file);
icd = container_of(vdev->parent, struct soc_camera_device, dev);
+
+ if (!icd->ops)
+ /* No device driver attached */
+ return -ENODEV;
+
ici = to_soc_camera_host(icd->dev.parent);
+ icf = vmalloc(sizeof(*icf));
+ if (!icf)
+ return -ENOMEM;
+
if (!try_module_get(icd->ops->owner)) {
dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
ret = -EINVAL;
@@ -333,7 +344,7 @@ static int soc_camera_open(struct file *file)
goto emgi;
}
- /* Protect against icd->remove() until we module_get() both drivers. */
+ /* Protect against icd->ops->remove() until we module_get() both drivers. */
mutex_lock(&icd->video_lock);
icf->icd = icd;
@@ -348,11 +359,16 @@ static int soc_camera_open(struct file *file)
.width = icd->width,
.height = icd->height,
.field = icd->field,
- .pixelformat = icd->current_fmt->fourcc,
- .colorspace = icd->current_fmt->colorspace,
},
};
+ ret = soc_camera_init_user_formats(icd);
+ if (ret < 0)
+ goto eiufmt;
+
+ f.fmt.pix.pixelformat = icd->current_fmt->fourcc;
+ f.fmt.pix.colorspace = icd->current_fmt->colorspace;
+
ret = ici->ops->add(icd);
if (ret < 0) {
dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
@@ -381,6 +397,8 @@ static int soc_camera_open(struct file *file)
esfmt:
ici->ops->remove(icd);
eiciadd:
+ soc_camera_free_user_formats(icd);
+eiufmt:
icd->use_count--;
mutex_unlock(&icd->video_lock);
module_put(ici->ops->owner);
@@ -400,8 +418,10 @@ static int soc_camera_close(struct file *file)
mutex_lock(&icd->video_lock);
icd->use_count--;
- if (!icd->use_count)
+ if (!icd->use_count) {
ici->ops->remove(icd);
+ soc_camera_free_user_formats(icd);
+ }
mutex_unlock(&icd->video_lock);
@@ -762,29 +782,6 @@ static int soc_camera_s_register(struct file *file, void *fh,
}
#endif
-static int device_register_link(struct soc_camera_device *icd)
-{
- int ret = dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum);
-
- if (!ret)
- ret = device_register(&icd->dev);
-
- if (ret < 0) {
- /* Prevent calling device_unregister() */
- icd->dev.parent = NULL;
- dev_err(&icd->dev, "Cannot register device: %d\n", ret);
- /* Even if probe() was unsuccessful for all registered drivers,
- * device_register() returns 0, and we add the link, just to
- * document this camera's control device */
- } else if (icd->control)
- /* Have to sysfs_remove_link() before device_unregister()? */
- if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj,
- "control"))
- dev_warn(&icd->dev,
- "Failed creating the control symlink\n");
- return ret;
-}
-
/* So far this function cannot fail */
static void scan_add_host(struct soc_camera_host *ici)
{
@@ -794,103 +791,70 @@ static void scan_add_host(struct soc_camera_host *ici)
list_for_each_entry(icd, &devices, list) {
if (icd->iface == ici->nr) {
+ int ret;
icd->dev.parent = ici->dev;
- device_register_link(icd);
- }
- }
-
- mutex_unlock(&list_lock);
-}
-
-/* return: 0 if no match found or a match found and
- * device_register() successful, error code otherwise */
-static int scan_add_device(struct soc_camera_device *icd)
-{
- struct soc_camera_host *ici;
- int ret = 0;
-
- mutex_lock(&list_lock);
-
- list_add_tail(&icd->list, &devices);
-
- /* Watch out for class_for_each_device / class_find_device API by
- * Dave Young <hidave.darkstar@gmail.com> */
- list_for_each_entry(ici, &hosts, list) {
- if (icd->iface == ici->nr) {
- ret = 1;
- icd->dev.parent = ici->dev;
- break;
+ dev_set_name(&icd->dev, "%u-%u", icd->iface,
+ icd->devnum);
+ ret = device_register(&icd->dev);
+ if (ret < 0) {
+ icd->dev.parent = NULL;
+ dev_err(&icd->dev,
+ "Cannot register device: %d\n", ret);
+ }
}
}
mutex_unlock(&list_lock);
-
- if (ret)
- ret = device_register_link(icd);
-
- return ret;
}
+static int video_dev_create(struct soc_camera_device *icd);
+/* Called during host-driver probe */
static int soc_camera_probe(struct device *dev)
{
struct soc_camera_device *icd = to_soc_camera_dev(dev);
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret;
+ struct i2c_client *client;
+ struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id);
- /*
- * Possible race scenario:
- * modprobe <camera-host-driver> triggers __func__
- * at this moment respective <camera-sensor-driver> gets rmmod'ed
- * to protect take module references.
- */
-
- if (!try_module_get(icd->ops->owner)) {
- dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
- ret = -EINVAL;
- goto emgd;
- }
-
- if (!try_module_get(ici->ops->owner)) {
- dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
- ret = -EINVAL;
- goto emgi;
+ if (!adap) {
+ ret = -ENODEV;
+ dev_err(dev, "Cannot get I2C adapter %d\n", icl->i2c_adapter_id);
+ goto ei2cga;
}
- mutex_lock(&icd->video_lock);
+ dev_info(dev, "Probing %s\n", dev_name(dev));
- /* We only call ->add() here to activate and probe the camera.
- * We shall ->remove() and deactivate it immediately afterwards. */
- ret = ici->ops->add(icd);
- if (ret < 0)
- goto eiadd;
+ client = i2c_new_device(adap, icl->board_info);
+ if (!client) {
+ ret = -ENOMEM;
+ goto ei2cnd;
+ }
- ret = icd->ops->probe(icd);
- if (ret >= 0) {
- const struct v4l2_queryctrl *qctrl;
+ /*
+ * We set icd drvdata at two locations - here and in
+ * soc_camera_video_start(). Depending on the module loading /
+ * initialisation order one of these locations will be entered first
+ */
+ /* Use to_i2c_client(dev) to recover the i2c client */
+ dev_set_drvdata(&icd->dev, &client->dev);
- qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
- icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
- qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
- icd->exposure = qctrl ? qctrl->default_value :
- (unsigned short)~0;
+ /* Do we have to sysfs_remove_link() before device_unregister()? */
+ if (sysfs_create_link(&dev->kobj, &to_soc_camera_control(icd)->kobj,
+ "control"))
+ dev_warn(dev, "Failed creating the control symlink\n");
- ret = soc_camera_init_user_formats(icd);
- if (ret < 0)
- goto eiufmt;
+ ret = video_dev_create(icd);
+ if (ret < 0)
+ goto evdc;
- icd->height = DEFAULT_HEIGHT;
- icd->width = DEFAULT_WIDTH;
- icd->field = V4L2_FIELD_ANY;
- }
+ return 0;
-eiufmt:
- ici->ops->remove(icd);
-eiadd:
- mutex_unlock(&icd->video_lock);
- module_put(ici->ops->owner);
-emgi:
- module_put(icd->ops->owner);
-emgd:
+evdc:
+ i2c_unregister_device(client);
+ei2cnd:
+ i2c_put_adapter(adap);
+ei2cga:
return ret;
}
@@ -899,11 +863,23 @@ emgd:
static int soc_camera_remove(struct device *dev)
{
struct soc_camera_device *icd = to_soc_camera_dev(dev);
+ struct video_device *vdev = icd->vdev;
- if (icd->ops->remove)
- icd->ops->remove(icd);
+ BUG_ON(!dev->parent);
- soc_camera_free_user_formats(icd);
+ if (vdev) {
+ mutex_lock(&icd->video_lock);
+ video_unregister_device(vdev);
+ icd->vdev = NULL;
+ mutex_unlock(&icd->video_lock);
+ }
+
+ if (to_soc_camera_control(icd)) {
+ struct i2c_client *client =
+ to_i2c_client(to_soc_camera_control(icd));
+ i2c_unregister_device(client);
+ i2c_put_adapter(client->adapter);
+ }
return 0;
}
@@ -998,10 +974,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
list_for_each_entry(icd, &devices, list) {
if (icd->dev.parent == ici->dev) {
+ /* The bus->remove will be called */
device_unregister(&icd->dev);
/* Not before device_unregister(), .remove
* needs parent to call ici->ops->remove() */
icd->dev.parent = NULL;
+
+ /* If the host module is loaded again, device_register()
+ * would complain "already initialised" */
memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj));
}
}
@@ -1013,26 +993,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
EXPORT_SYMBOL(soc_camera_host_unregister);
/* Image capture device */
-int soc_camera_device_register(struct soc_camera_device *icd)
+static int soc_camera_device_register(struct soc_camera_device *icd)
{
struct soc_camera_device *ix;
int num = -1, i;
- if (!icd || !icd->ops ||
- !icd->ops->probe ||
- !icd->ops->init ||
- !icd->ops->release ||
- !icd->ops->start_capture ||
- !icd->ops->stop_capture ||
- !icd->ops->set_crop ||
- !icd->ops->set_fmt ||
- !icd->ops->try_fmt ||
- !icd->ops->query_bus_param ||
- !icd->ops->set_bus_param)
- return -EINVAL;
-
for (i = 0; i < 256 && num < 0; i++) {
num = i;
+ /* Check if this index is available on this interface */
list_for_each_entry(ix, &devices, list) {
if (ix->iface == icd->iface && ix->devnum == i) {
num = -1;
@@ -1054,21 +1022,15 @@ int soc_camera_device_register(struct soc_camera_device *icd)
icd->host_priv = NULL;
mutex_init(&icd->video_lock);
- return scan_add_device(icd);
+ list_add_tail(&icd->list, &devices);
+
+ return 0;
}
-EXPORT_SYMBOL(soc_camera_device_register);
-void soc_camera_device_unregister(struct soc_camera_device *icd)
+static void soc_camera_device_unregister(struct soc_camera_device *icd)
{
- mutex_lock(&list_lock);
list_del(&icd->list);
-
- /* The bus->remove will be eventually called */
- if (icd->dev.parent)
- device_unregister(&icd->dev);
- mutex_unlock(&list_lock);
}
-EXPORT_SYMBOL(soc_camera_device_unregister);
static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
.vidioc_querycap = soc_camera_querycap,
@@ -1099,22 +1061,14 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
#endif
};
-/*
- * Usually called from the struct soc_camera_ops .probe() method, i.e., from
- * soc_camera_probe() above with .video_lock held
- */
-int soc_camera_video_start(struct soc_camera_device *icd)
+static int video_dev_create(struct soc_camera_device *icd)
{
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
- int err = -ENOMEM;
- struct video_device *vdev;
-
- if (!icd->dev.parent)
- return -ENODEV;
+ int ret;
+ struct video_device *vdev = video_device_alloc();
- vdev = video_device_alloc();
if (!vdev)
- goto evidallocd;
+ return -ENOMEM;
dev_dbg(ici->dev, "Allocated video_device %p\n", vdev);
strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
@@ -1125,10 +1079,10 @@ int soc_camera_video_start(struct soc_camera_device *icd)
vdev->ioctl_ops = &soc_camera_ioctl_ops;
vdev->release = video_device_release;
vdev->minor = -1;
- vdev->tvnorms = V4L2_STD_UNKNOWN,
+ vdev->tvnorms = V4L2_STD_UNKNOWN;
- err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
- if (err < 0) {
+ ret = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
+ if (ret < 0) {
dev_err(vdev->parent, "video_register_device failed\n");
goto evidregd;
}
@@ -1138,27 +1092,99 @@ int soc_camera_video_start(struct soc_camera_device *icd)
evidregd:
video_device_release(vdev);
-evidallocd:
- return err;
+ return ret;
+}
+
+/*
+ * Usually called from the struct soc_camera_ops .probe() method, i.e., from
+ * soc_camera_probe() above with .video_lock held
+ */
+int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ const struct v4l2_queryctrl *qctrl;
+
+ if (!icd->dev.parent)
+ return -ENODEV;
+
+ if (!icd->ops ||
+ !icd->ops->init ||
+ !icd->ops->release ||
+ !icd->ops->start_capture ||
+ !icd->ops->stop_capture ||
+ !icd->ops->set_fmt ||
+ !icd->ops->try_fmt ||
+ !icd->ops->query_bus_param ||
+ !icd->ops->set_bus_param)
+ return -EINVAL;
+
+ /* See comment in soc_camera_probe() */
+ dev_set_drvdata(&icd->dev, dev);
+
+ qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
+ icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
+ qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
+ icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0;
+
+ return ici->ops->add(icd);
}
EXPORT_SYMBOL(soc_camera_video_start);
void soc_camera_video_stop(struct soc_camera_device *icd)
{
- struct video_device *vdev = icd->vdev;
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
dev_dbg(&icd->dev, "%s\n", __func__);
- if (!icd->dev.parent || !vdev)
- return;
-
- mutex_lock(&icd->video_lock);
- video_unregister_device(vdev);
- icd->vdev = NULL;
- mutex_unlock(&icd->video_lock);
+ ici->ops->remove(icd);
}
EXPORT_SYMBOL(soc_camera_video_stop);
+static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
+{
+ struct soc_camera_link *icl = pdev->dev.platform_data;
+ struct soc_camera_device *icd;
+
+ if (!icl)
+ return -EINVAL;
+
+ icd = kzalloc(sizeof(*icd), GFP_KERNEL);
+ if (!icd)
+ return -ENOMEM;
+
+ icd->iface = icl->bus_id;
+ icl->board_info->platform_data = icd;
+ platform_set_drvdata(pdev, icd);
+ icd->dev.platform_data = icl;
+
+ return soc_camera_device_register(icd);
+}
+
+/* Only called on rmmod for each platform device, since they are not
+ * hot-pluggable. Now we know, that all our users - hosts and devices have
+ * been unloaded already */
+static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev)
+{
+ struct soc_camera_device *icd = platform_get_drvdata(pdev);
+
+ if (!icd)
+ return -EINVAL;
+
+ soc_camera_device_unregister(icd);
+
+ kfree(icd);
+
+ return 0;
+}
+
+static struct platform_driver soc_camera_pdrv = {
+ .remove = __exit_p(soc_camera_pdrv_remove),
+ .driver = {
+ .name = "soc-camera-pdrv",
+ .owner = THIS_MODULE,
+ },
+};
+
static int __init soc_camera_init(void)
{
int ret = bus_register(&soc_camera_bus_type);
@@ -1168,8 +1194,14 @@ static int __init soc_camera_init(void)
if (ret)
goto edrvr;
+ ret = platform_driver_probe(&soc_camera_pdrv, soc_camera_pdrv_probe);
+ if (ret)
+ goto epdr;
+
return 0;
+epdr:
+ driver_unregister(&ic_drv);
edrvr:
bus_unregister(&soc_camera_bus_type);
return ret;
@@ -1177,6 +1209,7 @@ edrvr:
static void __exit soc_camera_exit(void)
{
+ platform_driver_unregister(&soc_camera_pdrv);
driver_unregister(&ic_drv);
bus_unregister(&soc_camera_bus_type);
}
@@ -1187,3 +1220,4 @@ module_exit(soc_camera_exit);
MODULE_DESCRIPTION("Image capture bus driver");
MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:soc-camera-pdrv");
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c
index c486763..021f9f1 100644
--- a/drivers/media/video/soc_camera_platform.c
+++ b/drivers/media/video/soc_camera_platform.c
@@ -20,49 +20,52 @@
#include <media/soc_camera.h>
#include <media/soc_camera_platform.h>
+static const char drv_name[] = "soc_camera_platform";
+
struct soc_camera_platform_priv {
struct soc_camera_platform_info *info;
- struct soc_camera_device icd;
struct soc_camera_data_format format;
};
-static struct soc_camera_platform_info *
-soc_camera_platform_get_info(struct soc_camera_device *icd)
+static struct soc_camera_platform_info *i2c_to_info(struct i2c_client *client)
{
- struct soc_camera_platform_priv *priv;
- priv = container_of(icd, struct soc_camera_platform_priv, icd);
+ struct soc_camera_platform_priv *priv = i2c_get_clientdata(client);
return priv->info;
}
static int soc_camera_platform_init(struct soc_camera_device *icd)
{
- struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_platform_info *p = i2c_to_info(client);
- if (p->power)
- p->power(1);
+ if (p->link.power)
+ p->link.power(&client->dev, 1);
return 0;
}
static int soc_camera_platform_release(struct soc_camera_device *icd)
{
- struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_platform_info *p = i2c_to_info(client);
- if (p->power)
- p->power(0);
+ if (p->link.power)
+ p->link.power(&client->dev, 0);
return 0;
}
static int soc_camera_platform_start_capture(struct soc_camera_device *icd)
{
- struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_platform_info *p = i2c_to_info(client);
return p->set_capture(p, 1);
}
static int soc_camera_platform_stop_capture(struct soc_camera_device *icd)
{
- struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_platform_info *p = i2c_to_info(client);
return p->set_capture(p, 0);
}
@@ -75,7 +78,8 @@ static int soc_camera_platform_set_bus_param(struct soc_camera_device *icd,
static unsigned long
soc_camera_platform_query_bus_param(struct soc_camera_device *icd)
{
- struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_platform_info *p = i2c_to_info(client);
return p->bus_param;
}
@@ -94,7 +98,8 @@ static int soc_camera_platform_set_fmt(struct soc_camera_device *icd,
static int soc_camera_platform_try_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
- struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_platform_info *p = i2c_to_info(client);
struct v4l2_pix_format *pix = &f->fmt.pix;
pix->width = p->format.width;
@@ -102,31 +107,30 @@ static int soc_camera_platform_try_fmt(struct soc_camera_device *icd,
return 0;
}
-static int soc_camera_platform_video_probe(struct soc_camera_device *icd)
+static int soc_camera_platform_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
{
- struct soc_camera_platform_priv *priv;
- priv = container_of(icd, struct soc_camera_platform_priv, icd);
+ struct soc_camera_platform_priv *priv = i2c_get_clientdata(client);
+ struct soc_camera_platform_info *p = priv->info;
- priv->format.name = priv->info->format_name;
- priv->format.depth = priv->info->format_depth;
- priv->format.fourcc = priv->info->format.pixelformat;
- priv->format.colorspace = priv->info->format.colorspace;
+ priv->format.name = p->format_name;
+ priv->format.depth = p->format_depth;
+ priv->format.fourcc = p->format.pixelformat;
+ priv->format.colorspace = p->format.colorspace;
icd->formats = &priv->format;
icd->num_formats = 1;
- return soc_camera_video_start(icd);
+ return 0;
}
static void soc_camera_platform_video_remove(struct soc_camera_device *icd)
{
- soc_camera_video_stop(icd);
+ icd->ops = NULL;
}
static struct soc_camera_ops soc_camera_platform_ops = {
.owner = THIS_MODULE,
- .probe = soc_camera_platform_video_probe,
- .remove = soc_camera_platform_video_remove,
.init = soc_camera_platform_init,
.release = soc_camera_platform_release,
.start_capture = soc_camera_platform_start_capture,
@@ -138,66 +142,85 @@ static struct soc_camera_ops soc_camera_platform_ops = {
.query_bus_param = soc_camera_platform_query_bus_param,
};
-static int soc_camera_platform_probe(struct platform_device *pdev)
+static int soc_camera_platform_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
{
struct soc_camera_platform_priv *priv;
struct soc_camera_platform_info *p;
- struct soc_camera_device *icd;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct soc_camera_link *icl;
int ret;
- p = pdev->dev.platform_data;
- if (!p)
+ if (!icd) {
+ dev_err(&client->dev, "%s: missing soc-camera data!\n", drv_name);
return -EINVAL;
+ }
+
+ icl = dev_get_drvdata(&icd->dev);
+ if (!icl) {
+ dev_err(&client->dev, "%s driver needs platform data\n", drv_name);
+ return -EINVAL;
+ }
+
+ p = container_of(icl, struct soc_camera_platform_info, link);
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->info = p;
- platform_set_drvdata(pdev, priv);
+ i2c_set_clientdata(client, priv);
- icd = &priv->icd;
icd->ops = &soc_camera_platform_ops;
- icd->control = &pdev->dev;
icd->width_min = 0;
- icd->width_max = priv->info->format.width;
+ icd->width_max = p->format.width;
icd->height_min = 0;
- icd->height_max = priv->info->format.height;
+ icd->height_max = p->format.height;
icd->y_skip_top = 0;
- icd->iface = priv->info->iface;
- ret = soc_camera_device_register(icd);
- if (ret)
+ ret = soc_camera_platform_video_probe(icd, client);
+ if (ret) {
+ i2c_set_clientdata(client, NULL);
kfree(priv);
+ }
return ret;
}
-static int soc_camera_platform_remove(struct platform_device *pdev)
+static int soc_camera_platform_remove(struct i2c_client *client)
{
- struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev);
+ struct soc_camera_platform_priv *priv = i2c_get_clientdata(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
- soc_camera_device_unregister(&priv->icd);
+ soc_camera_platform_video_remove(icd);
+ i2c_set_clientdata(client, NULL);
kfree(priv);
return 0;
}
-static struct platform_driver soc_camera_platform_driver = {
+static const struct i2c_device_id soc_camera_platform_id[] = {
+ { "soc_camera_platform", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, soc_camera_platform_id);
+
+static struct i2c_driver soc_camera_platform_driver = {
.driver = {
.name = "soc_camera_platform",
},
.probe = soc_camera_platform_probe,
.remove = soc_camera_platform_remove,
+ .id_table = soc_camera_platform_id,
};
static int __init soc_camera_platform_module_init(void)
{
- return platform_driver_register(&soc_camera_platform_driver);
+ return i2c_add_driver(&soc_camera_platform_driver);
}
static void __exit soc_camera_platform_module_exit(void)
{
- platform_driver_unregister(&soc_camera_platform_driver);
+ i2c_del_driver(&soc_camera_platform_driver);
}
module_init(soc_camera_platform_module_init);
@@ -206,3 +229,4 @@ module_exit(soc_camera_platform_module_exit);
MODULE_DESCRIPTION("SoC Camera Platform driver");
MODULE_AUTHOR("Magnus Damm");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:soc_camera_platform");
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c
index a399476..419e596 100644
--- a/drivers/media/video/tw9910.c
+++ b/drivers/media/video/tw9910.c
@@ -224,8 +224,6 @@ struct tw9910_hsync_ctrl {
struct tw9910_priv {
struct tw9910_video_info *info;
- struct i2c_client *client;
- struct soc_camera_device icd;
const struct tw9910_scale_ctrl *scale;
};
@@ -511,35 +509,38 @@ tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height)
*/
static int tw9910_init(struct soc_camera_device *icd)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret = 0;
- if (priv->info->link.power) {
- ret = priv->info->link.power(&priv->client->dev, 1);
+ if (icl->power) {
+ ret = icl->power(&client->dev, 1);
if (ret < 0)
return ret;
}
- if (priv->info->link.reset)
- ret = priv->info->link.reset(&priv->client->dev);
+ if (icl->reset)
+ ret = icl->reset(&client->dev);
return ret;
}
static int tw9910_release(struct soc_camera_device *icd)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret = 0;
- if (priv->info->link.power)
- ret = priv->info->link.power(&priv->client->dev, 0);
+ if (icl->power)
+ ret = icl->power(&client->dev, 0);
return ret;
}
static int tw9910_start_capture(struct soc_camera_device *icd)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct tw9910_priv *priv = i2c_get_clientdata(client);
if (!priv->scale) {
dev_err(&icd->dev, "norm select error\n");
@@ -567,8 +568,9 @@ static int tw9910_set_bus_param(struct soc_camera_device *icd,
static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
- struct soc_camera_link *icl = priv->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct tw9910_priv *priv = i2c_get_clientdata(client);
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
@@ -610,13 +612,13 @@ static int tw9910_enum_input(struct soc_camera_device *icd,
static int tw9910_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int ret;
if (reg->reg > 0xff)
return -EINVAL;
- ret = i2c_smbus_read_byte_data(priv->client, reg->reg);
+ ret = i2c_smbus_read_byte_data(client, reg->reg);
if (ret < 0)
return ret;
@@ -631,20 +633,21 @@ static int tw9910_get_register(struct soc_camera_device *icd,
static int tw9910_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->reg > 0xff ||
reg->val > 0xff)
return -EINVAL;
- return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val);
+ return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
}
#endif
static int tw9910_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct tw9910_priv *priv = i2c_get_clientdata(client);
int ret = -EINVAL;
u8 val;
@@ -658,8 +661,8 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
/*
* reset hardware
*/
- tw9910_reset(priv->client);
- ret = tw9910_write_array(priv->client, tw9910_default_regs);
+ tw9910_reset(client);
+ ret = tw9910_write_array(client, tw9910_default_regs);
if (ret < 0)
goto tw9910_set_fmt_error;
@@ -670,7 +673,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
if (SOCAM_DATAWIDTH_16 == priv->info->buswidth)
val = LEN;
- ret = tw9910_mask_set(priv->client, OPFORM, LEN, val);
+ ret = tw9910_mask_set(client, OPFORM, LEN, val);
if (ret < 0)
goto tw9910_set_fmt_error;
@@ -698,28 +701,28 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
val = 0;
}
- ret = tw9910_mask_set(priv->client, VBICNTL, RTSEL_MASK, val);
+ ret = tw9910_mask_set(client, VBICNTL, RTSEL_MASK, val);
if (ret < 0)
goto tw9910_set_fmt_error;
/*
* set scale
*/
- ret = tw9910_set_scale(priv->client, priv->scale);
+ ret = tw9910_set_scale(client, priv->scale);
if (ret < 0)
goto tw9910_set_fmt_error;
/*
* set cropping
*/
- ret = tw9910_set_cropping(priv->client, &tw9910_cropping_ctrl);
+ ret = tw9910_set_cropping(client, &tw9910_cropping_ctrl);
if (ret < 0)
goto tw9910_set_fmt_error;
/*
* set hsync
*/
- ret = tw9910_set_hsync(priv->client, &tw9910_hsync_ctrl);
+ ret = tw9910_set_hsync(client, &tw9910_hsync_ctrl);
if (ret < 0)
goto tw9910_set_fmt_error;
@@ -727,7 +730,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
tw9910_set_fmt_error:
- tw9910_reset(priv->client);
+ tw9910_reset(client);
priv->scale = NULL;
return ret;
@@ -784,9 +787,10 @@ static int tw9910_try_fmt(struct soc_camera_device *icd,
return 0;
}
-static int tw9910_video_probe(struct soc_camera_device *icd)
+static int tw9910_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
+ struct tw9910_priv *priv = i2c_get_clientdata(client);
s32 val;
int ret;
@@ -810,10 +814,18 @@ static int tw9910_video_probe(struct soc_camera_device *icd)
icd->formats = tw9910_color_fmt;
icd->num_formats = ARRAY_SIZE(tw9910_color_fmt);
+ /* Switch master clock on */
+ ret = soc_camera_video_start(icd, &client->dev);
+ if (ret)
+ return ret;
+
/*
* check and show Product ID
*/
- val = i2c_smbus_read_byte_data(priv->client, ID);
+ val = i2c_smbus_read_byte_data(client, ID);
+
+ soc_camera_video_stop(icd);
+
if (0x0B != GET_ID(val) ||
0x00 != GET_ReV(val)) {
dev_err(&icd->dev,
@@ -824,10 +836,6 @@ static int tw9910_video_probe(struct soc_camera_device *icd)
dev_info(&icd->dev,
"tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val));
- ret = soc_camera_video_start(icd);
- if (ret < 0)
- return ret;
-
icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL;
icd->vdev->current_norm = V4L2_STD_NTSC;
@@ -836,13 +844,11 @@ static int tw9910_video_probe(struct soc_camera_device *icd)
static void tw9910_video_remove(struct soc_camera_device *icd)
{
- soc_camera_video_stop(icd);
+ icd->ops = NULL;
}
static struct soc_camera_ops tw9910_ops = {
.owner = THIS_MODULE,
- .probe = tw9910_video_probe,
- .remove = tw9910_video_remove,
.init = tw9910_init,
.release = tw9910_release,
.start_capture = tw9910_start_capture,
@@ -871,16 +877,25 @@ static int tw9910_probe(struct i2c_client *client,
{
struct tw9910_priv *priv;
struct tw9910_video_info *info;
- struct soc_camera_device *icd;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct i2c_adapter *adapter =
+ to_i2c_adapter(client->dev.parent);
+ struct soc_camera_link *icl;
const struct tw9910_scale_ctrl *scale;
int i, ret;
- info = client->dev.platform_data;
- if (!info)
+ if (!icd) {
+ dev_err(&client->dev, "TW9910: missing soc-camera data!\n");
return -EINVAL;
+ }
- if (!i2c_check_functionality(to_i2c_adapter(client->dev.parent),
- I2C_FUNC_SMBUS_BYTE_DATA)) {
+ icl = to_soc_camera_link(icd);
+ if (!icl)
+ return -EINVAL;
+
+ info = container_of(icl, struct tw9910_video_info, link);
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_err(&client->dev,
"I2C-Adapter doesn't support "
"I2C_FUNC_SMBUS_BYTE_DATA\n");
@@ -892,12 +907,9 @@ static int tw9910_probe(struct i2c_client *client,
return -ENOMEM;
priv->info = info;
- priv->client = client;
i2c_set_clientdata(client, priv);
- icd = &priv->icd;
icd->ops = &tw9910_ops;
- icd->control = &client->dev;
icd->iface = info->link.bus_id;
/*
@@ -923,8 +935,7 @@ static int tw9910_probe(struct i2c_client *client,
icd->height_min = min(scale[i].height, icd->height_min);
}
- ret = soc_camera_device_register(icd);
-
+ ret = tw9910_video_probe(icd, client);
if (ret) {
i2c_set_clientdata(client, NULL);
kfree(priv);
@@ -936,8 +947,9 @@ static int tw9910_probe(struct i2c_client *client,
static int tw9910_remove(struct i2c_client *client)
{
struct tw9910_priv *priv = i2c_get_clientdata(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
- soc_camera_device_unregister(&priv->icd);
+ tw9910_video_remove(icd);
i2c_set_clientdata(client, NULL);
kfree(priv);
return 0;
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index bef5e81..977326e 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -12,6 +12,7 @@
#ifndef SOC_CAMERA_H
#define SOC_CAMERA_H
+#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/pm.h>
#include <linux/videodev2.h>
@@ -20,7 +21,6 @@
struct soc_camera_device {
struct list_head list;
struct device dev;
- struct device *control;
unsigned short width; /* Current window */
unsigned short height; /* sizes */
unsigned short x_min; /* Camera capabilities */
@@ -97,6 +97,8 @@ struct soc_camera_link {
int bus_id;
/* Per camera SOCAM_SENSOR_* bus flags */
unsigned long flags;
+ int i2c_adapter_id;
+ struct i2c_board_info *board_info;
/* Optional callbacks to power on or off and reset the sensor */
int (*power)(struct device *, int);
int (*reset)(struct device *);
@@ -120,17 +122,25 @@ static inline struct soc_camera_host *to_soc_camera_host(struct device *dev)
return dev_get_drvdata(dev);
}
-extern int soc_camera_host_register(struct soc_camera_host *ici);
-extern void soc_camera_host_unregister(struct soc_camera_host *ici);
-extern int soc_camera_device_register(struct soc_camera_device *icd);
-extern void soc_camera_device_unregister(struct soc_camera_device *icd);
+static inline struct soc_camera_link *to_soc_camera_link(struct soc_camera_device *icd)
+{
+ return icd->dev.platform_data;
+}
-extern int soc_camera_video_start(struct soc_camera_device *icd);
-extern void soc_camera_video_stop(struct soc_camera_device *icd);
+static inline struct device *to_soc_camera_control(struct soc_camera_device *icd)
+{
+ return dev_get_drvdata(&icd->dev);
+}
-extern const struct soc_camera_data_format *soc_camera_format_by_fourcc(
+int soc_camera_host_register(struct soc_camera_host *ici);
+void soc_camera_host_unregister(struct soc_camera_host *ici);
+
+int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev);
+void soc_camera_video_stop(struct soc_camera_device *icd);
+
+const struct soc_camera_data_format *soc_camera_format_by_fourcc(
struct soc_camera_device *icd, unsigned int fourcc);
-extern const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
+const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
struct soc_camera_device *icd, unsigned int fourcc);
struct soc_camera_data_format {
@@ -159,8 +169,6 @@ struct soc_camera_format_xlate {
struct soc_camera_ops {
struct module *owner;
- int (*probe)(struct soc_camera_device *);
- void (*remove)(struct soc_camera_device *);
int (*suspend)(struct soc_camera_device *, pm_message_t state);
int (*resume)(struct soc_camera_device *);
int (*init)(struct soc_camera_device *);
diff --git a/include/media/soc_camera_platform.h b/include/media/soc_camera_platform.h
index 1d092b4..db7ff89 100644
--- a/include/media/soc_camera_platform.h
+++ b/include/media/soc_camera_platform.h
@@ -14,13 +14,12 @@
#include <linux/videodev2.h>
struct soc_camera_platform_info {
- int iface;
- char *format_name;
+ const char *format_name;
unsigned long format_depth;
struct v4l2_pix_format format;
unsigned long bus_param;
- void (*power)(int);
int (*set_capture)(struct soc_camera_platform_info *info, int enable);
+ struct soc_camera_link link;
};
#endif /* __SOC_CAMERA_H__ */
--
1.5.4
^ permalink raw reply related [flat|nested] 46+ messages in thread* Re: [PATCH 5/5] soc-camera: Convert to a platform driver
2009-04-15 12:20 ` [PATCH 5/5] soc-camera: Convert to a platform driver Guennadi Liakhovetski
@ 2009-04-15 20:36 ` Robert Jarzmik
2009-04-16 2:19 ` Dongsoo, Nathaniel Kim
1 sibling, 0 replies; 46+ messages in thread
From: Robert Jarzmik @ 2009-04-15 20:36 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: Linux Media Mailing List
Guennadi Liakhovetski <g.liakhovetski@gmx.de> writes:
> Convert soc-camera core to a platform driver. With this approach I2C
> devices are no longer statically registered in platform code, instead they
> are registered dynamically by the soc-camera core, when a match with a
> host driver is found. With this patch all platforms and all soc-camera
> device drivers are converted too. This is a preparatory step for the
> v4l-subdev conversion.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> ---
>
> Ok, here goes the bad guy. Hit it hard, hit it as hard as you can.
>
> Robert, I addressed your wishes from your previous comments, but kept the
> semicolon rearrangement hunk. I think, it is better not to terminate a
> define with a semicolon, if you like, we can make this a separate patch.
Yep, I'd like to. That's because of merge conflict with current patches through
arm tree. It will be easier for Eric or me to handle that other patch conflict,
thus letting the true v4l patch through.
> @@ -754,20 +756,21 @@ static struct platform_device var = { \
> .platform_data = pdata, \
> .parent = tparent, \
> }, \
> -};
> +}
> #define MIO_SIMPLE_DEV(var, strname, pdata) \
> MIO_PARENT_DEV(var, strname, NULL, pdata)
>
> -MIO_SIMPLE_DEV(mioa701_gpio_keys, "gpio-keys", &mioa701_gpio_keys_data)
> +MIO_SIMPLE_DEV(mioa701_gpio_keys, "gpio-keys", &mioa701_gpio_keys_data);
> MIO_PARENT_DEV(mioa701_backlight, "pwm-backlight", &pxa27x_device_pwm0.dev,
> &mioa701_backlight_data);
> -MIO_SIMPLE_DEV(mioa701_led, "leds-gpio", &gpio_led_info)
> -MIO_SIMPLE_DEV(pxa2xx_pcm, "pxa2xx-pcm", NULL)
> -MIO_SIMPLE_DEV(pxa2xx_ac97, "pxa2xx-ac97", NULL)
> -MIO_PARENT_DEV(mio_wm9713_codec, "wm9713-codec", &pxa2xx_ac97.dev, NULL)
> -MIO_SIMPLE_DEV(mioa701_sound, "mioa701-wm9713", NULL)
> -MIO_SIMPLE_DEV(mioa701_board, "mioa701-board", NULL)
> +MIO_SIMPLE_DEV(mioa701_led, "leds-gpio", &gpio_led_info);
> +MIO_SIMPLE_DEV(pxa2xx_pcm, "pxa2xx-pcm", NULL);
> +MIO_SIMPLE_DEV(pxa2xx_ac97, "pxa2xx-ac97", NULL);
> +MIO_PARENT_DEV(mio_wm9713_codec, "wm9713-codec", &pxa2xx_ac97.dev, NULL);
> +MIO_SIMPLE_DEV(mioa701_sound, "mioa701-wm9713", NULL);
> +MIO_SIMPLE_DEV(mioa701_board, "mioa701-board", NULL);
> MIO_SIMPLE_DEV(gpio_vbus, "gpio-vbus", &gpio_vbus_data);
> +MIO_SIMPLE_DEV(mioa701_camera, "soc-camera-pdrv",&iclink[0]);
\
-> still broken
(should be &iclink)
> diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
> @@ -917,6 +921,11 @@ static int mt9m111_video_probe(struct soc_camera_device *icd)
> to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
> return -ENODEV;
>
> + /* Switch master clock on */
> + ret = soc_camera_video_start(icd, &client->dev);
> + if (ret)
> + return ret;
> +
Well, I'd wish to keep only out "return" point where return value is given back
by another function (ie. have goto evid).
The reason behind is when debuggin, it's easier to put one printk("%d", ret),
and see what happened.
As the legacy mt9m111 style is :
- either return <immediate value>
- or if single occurence return func(foo)
- or error path with gotos
I'd like that "return ret" to be transformed into "goto evid" or the like.
> diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
> @@ -794,103 +791,70 @@ static void scan_add_host(struct soc_camera_host *ici)
>
> list_for_each_entry(icd, &devices, list) {
> if (icd->iface == ici->nr) {
> + int ret;
> icd->dev.parent = ici->dev;
> - device_register_link(icd);
> - }
> - }
> -
> - mutex_unlock(&list_lock);
> -}
> -
> -/* return: 0 if no match found or a match found and
> - * device_register() successful, error code otherwise */
> -static int scan_add_device(struct soc_camera_device *icd)
> -{
> - struct soc_camera_host *ici;
> - int ret = 0;
> -
> - mutex_lock(&list_lock);
> -
> - list_add_tail(&icd->list, &devices);
> -
> - /* Watch out for class_for_each_device / class_find_device API by
> - * Dave Young <hidave.darkstar@gmail.com> */
> - list_for_each_entry(ici, &hosts, list) {
> - if (icd->iface == ici->nr) {
> - ret = 1;
> - icd->dev.parent = ici->dev;
> - break;
> + dev_set_name(&icd->dev, "%u-%u", icd->iface,
> + icd->devnum);
> + ret = device_register(&icd->dev);
> + if (ret < 0) {
> + icd->dev.parent = NULL;
> + dev_err(&icd->dev,
> + "Cannot register device: %d\n", ret);
> + }
> }
> }
>
> mutex_unlock(&list_lock);
> -
> - if (ret)
> - ret = device_register_link(icd);
> -
> - return ret;
> }
>
> +static int video_dev_create(struct soc_camera_device *icd);
> +/* Called during host-driver probe */
> static int soc_camera_probe(struct device *dev)
> {
> struct soc_camera_device *icd = to_soc_camera_dev(dev);
> - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> int ret;
> + struct i2c_client *client;
> + struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id);
>
> - /*
> - * Possible race scenario:
> - * modprobe <camera-host-driver> triggers __func__
> - * at this moment respective <camera-sensor-driver> gets rmmod'ed
> - * to protect take module references.
> - */
> -
> - if (!try_module_get(icd->ops->owner)) {
> - dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
> - ret = -EINVAL;
> - goto emgd;
> - }
> -
> - if (!try_module_get(ici->ops->owner)) {
> - dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
> - ret = -EINVAL;
> - goto emgi;
> + if (!adap) {
> + ret = -ENODEV;
> + dev_err(dev, "Cannot get I2C adapter %d\n", icl->i2c_adapter_id);
> + goto ei2cga;
> }
>
> - mutex_lock(&icd->video_lock);
> + dev_info(dev, "Probing %s\n", dev_name(dev));
>
> - /* We only call ->add() here to activate and probe the camera.
> - * We shall ->remove() and deactivate it immediately afterwards. */
> - ret = ici->ops->add(icd);
> - if (ret < 0)
> - goto eiadd;
> + client = i2c_new_device(adap, icl->board_info);
> + if (!client) {
> + ret = -ENOMEM;
> + goto ei2cnd;
> + }
>
> - ret = icd->ops->probe(icd);
> - if (ret >= 0) {
> - const struct v4l2_queryctrl *qctrl;
> + /*
> + * We set icd drvdata at two locations - here and in
> + * soc_camera_video_start(). Depending on the module loading /
> + * initialisation order one of these locations will be entered first
> + */
> + /* Use to_i2c_client(dev) to recover the i2c client */
> + dev_set_drvdata(&icd->dev, &client->dev);
I didn't find any reference to unsetting the driver data. Is it normal ?
I must admit I didn't go fully through soc_camera* ... I'll try harder in the
next days.
Cheers.
--
Robert
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [PATCH 5/5] soc-camera: Convert to a platform driver
2009-04-15 12:20 ` [PATCH 5/5] soc-camera: Convert to a platform driver Guennadi Liakhovetski
2009-04-15 20:36 ` Robert Jarzmik
@ 2009-04-16 2:19 ` Dongsoo, Nathaniel Kim
2009-04-16 8:58 ` Guennadi Liakhovetski
1 sibling, 1 reply; 46+ messages in thread
From: Dongsoo, Nathaniel Kim @ 2009-04-16 2:19 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: Linux Media Mailing List, Robert Jarzmik
Hello Guennadi,
Reviewing your patch, I've got curious about a thing.
I think your soc camera subsystem is covering multiple camera
devices(sensors) in one target board, but if that is true I'm afraid
I'm confused how to handle them properly.
Because according to your patch, video_dev_create() takes camera
device as parameter and it seems to be creating device node for each
camera devices.
It means, if I have one camera host and several camera devices, there
should be several device nodes for camera devices but cannot be used
at the same time. Because typical camera host(camera interface) can
handle only one camera device at a time. But multiple device nodes
mean "we can open and handle them at the same time".
How about registering camera host device as v4l2 device and make
camera device a input device which could be handled using
VIDIOC_S_INPUT/G_INPUT api?
Actually, I'm working on S3C64xx camera interface driver with soc
camera subsystem, and I'm facing that issue right now because I've got
dual camera on my target board.
I hope you to consider this concept, and also want to know your opinion.
Cheers,
Nate
On Wed, Apr 15, 2009 at 9:20 PM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> Convert soc-camera core to a platform driver. With this approach I2C
> devices are no longer statically registered in platform code, instead they
> are registered dynamically by the soc-camera core, when a match with a
> host driver is found. With this patch all platforms and all soc-camera
> device drivers are converted too. This is a preparatory step for the
> v4l-subdev conversion.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> ---
>
> Ok, here goes the bad guy. Hit it hard, hit it as hard as you can.
>
> Robert, I addressed your wishes from your previous comments, but kept the
> semicolon rearrangement hunk. I think, it is better not to terminate a
> define with a semicolon, if you like, we can make this a separate patch.
>
> arch/arm/mach-mx3/pcm037.c | 25 ++-
> arch/arm/mach-pxa/em-x270.c | 21 ++-
> arch/arm/mach-pxa/mioa701.c | 35 ++--
> arch/arm/mach-pxa/pcm990-baseboard.c | 52 ++++-
> arch/sh/boards/board-ap325rxa.c | 55 +++--
> arch/sh/boards/mach-migor/setup.c | 77 ++++--
> drivers/media/video/mt9m001.c | 113 ++++-----
> drivers/media/video/mt9m111.c | 152 ++++++------
> drivers/media/video/mt9t031.c | 113 ++++-----
> drivers/media/video/mt9v022.c | 118 +++++-----
> drivers/media/video/mx3_camera.c | 27 ++-
> drivers/media/video/ov772x.c | 148 +++++++-----
> drivers/media/video/pxa_camera.c | 27 ++-
> drivers/media/video/sh_mobile_ceu_camera.c | 13 +-
> drivers/media/video/soc_camera.c | 364 +++++++++++++++-------------
> drivers/media/video/soc_camera_platform.c | 112 +++++----
> drivers/media/video/tw9910.c | 106 +++++----
> include/media/soc_camera.h | 30 ++-
> include/media/soc_camera_platform.h | 5 +-
> 19 files changed, 894 insertions(+), 699 deletions(-)
>
> diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c
> index 6bfd29a..00ce1eb 100644
> --- a/arch/arm/mach-mx3/pcm037.c
> +++ b/arch/arm/mach-mx3/pcm037.c
> @@ -241,9 +241,17 @@ static int pcm037_camera_power(struct device *dev, int on)
> return 0;
> }
>
> +static struct i2c_board_info pcm037_i2c_2_devices[] = {
> + {
> + I2C_BOARD_INFO("mt9t031", 0x5d),
> + },
> +};
> +
> static struct soc_camera_link iclink = {
> - .bus_id = 0, /* Must match with the camera ID */
> - .power = pcm037_camera_power,
> + .bus_id = 0, /* Must match with the camera ID */
> + .power = pcm037_camera_power,
> + .board_info = &pcm037_i2c_2_devices[0],
> + .i2c_adapter_id = 2,
> };
>
> static struct i2c_board_info pcm037_i2c_devices[] = {
> @@ -256,9 +264,10 @@ static struct i2c_board_info pcm037_i2c_devices[] = {
> }
> };
>
> -static struct i2c_board_info pcm037_i2c_2_devices[] = {
> - {
> - I2C_BOARD_INFO("mt9t031", 0x5d),
> +static struct platform_device pcm037_camera = {
> + .name = "soc-camera-pdrv",
> + .id = 0,
> + .dev = {
> .platform_data = &iclink,
> },
> };
> @@ -338,6 +347,9 @@ static struct platform_device *devices[] __initdata = {
> &pcm037_flash,
> &pcm037_eth,
> &pcm037_sram_device,
> +#if defined(CONFIG_I2C_IMX) || defined(CONFIG_I2C_IMX_MODULE)
> + &pcm037_camera,
> +#endif
> };
>
> static struct ipu_platform_data mx3_ipu_data = {
> @@ -395,9 +407,6 @@ static void __init mxc_board_init(void)
> i2c_register_board_info(1, pcm037_i2c_devices,
> ARRAY_SIZE(pcm037_i2c_devices));
>
> - i2c_register_board_info(2, pcm037_i2c_2_devices,
> - ARRAY_SIZE(pcm037_i2c_2_devices));
> -
> mxc_register_device(&mxc_i2c_device1, &pcm037_i2c_1_data);
> mxc_register_device(&mxc_i2c_device2, &pcm037_i2c_2_data);
> #endif
> diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
> index 920dfb8..d4eb0c7 100644
> --- a/arch/arm/mach-pxa/em-x270.c
> +++ b/arch/arm/mach-pxa/em-x270.c
> @@ -847,14 +847,23 @@ static int em_x270_sensor_power(struct device *dev, int on)
> return 0;
> }
>
> -static struct soc_camera_link iclink = {
> - .bus_id = 0,
> - .power = em_x270_sensor_power,
> -};
> -
> static struct i2c_board_info em_x270_i2c_cam_info[] = {
> {
> I2C_BOARD_INFO("mt9m111", 0x48),
> + },
> +};
> +
> +static struct soc_camera_link iclink = {
> + .bus_id = 0,
> + .power = em_x270_sensor_power,
> + .board_info = &em_x270_i2c_cam_info[0],
> + .i2c_adapter_id = 0,
> +};
> +
> +static struct platform_device em_x270_camera = {
> + .name = "soc-camera-pdrv",
> + .id = -1,
> + .dev = {
> .platform_data = &iclink,
> },
> };
> @@ -866,8 +875,8 @@ static struct i2c_pxa_platform_data em_x270_i2c_info = {
> static void __init em_x270_init_camera(void)
> {
> pxa_set_i2c_info(&em_x270_i2c_info);
> - i2c_register_board_info(0, ARRAY_AND_SIZE(em_x270_i2c_cam_info));
> pxa_set_camera_info(&em_x270_camera_platform_data);
> + platform_device_register(&em_x270_camera);
> }
> #else
> static inline void em_x270_init_camera(void) {}
> diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
> index 97c93a7..444818b 100644
> --- a/arch/arm/mach-pxa/mioa701.c
> +++ b/arch/arm/mach-pxa/mioa701.c
> @@ -724,19 +724,21 @@ struct pxacamera_platform_data mioa701_pxacamera_platform_data = {
> .mclk_10khz = 5000,
> };
>
> -static struct soc_camera_link iclink = {
> - .bus_id = 0, /* Must match id in pxa27x_device_camera in device.c */
> -};
> -
> -/* Board I2C devices. */
> +/*
> + * Board I2C devices
> + */
> static struct i2c_board_info __initdata mioa701_i2c_devices[] = {
> {
> - /* Must initialize before the camera(s) */
> I2C_BOARD_INFO("mt9m111", 0x5d),
> - .platform_data = &iclink,
> },
> };
>
> +static struct soc_camera_link iclink = {
> + .bus_id = 0, /* Match id in pxa27x_device_camera in device.c */
> + .board_info = &mioa701_i2c_devices[0],
> + .i2c_adapter_id = 0,
> +};
> +
> struct i2c_pxa_platform_data i2c_pdata = {
> .fast_mode = 1,
> };
> @@ -754,20 +756,21 @@ static struct platform_device var = { \
> .platform_data = pdata, \
> .parent = tparent, \
> }, \
> -};
> +}
> #define MIO_SIMPLE_DEV(var, strname, pdata) \
> MIO_PARENT_DEV(var, strname, NULL, pdata)
>
> -MIO_SIMPLE_DEV(mioa701_gpio_keys, "gpio-keys", &mioa701_gpio_keys_data)
> +MIO_SIMPLE_DEV(mioa701_gpio_keys, "gpio-keys", &mioa701_gpio_keys_data);
> MIO_PARENT_DEV(mioa701_backlight, "pwm-backlight", &pxa27x_device_pwm0.dev,
> &mioa701_backlight_data);
> -MIO_SIMPLE_DEV(mioa701_led, "leds-gpio", &gpio_led_info)
> -MIO_SIMPLE_DEV(pxa2xx_pcm, "pxa2xx-pcm", NULL)
> -MIO_SIMPLE_DEV(pxa2xx_ac97, "pxa2xx-ac97", NULL)
> -MIO_PARENT_DEV(mio_wm9713_codec, "wm9713-codec", &pxa2xx_ac97.dev, NULL)
> -MIO_SIMPLE_DEV(mioa701_sound, "mioa701-wm9713", NULL)
> -MIO_SIMPLE_DEV(mioa701_board, "mioa701-board", NULL)
> +MIO_SIMPLE_DEV(mioa701_led, "leds-gpio", &gpio_led_info);
> +MIO_SIMPLE_DEV(pxa2xx_pcm, "pxa2xx-pcm", NULL);
> +MIO_SIMPLE_DEV(pxa2xx_ac97, "pxa2xx-ac97", NULL);
> +MIO_PARENT_DEV(mio_wm9713_codec, "wm9713-codec", &pxa2xx_ac97.dev, NULL);
> +MIO_SIMPLE_DEV(mioa701_sound, "mioa701-wm9713", NULL);
> +MIO_SIMPLE_DEV(mioa701_board, "mioa701-board", NULL);
> MIO_SIMPLE_DEV(gpio_vbus, "gpio-vbus", &gpio_vbus_data);
> +MIO_SIMPLE_DEV(mioa701_camera, "soc-camera-pdrv",&iclink[0]);
>
> static struct platform_device *devices[] __initdata = {
> &mioa701_gpio_keys,
> @@ -780,6 +783,7 @@ static struct platform_device *devices[] __initdata = {
> &power_dev,
> &strataflash,
> &gpio_vbus,
> + &mioa701_camera,
> &mioa701_board,
> };
>
> @@ -825,7 +829,6 @@ static void __init mioa701_machine_init(void)
>
> pxa_set_i2c_info(&i2c_pdata);
> pxa_set_camera_info(&mioa701_pxacamera_platform_data);
> - i2c_register_board_info(0, ARRAY_AND_SIZE(mioa701_i2c_devices));
> }
>
> static void mioa701_machine_exit(void)
> diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
> index 9ce1ef2..619b90e 100644
> --- a/arch/arm/mach-pxa/pcm990-baseboard.c
> +++ b/arch/arm/mach-pxa/pcm990-baseboard.c
> @@ -427,25 +427,54 @@ static void pcm990_camera_free_bus(struct soc_camera_link *link)
> gpio_bus_switch = -EINVAL;
> }
>
> -static struct soc_camera_link iclink = {
> - .bus_id = 0, /* Must match with the camera ID above */
> - .query_bus_param = pcm990_camera_query_bus_param,
> - .set_bus_param = pcm990_camera_set_bus_param,
> - .free_bus = pcm990_camera_free_bus,
> -};
> -
> /* Board I2C devices. */
> static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
> {
> /* Must initialize before the camera(s) */
> I2C_BOARD_INFO("pca9536", 0x41),
> .platform_data = &pca9536_data,
> - }, {
> + },
> +};
> +
> +static struct i2c_board_info __initdata pcm990_camera_i2c[] = {
> + {
> I2C_BOARD_INFO("mt9v022", 0x48),
> - .platform_data = &iclink, /* With extender */
> }, {
> I2C_BOARD_INFO("mt9m001", 0x5d),
> - .platform_data = &iclink, /* With extender */
> + },
> +};
> +
> +static struct soc_camera_link iclink[] = {
> + {
> + .bus_id = 0, /* Must match with the camera ID */
> + .board_info = &pcm990_camera_i2c[0],
> + .i2c_adapter_id = 0,
> + .query_bus_param = pcm990_camera_query_bus_param,
> + .set_bus_param = pcm990_camera_set_bus_param,
> + .free_bus = pcm990_camera_free_bus,
> + }, {
> + .bus_id = 0, /* Must match with the camera ID */
> + .board_info = &pcm990_camera_i2c[1],
> + .i2c_adapter_id = 0,
> + .query_bus_param = pcm990_camera_query_bus_param,
> + .set_bus_param = pcm990_camera_set_bus_param,
> + .free_bus = pcm990_camera_free_bus,
> + },
> +};
> +
> +static struct platform_device pcm990_camera[] = {
> + {
> + .name = "soc-camera-pdrv",
> + .id = 0,
> + .dev = {
> + .platform_data = &iclink[0],
> + },
> + }, {
> + .name = "soc-camera-pdrv",
> + .id = 1,
> + .dev = {
> + .platform_data = &iclink[1],
> + },
> },
> };
> #endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */
> @@ -501,6 +530,9 @@ void __init pcm990_baseboard_init(void)
> pxa_set_camera_info(&pcm990_pxacamera_platform_data);
>
> i2c_register_board_info(0, ARRAY_AND_SIZE(pcm990_i2c_devices));
> +
> + platform_device_register(&pcm990_camera[0]);
> + platform_device_register(&pcm990_camera[1]);
> #endif
>
> printk(KERN_INFO "PCM-990 Evaluation baseboard initialized\n");
> diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c
> index e27655b..37c9139 100644
> --- a/arch/sh/boards/board-ap325rxa.c
> +++ b/arch/sh/boards/board-ap325rxa.c
> @@ -228,12 +228,6 @@ static struct platform_device lcdc_device = {
> },
> };
>
> -static void camera_power(int val)
> -{
> - gpio_set_value(GPIO_PTZ5, val); /* RST_CAM/RSTB */
> - mdelay(10);
> -}
> -
> #ifdef CONFIG_I2C
> static unsigned char camera_ncm03j_magic[] =
> {
> @@ -255,23 +249,28 @@ static unsigned char camera_ncm03j_magic[] =
> 0x63, 0xD4, 0x64, 0xEA, 0xD6, 0x0F,
> };
>
> -static int camera_set_capture(struct soc_camera_platform_info *info,
> - int enable)
> +static int ap325rxa_camera_power(struct device *dev, int on)
> {
> - struct i2c_adapter *a = i2c_get_adapter(0);
> + gpio_set_value(GPIO_PTZ5, on); /* RST_CAM/RSTB */
> + mdelay(10);
> + return 0;
> +}
> +
> +static int ap325rxa_camera_set_capture(struct soc_camera_platform_info *info,
> + int enable)
> +{
> + struct i2c_adapter *a = i2c_get_adapter(info->link.i2c_adapter_id);
> struct i2c_msg msg;
> int ret = 0;
> int i;
>
> - camera_power(0);
> if (!enable)
> - return 0; /* no disable for now */
> + return ap325rxa_camera_power(NULL, 0); /* no disable for now */
>
> - camera_power(1);
> for (i = 0; i < ARRAY_SIZE(camera_ncm03j_magic); i += 2) {
> u_int8_t buf[8];
>
> - msg.addr = 0x6e;
> + msg.addr = info->link.board_info->addr;
> msg.buf = buf;
> msg.len = 2;
> msg.flags = 0;
> @@ -285,8 +284,11 @@ static int camera_set_capture(struct soc_camera_platform_info *info,
> return ret;
> }
>
> +static struct i2c_board_info __initdata ap325rxa_camera_i2c = {
> + I2C_BOARD_INFO("soc_camera_platform", 0x6e),
> +};
> +
> static struct soc_camera_platform_info camera_info = {
> - .iface = 0,
> .format_name = "UYVY",
> .format_depth = 16,
> .format = {
> @@ -296,22 +298,29 @@ static struct soc_camera_platform_info camera_info = {
> .height = 480,
> },
> .bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
> - SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
> - .set_capture = camera_set_capture,
> + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
> + .set_capture = ap325rxa_camera_set_capture,
> + .link = {
> + .bus_id = 0,
> + .board_info = &ap325rxa_camera_i2c,
> + .i2c_adapter_id = 0,
> + .power = ap325rxa_camera_power,
> + },
> };
>
> -static struct platform_device camera_device = {
> - .name = "soc_camera_platform",
> - .dev = {
> - .platform_data = &camera_info,
> +static struct platform_device ap325rxa_camera = {
> + .name = "soc-camera-pdrv",
> + .id = -1,
> + .dev = {
> + .platform_data = &camera_info.link,
> },
> };
> #endif /* CONFIG_I2C */
>
> static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
> .flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
> - SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER |
> - SOCAM_DATAWIDTH_8,
> + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH |
> + SOCAM_MASTER | SOCAM_DATAWIDTH_8,
> };
>
> static struct resource ceu_resources[] = {
> @@ -360,7 +369,7 @@ static struct platform_device *ap325rxa_devices[] __initdata = {
> &lcdc_device,
> &ceu_device,
> #ifdef CONFIG_I2C
> - &camera_device,
> + &ap325rxa_camera,
> #endif
> &nand_flash_device,
> &sdcard_cn3_device,
> diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
> index 4fd6a72..b8cb246 100644
> --- a/arch/sh/boards/mach-migor/setup.c
> +++ b/arch/sh/boards/mach-migor/setup.c
> @@ -383,21 +383,6 @@ static struct platform_device migor_ceu_device = {
> },
> };
>
> -static struct ov772x_camera_info ov7725_info = {
> - .buswidth = SOCAM_DATAWIDTH_8,
> - .link = {
> - .power = ov7725_power,
> - },
> -};
> -
> -static struct tw9910_video_info tw9910_info = {
> - .buswidth = SOCAM_DATAWIDTH_8,
> - .mpout = TW9910_MPO_FIELD,
> - .link = {
> - .power = tw9910_power,
> - }
> -};
> -
> struct spi_gpio_platform_data sdcard_cn9_platform_data = {
> .sck = GPIO_PTD0,
> .mosi = GPIO_PTD1,
> @@ -412,16 +397,6 @@ static struct platform_device sdcard_cn9_device = {
> },
> };
>
> -static struct platform_device *migor_devices[] __initdata = {
> - &smc91x_eth_device,
> - &sh_keysc_device,
> - &migor_lcdc_device,
> - &migor_ceu_device,
> - &migor_nor_flash_device,
> - &migor_nand_flash_device,
> - &sdcard_cn9_device,
> -};
> -
> static struct i2c_board_info migor_i2c_devices[] = {
> {
> I2C_BOARD_INFO("rs5c372b", 0x32),
> @@ -430,16 +405,64 @@ static struct i2c_board_info migor_i2c_devices[] = {
> I2C_BOARD_INFO("migor_ts", 0x51),
> .irq = 38, /* IRQ6 */
> },
> +};
> +
> +static struct i2c_board_info migor_camera_i2c[] = {
> {
> I2C_BOARD_INFO("ov772x", 0x21),
> - .platform_data = &ov7725_info,
> },
> {
> I2C_BOARD_INFO("tw9910", 0x45),
> - .platform_data = &tw9910_info,
> },
> };
>
> +static struct ov772x_camera_info ov7725_info = {
> + .buswidth = SOCAM_DATAWIDTH_8,
> + .link = {
> + .power = ov7725_power,
> + .board_info = &migor_camera_i2c[0],
> + .i2c_adapter_id = 0,
> + },
> +};
> +
> +static struct tw9910_video_info tw9910_info = {
> + .buswidth = SOCAM_DATAWIDTH_8,
> + .mpout = TW9910_MPO_FIELD,
> + .link = {
> + .power = tw9910_power,
> + .board_info = &migor_camera_i2c[1],
> + .i2c_adapter_id = 0,
> + }
> +};
> +
> +static struct platform_device migor_camera[] = {
> + {
> + .name = "soc-camera-pdrv",
> + .id = 0,
> + .dev = {
> + .platform_data = &ov7725_info.link,
> + },
> + }, {
> + .name = "soc-camera-pdrv",
> + .id = 1,
> + .dev = {
> + .platform_data = &tw9910_info.link,
> + },
> + },
> +};
> +
> +static struct platform_device *migor_devices[] __initdata = {
> + &smc91x_eth_device,
> + &sh_keysc_device,
> + &migor_lcdc_device,
> + &migor_ceu_device,
> + &migor_nor_flash_device,
> + &migor_nand_flash_device,
> + &sdcard_cn9_device,
> + &migor_camera[0],
> + &migor_camera[1],
> +};
> +
> static struct spi_board_info migor_spi_devices[] = {
> {
> .modalias = "mmc_spi",
> diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
> index 459c04c..b0f4ad5 100644
> --- a/drivers/media/video/mt9m001.c
> +++ b/drivers/media/video/mt9m001.c
> @@ -69,8 +69,6 @@ static const struct soc_camera_data_format mt9m001_monochrome_formats[] = {
> };
>
> struct mt9m001 {
> - struct i2c_client *client;
> - struct soc_camera_device icd;
> int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
> unsigned char autoexposure;
> };
> @@ -111,11 +109,11 @@ static int reg_clear(struct i2c_client *client, const u8 reg,
>
> static int mt9m001_init(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> int ret;
>
> - dev_dbg(icd->vdev->parent, "%s\n", __func__);
> + dev_dbg(&icd->dev, "%s\n", __func__);
>
> if (icl->power) {
> ret = icl->power(&client->dev, 1);
> @@ -147,8 +145,8 @@ static int mt9m001_init(struct soc_camera_device *icd)
>
> static int mt9m001_release(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
>
> /* Disable the chip */
> reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
> @@ -161,7 +159,7 @@ static int mt9m001_release(struct soc_camera_device *icd)
>
> static int mt9m001_start_capture(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> /* Switch to master "normal" mode */
> if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0)
> @@ -171,7 +169,7 @@ static int mt9m001_start_capture(struct soc_camera_device *icd)
>
> static int mt9m001_stop_capture(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> /* Stop sensor readout */
> if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0)
> @@ -182,8 +180,7 @@ static int mt9m001_stop_capture(struct soc_camera_device *icd)
> static int mt9m001_set_bus_param(struct soc_camera_device *icd,
> unsigned long flags)
> {
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> - struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK;
>
> /* Only one width bit may be set */
> @@ -205,8 +202,7 @@ static int mt9m001_set_bus_param(struct soc_camera_device *icd,
>
> static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
> {
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> - struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> /* MT9M001 has all capture_format parameters fixed */
> unsigned long flags = SOCAM_PCLK_SAMPLE_FALLING |
> SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
> @@ -223,8 +219,8 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
> static int mt9m001_set_crop(struct soc_camera_device *icd,
> struct v4l2_rect *rect)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
> int ret;
> const u16 hblank = 9, vblank = 25;
>
> @@ -296,12 +292,13 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd,
> static int mt9m001_get_chip_id(struct soc_camera_device *icd,
> struct v4l2_dbg_chip_ident *id)
> {
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
>
> if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
> return -EINVAL;
>
> - if (id->match.addr != mt9m001->client->addr)
> + if (id->match.addr != client->addr)
> return -ENODEV;
>
> id->ident = mt9m001->model;
> @@ -314,7 +311,7 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd,
> static int mt9m001_get_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
> return -EINVAL;
> @@ -334,7 +331,7 @@ static int mt9m001_get_register(struct soc_camera_device *icd,
> static int mt9m001_set_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
> return -EINVAL;
> @@ -387,15 +384,11 @@ static const struct v4l2_queryctrl mt9m001_controls[] = {
> }
> };
>
> -static int mt9m001_video_probe(struct soc_camera_device *);
> -static void mt9m001_video_remove(struct soc_camera_device *);
> static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *);
> static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *);
>
> static struct soc_camera_ops mt9m001_ops = {
> .owner = THIS_MODULE,
> - .probe = mt9m001_video_probe,
> - .remove = mt9m001_video_remove,
> .init = mt9m001_init,
> .release = mt9m001_release,
> .start_capture = mt9m001_start_capture,
> @@ -418,8 +411,8 @@ static struct soc_camera_ops mt9m001_ops = {
>
> static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
> int data;
>
> switch (ctrl->id) {
> @@ -438,8 +431,8 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro
>
> static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
> const struct v4l2_queryctrl *qctrl;
> int data;
>
> @@ -531,11 +524,11 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
>
> /* Interface active, can use i2c. If it fails, it can indeed mean, that
> * this wasn't our capture interface, so, we wait for the right one */
> -static int mt9m001_video_probe(struct soc_camera_device *icd)
> +static int mt9m001_video_probe(struct soc_camera_device *icd,
> + struct i2c_client *client)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> s32 data;
> int ret;
> unsigned long flags;
> @@ -546,6 +539,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
> to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
> return -ENODEV;
>
> + /* Switch master clock on */
> + ret = soc_camera_video_start(icd, &client->dev);
> + if (ret)
> + return ret;
> +
> /* Enable the chip */
> data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
> dev_dbg(&icd->dev, "write: %d\n", data);
> @@ -553,6 +551,8 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
> /* Read out the chip version register */
> data = reg_read(client, MT9M001_CHIP_VERSION);
>
> + soc_camera_video_stop(icd);
> +
> /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
> switch (data) {
> case 0x8411:
> @@ -565,10 +565,9 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
> icd->formats = mt9m001_monochrome_formats;
> break;
> default:
> - ret = -ENODEV;
> dev_err(&icd->dev,
> "No MT9M001 chip detected, register read %x\n", data);
> - goto ei2c;
> + return -ENODEV;
> }
>
> icd->num_formats = 0;
> @@ -594,26 +593,17 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
> dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
> data == 0x8431 ? "C12STM" : "C12ST");
>
> - /* Now that we know the model, we can start video */
> - ret = soc_camera_video_start(icd);
> - if (ret)
> - goto eisis;
> -
> return 0;
> -
> -eisis:
> -ei2c:
> - return ret;
> }
>
> static void mt9m001_video_remove(struct soc_camera_device *icd)
> {
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> - struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
>
> - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr,
> + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
> icd->dev.parent, icd->vdev);
> - soc_camera_video_stop(icd);
> + icd->ops = NULL;
> if (icl->free_bus)
> icl->free_bus(icl);
> }
> @@ -622,11 +612,17 @@ static int mt9m001_probe(struct i2c_client *client,
> const struct i2c_device_id *did)
> {
> struct mt9m001 *mt9m001;
> - struct soc_camera_device *icd;
> + struct soc_camera_device *icd = client->dev.platform_data;
> struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct soc_camera_link *icl;
> int ret;
>
> + if (!icd) {
> + dev_err(&client->dev, "MT9M001: missing soc-camera data!\n");
> + return -EINVAL;
> + }
> +
> + icl = to_soc_camera_link(icd);
> if (!icl) {
> dev_err(&client->dev, "MT9M001 driver needs platform data\n");
> return -EINVAL;
> @@ -642,13 +638,10 @@ static int mt9m001_probe(struct i2c_client *client,
> if (!mt9m001)
> return -ENOMEM;
>
> - mt9m001->client = client;
> i2c_set_clientdata(client, mt9m001);
>
> /* Second stage probe - when a capture adapter is there */
> - icd = &mt9m001->icd;
> icd->ops = &mt9m001_ops;
> - icd->control = &client->dev;
> icd->x_min = 20;
> icd->y_min = 12;
> icd->x_current = 20;
> @@ -658,27 +651,27 @@ static int mt9m001_probe(struct i2c_client *client,
> icd->height_min = 32;
> icd->height_max = 1024;
> icd->y_skip_top = 1;
> - icd->iface = icl->bus_id;
> /* Simulated autoexposure. If enabled, we calculate shutter width
> * ourselves in the driver based on vertical blanking and frame width */
> mt9m001->autoexposure = 1;
>
> - ret = soc_camera_device_register(icd);
> - if (ret)
> - goto eisdr;
> -
> - return 0;
> + ret = mt9m001_video_probe(icd, client);
> + if (ret) {
> + i2c_set_clientdata(client, NULL);
> + kfree(mt9m001);
> + }
>
> -eisdr:
> - kfree(mt9m001);
> return ret;
> }
>
> static int mt9m001_remove(struct i2c_client *client)
> {
> struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
> + struct soc_camera_device *icd = client->dev.platform_data;
>
> - soc_camera_device_unregister(&mt9m001->icd);
> + mt9m001_video_remove(icd);
> + i2c_set_clientdata(client, NULL);
> + client->driver = NULL;
> kfree(mt9m001);
>
> return 0;
> diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
> index fc5e2de..330753a 100644
> --- a/drivers/media/video/mt9m111.c
> +++ b/drivers/media/video/mt9m111.c
> @@ -148,8 +148,6 @@ enum mt9m111_context {
> };
>
> struct mt9m111 {
> - struct i2c_client *client;
> - struct soc_camera_device icd;
> int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */
> enum mt9m111_context context;
> struct v4l2_rect rect;
> @@ -203,7 +201,7 @@ static int mt9m111_reg_write(struct i2c_client *client, const u16 reg,
>
> ret = reg_page_map_set(client, reg);
> if (!ret)
> - ret = i2c_smbus_write_word_data(client, (reg & 0xff),
> + ret = i2c_smbus_write_word_data(client, reg & 0xff,
> swab16(data));
> dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
> return ret;
> @@ -232,7 +230,7 @@ static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg,
> static int mt9m111_set_context(struct soc_camera_device *icd,
> enum mt9m111_context ctxt)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B
> | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B
> | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B
> @@ -249,8 +247,8 @@ static int mt9m111_set_context(struct soc_camera_device *icd,
> static int mt9m111_setup_rect(struct soc_camera_device *icd,
> struct v4l2_rect *rect)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret, is_raw_format;
> int width = rect->width;
> int height = rect->height;
> @@ -294,7 +292,7 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd,
>
> static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> int ret;
>
> ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt);
> @@ -315,7 +313,8 @@ static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd)
>
> static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int val = 0;
>
> if (mt9m111->swap_rgb_red_blue)
> @@ -329,7 +328,8 @@ static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd)
>
> static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int val = 0;
>
> if (mt9m111->swap_rgb_red_blue)
> @@ -343,7 +343,8 @@ static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd)
>
> static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int val = 0;
>
> if (mt9m111->swap_yuv_cb_cr)
> @@ -356,9 +357,9 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
>
> static int mt9m111_enable(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> if (icl->power) {
> @@ -378,9 +379,9 @@ static int mt9m111_enable(struct soc_camera_device *icd)
>
> static int mt9m111_disable(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE);
> @@ -395,8 +396,8 @@ static int mt9m111_disable(struct soc_camera_device *icd)
>
> static int mt9m111_reset(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> int ret;
>
> ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
> @@ -424,8 +425,7 @@ static int mt9m111_stop_capture(struct soc_camera_device *icd)
>
> static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> - struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |
> SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
> SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
> @@ -441,7 +441,8 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
> static int mt9m111_set_crop(struct soc_camera_device *icd,
> struct v4l2_rect *rect)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
> @@ -456,7 +457,8 @@ static int mt9m111_set_crop(struct soc_camera_device *icd,
>
> static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> switch (pixfmt) {
> @@ -506,7 +508,8 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
> static int mt9m111_set_fmt(struct soc_camera_device *icd,
> struct v4l2_format *f)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> struct v4l2_pix_format *pix = &f->fmt.pix;
> struct v4l2_rect rect = {
> .left = mt9m111->rect.left,
> @@ -544,12 +547,13 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd,
> static int mt9m111_get_chip_id(struct soc_camera_device *icd,
> struct v4l2_dbg_chip_ident *id)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>
> if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
> return -EINVAL;
>
> - if (id->match.addr != mt9m111->client->addr)
> + if (id->match.addr != client->addr)
> return -ENODEV;
>
> id->ident = mt9m111->model;
> @@ -562,8 +566,8 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd,
> static int mt9m111_get_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> int val;
> - struct i2c_client *client = to_i2c_client(icd->control);
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
> return -EINVAL;
> @@ -583,7 +587,7 @@ static int mt9m111_get_register(struct soc_camera_device *icd,
> static int mt9m111_set_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
> return -EINVAL;
> @@ -635,8 +639,6 @@ static const struct v4l2_queryctrl mt9m111_controls[] = {
> }
> };
>
> -static int mt9m111_video_probe(struct soc_camera_device *);
> -static void mt9m111_video_remove(struct soc_camera_device *);
> static int mt9m111_get_control(struct soc_camera_device *,
> struct v4l2_control *);
> static int mt9m111_set_control(struct soc_camera_device *,
> @@ -647,8 +649,6 @@ static int mt9m111_release(struct soc_camera_device *icd);
>
> static struct soc_camera_ops mt9m111_ops = {
> .owner = THIS_MODULE,
> - .probe = mt9m111_video_probe,
> - .remove = mt9m111_video_remove,
> .init = mt9m111_init,
> .resume = mt9m111_resume,
> .release = mt9m111_release,
> @@ -672,8 +672,8 @@ static struct soc_camera_ops mt9m111_ops = {
>
> static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> if (mt9m111->context == HIGHPOWER) {
> @@ -693,7 +693,7 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
>
> static int mt9m111_get_global_gain(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> int data;
>
> data = reg_read(GLOBAL_GAIN);
> @@ -705,7 +705,7 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd)
>
> static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> u16 val;
>
> if (gain > 63 * 2 * 2)
> @@ -724,8 +724,8 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
>
> static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> if (on)
> @@ -741,8 +741,8 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
>
> static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> if (on)
> @@ -759,8 +759,8 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
> static int mt9m111_get_control(struct soc_camera_device *icd,
> struct v4l2_control *ctrl)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int data;
>
> switch (ctrl->id) {
> @@ -803,7 +803,8 @@ static int mt9m111_get_control(struct soc_camera_device *icd,
> static int mt9m111_set_control(struct soc_camera_device *icd,
> struct v4l2_control *ctrl)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> const struct v4l2_queryctrl *qctrl;
> int ret;
>
> @@ -841,7 +842,8 @@ static int mt9m111_set_control(struct soc_camera_device *icd,
>
> static int mt9m111_restore_state(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>
> mt9m111_set_context(icd, mt9m111->context);
> mt9m111_set_pixfmt(icd, mt9m111->pixfmt);
> @@ -856,7 +858,8 @@ static int mt9m111_restore_state(struct soc_camera_device *icd)
>
> static int mt9m111_resume(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret = 0;
>
> if (mt9m111->powered) {
> @@ -871,7 +874,8 @@ static int mt9m111_resume(struct soc_camera_device *icd)
>
> static int mt9m111_init(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> mt9m111->context = HIGHPOWER;
> @@ -902,10 +906,10 @@ static int mt9m111_release(struct soc_camera_device *icd)
> * Interface active, can use i2c. If it fails, it can indeed mean, that
> * this wasn't our capture interface, so, we wait for the right one
> */
> -static int mt9m111_video_probe(struct soc_camera_device *icd)
> +static int mt9m111_video_probe(struct soc_camera_device *icd,
> + struct i2c_client *client)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> s32 data;
> int ret;
>
> @@ -917,6 +921,11 @@ static int mt9m111_video_probe(struct soc_camera_device *icd)
> to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
> return -ENODEV;
>
> + /* Switch master clock on */
> + ret = soc_camera_video_start(icd, &client->dev);
> + if (ret)
> + return ret;
> +
> ret = mt9m111_enable(icd);
> if (ret)
> goto ei2c;
> @@ -945,40 +954,42 @@ static int mt9m111_video_probe(struct soc_camera_device *icd)
>
> dev_info(&icd->dev, "Detected a MT9M11x chip ID %x\n", data);
>
> - ret = soc_camera_video_start(icd);
> - if (ret)
> - goto eisis;
> -
> mt9m111->autoexposure = 1;
> mt9m111->autowhitebalance = 1;
>
> mt9m111->swap_rgb_even_odd = 1;
> mt9m111->swap_rgb_red_blue = 1;
>
> - return 0;
> -eisis:
> ei2c:
> + soc_camera_video_stop(icd);
> +
> return ret;
> }
>
> static void mt9m111_video_remove(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m111->client->addr,
> - mt9m111->icd.dev.parent, mt9m111->icd.vdev);
> - soc_camera_video_stop(&mt9m111->icd);
> + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
> + icd->dev.parent, icd->vdev);
> + icd->ops = NULL;
> }
>
> static int mt9m111_probe(struct i2c_client *client,
> const struct i2c_device_id *did)
> {
> struct mt9m111 *mt9m111;
> - struct soc_camera_device *icd;
> + struct soc_camera_device *icd = client->dev.platform_data;
> struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct soc_camera_link *icl;
> int ret;
>
> + if (!icd) {
> + dev_err(&client->dev, "MT9M11x: missing soc-camera data!\n");
> + return -EINVAL;
> + }
> +
> + icl = to_soc_camera_link(icd);
> if (!icl) {
> dev_err(&client->dev, "MT9M11x driver needs platform data\n");
> return -EINVAL;
> @@ -994,13 +1005,10 @@ static int mt9m111_probe(struct i2c_client *client,
> if (!mt9m111)
> return -ENOMEM;
>
> - mt9m111->client = client;
> i2c_set_clientdata(client, mt9m111);
>
> /* Second stage probe - when a capture adapter is there */
> - icd = &mt9m111->icd;
> icd->ops = &mt9m111_ops;
> - icd->control = &client->dev;
> icd->x_min = MT9M111_MIN_DARK_COLS;
> icd->y_min = MT9M111_MIN_DARK_ROWS;
> icd->x_current = icd->x_min;
> @@ -1010,22 +1018,24 @@ static int mt9m111_probe(struct i2c_client *client,
> icd->height_min = MT9M111_MIN_DARK_COLS;
> icd->height_max = MT9M111_MAX_HEIGHT;
> icd->y_skip_top = 0;
> - icd->iface = icl->bus_id;
>
> - ret = soc_camera_device_register(icd);
> - if (ret)
> - goto eisdr;
> - return 0;
> + ret = mt9m111_video_probe(icd, client);
> + if (ret) {
> + i2c_set_clientdata(client, NULL);
> + kfree(mt9m111);
> + }
>
> -eisdr:
> - kfree(mt9m111);
> return ret;
> }
>
> static int mt9m111_remove(struct i2c_client *client)
> {
> struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> - soc_camera_device_unregister(&mt9m111->icd);
> + struct soc_camera_device *icd = client->dev.platform_data;
> +
> + mt9m111_video_remove(icd);
> + i2c_set_clientdata(client, NULL);
> + client->driver = NULL;
> kfree(mt9m111);
>
> return 0;
> diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
> index f72aeb7..da09906 100644
> --- a/drivers/media/video/mt9t031.c
> +++ b/drivers/media/video/mt9t031.c
> @@ -68,8 +68,6 @@ static const struct soc_camera_data_format mt9t031_colour_formats[] = {
> };
>
> struct mt9t031 {
> - struct i2c_client *client;
> - struct soc_camera_device icd;
> int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */
> unsigned char autoexposure;
> u16 xskip;
> @@ -138,8 +136,8 @@ static int get_shutter(struct i2c_client *client, u32 *data)
>
> static int mt9t031_init(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> int ret;
>
> if (icl->power) {
> @@ -166,8 +164,8 @@ static int mt9t031_init(struct soc_camera_device *icd)
>
> static int mt9t031_release(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
>
> /* Disable the chip */
> reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
> @@ -180,7 +178,7 @@ static int mt9t031_release(struct soc_camera_device *icd)
>
> static int mt9t031_start_capture(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> /* Switch to master "normal" mode */
> if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
> @@ -190,7 +188,7 @@ static int mt9t031_start_capture(struct soc_camera_device *icd)
>
> static int mt9t031_stop_capture(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> /* Stop sensor readout */
> if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
> @@ -201,7 +199,7 @@ static int mt9t031_stop_capture(struct soc_camera_device *icd)
> static int mt9t031_set_bus_param(struct soc_camera_device *icd,
> unsigned long flags)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> /* The caller should have queried our parameters, check anyway */
> if (flags & ~MT9T031_BUS_PARAM)
> @@ -217,8 +215,7 @@ static int mt9t031_set_bus_param(struct soc_camera_device *icd,
>
> static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd)
> {
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> - struct soc_camera_link *icl = mt9t031->client->dev.platform_data;
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
>
> return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM);
> }
> @@ -238,8 +235,8 @@ static void recalculate_limits(struct soc_camera_device *icd,
> static int mt9t031_set_params(struct soc_camera_device *icd,
> struct v4l2_rect *rect, u16 xskip, u16 yskip)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
> int ret;
> u16 xbin, ybin, width, height, left, top;
> const u16 hblank = MT9T031_HORIZONTAL_BLANK,
> @@ -336,7 +333,8 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
> static int mt9t031_set_crop(struct soc_camera_device *icd,
> struct v4l2_rect *rect)
> {
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
>
> /* CROP - no change in scaling, or in limits */
> return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip);
> @@ -345,7 +343,8 @@ static int mt9t031_set_crop(struct soc_camera_device *icd,
> static int mt9t031_set_fmt(struct soc_camera_device *icd,
> struct v4l2_format *f)
> {
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
> int ret;
> u16 xskip, yskip;
> struct v4l2_rect rect = {
> @@ -403,12 +402,13 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd,
> static int mt9t031_get_chip_id(struct soc_camera_device *icd,
> struct v4l2_dbg_chip_ident *id)
> {
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
>
> if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
> return -EINVAL;
>
> - if (id->match.addr != mt9t031->client->addr)
> + if (id->match.addr != client->addr)
> return -ENODEV;
>
> id->ident = mt9t031->model;
> @@ -421,7 +421,7 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd,
> static int mt9t031_get_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
> return -EINVAL;
> @@ -440,7 +440,7 @@ static int mt9t031_get_register(struct soc_camera_device *icd,
> static int mt9t031_set_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
> return -EINVAL;
> @@ -501,15 +501,11 @@ static const struct v4l2_queryctrl mt9t031_controls[] = {
> }
> };
>
> -static int mt9t031_video_probe(struct soc_camera_device *);
> -static void mt9t031_video_remove(struct soc_camera_device *);
> static int mt9t031_get_control(struct soc_camera_device *, struct v4l2_control *);
> static int mt9t031_set_control(struct soc_camera_device *, struct v4l2_control *);
>
> static struct soc_camera_ops mt9t031_ops = {
> .owner = THIS_MODULE,
> - .probe = mt9t031_video_probe,
> - .remove = mt9t031_video_remove,
> .init = mt9t031_init,
> .release = mt9t031_release,
> .start_capture = mt9t031_start_capture,
> @@ -532,8 +528,8 @@ static struct soc_camera_ops mt9t031_ops = {
>
> static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
> int data;
>
> switch (ctrl->id) {
> @@ -558,8 +554,8 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro
>
> static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
> const struct v4l2_queryctrl *qctrl;
> int data;
>
> @@ -665,10 +661,10 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
>
> /* Interface active, can use i2c. If it fails, it can indeed mean, that
> * this wasn't our capture interface, so, we wait for the right one */
> -static int mt9t031_video_probe(struct soc_camera_device *icd)
> +static int mt9t031_video_probe(struct soc_camera_device *icd,
> + struct i2c_client *client)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
> s32 data;
> int ret;
>
> @@ -678,6 +674,11 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
> to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
> return -ENODEV;
>
> + /* Switch master clock on */
> + ret = soc_camera_video_start(icd, &client->dev);
> + if (ret)
> + return ret;
> +
> /* Enable the chip */
> data = reg_write(client, MT9T031_CHIP_ENABLE, 1);
> dev_dbg(&icd->dev, "write: %d\n", data);
> @@ -685,6 +686,8 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
> /* Read out the chip version register */
> data = reg_read(client, MT9T031_CHIP_VERSION);
>
> + soc_camera_video_stop(icd);
> +
> switch (data) {
> case 0x1621:
> mt9t031->model = V4L2_IDENT_MT9T031;
> @@ -692,44 +695,40 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
> icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats);
> break;
> default:
> - ret = -ENODEV;
> dev_err(&icd->dev,
> "No MT9T031 chip detected, register read %x\n", data);
> - goto ei2c;
> + return -ENODEV;
> }
>
> dev_info(&icd->dev, "Detected a MT9T031 chip ID %x\n", data);
>
> - /* Now that we know the model, we can start video */
> - ret = soc_camera_video_start(icd);
> - if (ret)
> - goto evstart;
> -
> return 0;
> -
> -evstart:
> -ei2c:
> - return ret;
> }
>
> static void mt9t031_video_remove(struct soc_camera_device *icd)
> {
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9t031->client->addr,
> + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
> icd->dev.parent, icd->vdev);
> - soc_camera_video_stop(icd);
> + icd->ops = NULL;
> }
>
> static int mt9t031_probe(struct i2c_client *client,
> const struct i2c_device_id *did)
> {
> struct mt9t031 *mt9t031;
> - struct soc_camera_device *icd;
> + struct soc_camera_device *icd = client->dev.platform_data;
> struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct soc_camera_link *icl;
> int ret;
>
> + if (!icd) {
> + dev_err(&client->dev, "MT9T031: missing soc-camera data!\n");
> + return -EINVAL;
> + }
> +
> + icl = to_soc_camera_link(icd);
> if (!icl) {
> dev_err(&client->dev, "MT9T031 driver needs platform data\n");
> return -EINVAL;
> @@ -745,13 +744,10 @@ static int mt9t031_probe(struct i2c_client *client,
> if (!mt9t031)
> return -ENOMEM;
>
> - mt9t031->client = client;
> i2c_set_clientdata(client, mt9t031);
>
> /* Second stage probe - when a capture adapter is there */
> - icd = &mt9t031->icd;
> icd->ops = &mt9t031_ops;
> - icd->control = &client->dev;
> icd->x_min = MT9T031_COLUMN_SKIP;
> icd->y_min = MT9T031_ROW_SKIP;
> icd->x_current = icd->x_min;
> @@ -761,7 +757,6 @@ static int mt9t031_probe(struct i2c_client *client,
> icd->height_min = MT9T031_MIN_HEIGHT;
> icd->height_max = MT9T031_MAX_HEIGHT;
> icd->y_skip_top = 0;
> - icd->iface = icl->bus_id;
> /* Simulated autoexposure. If enabled, we calculate shutter width
> * ourselves in the driver based on vertical blanking and frame width */
> mt9t031->autoexposure = 1;
> @@ -769,24 +764,24 @@ static int mt9t031_probe(struct i2c_client *client,
> mt9t031->xskip = 1;
> mt9t031->yskip = 1;
>
> - ret = soc_camera_device_register(icd);
> - if (ret)
> - goto eisdr;
> -
> - return 0;
> + ret = mt9t031_video_probe(icd, client);
> + if (ret) {
> + icd->ops = NULL;
> + i2c_set_clientdata(client, NULL);
> + kfree(mt9t031);
> + }
>
> -eisdr:
> - i2c_set_clientdata(client, NULL);
> - kfree(mt9t031);
> return ret;
> }
>
> static int mt9t031_remove(struct i2c_client *client)
> {
> struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
> + struct soc_camera_device *icd = client->dev.platform_data;
>
> - soc_camera_device_unregister(&mt9t031->icd);
> + mt9t031_video_remove(icd);
> i2c_set_clientdata(client, NULL);
> + client->driver = NULL;
> kfree(mt9t031);
>
> return 0;
> diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
> index be20d31..1683af1 100644
> --- a/drivers/media/video/mt9v022.c
> +++ b/drivers/media/video/mt9v022.c
> @@ -85,8 +85,6 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = {
> };
>
> struct mt9v022 {
> - struct i2c_client *client;
> - struct soc_camera_device icd;
> int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
> u16 chip_control;
> };
> @@ -127,9 +125,9 @@ static int reg_clear(struct i2c_client *client, const u8 reg,
>
> static int mt9v022_init(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> + struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> int ret;
>
> if (icl->power) {
> @@ -173,19 +171,19 @@ static int mt9v022_init(struct soc_camera_device *icd)
>
> static int mt9v022_release(struct soc_camera_device *icd)
> {
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> - struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
>
> if (icl->power)
> - icl->power(&mt9v022->client->dev, 0);
> + icl->power(&client->dev, 0);
>
> return 0;
> }
>
> static int mt9v022_start_capture(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> /* Switch to master "normal" mode */
> mt9v022->chip_control &= ~0x10;
> if (reg_write(client, MT9V022_CHIP_CONTROL,
> @@ -196,8 +194,8 @@ static int mt9v022_start_capture(struct soc_camera_device *icd)
>
> static int mt9v022_stop_capture(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> /* Switch to snapshot mode */
> mt9v022->chip_control |= 0x10;
> if (reg_write(client, MT9V022_CHIP_CONTROL,
> @@ -209,9 +207,9 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd)
> static int mt9v022_set_bus_param(struct soc_camera_device *icd,
> unsigned long flags)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
> int ret;
> u16 pixclk = 0;
> @@ -263,8 +261,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd,
>
> static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
> {
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> - struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> unsigned int width_flag;
>
> if (icl->query_bus_param)
> @@ -283,7 +280,7 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
> static int mt9v022_set_crop(struct soc_camera_device *icd,
> struct v4l2_rect *rect)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> int ret;
>
> /* Like in example app. Contradicts the datasheet though */
> @@ -326,7 +323,8 @@ static int mt9v022_set_crop(struct soc_camera_device *icd,
> static int mt9v022_set_fmt(struct soc_camera_device *icd,
> struct v4l2_format *f)
> {
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> struct v4l2_pix_format *pix = &f->fmt.pix;
> struct v4l2_rect rect = {
> .left = icd->x_current,
> @@ -380,12 +378,13 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd,
> static int mt9v022_get_chip_id(struct soc_camera_device *icd,
> struct v4l2_dbg_chip_ident *id)
> {
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
>
> if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
> return -EINVAL;
>
> - if (id->match.addr != mt9v022->client->addr)
> + if (id->match.addr != client->addr)
> return -ENODEV;
>
> id->ident = mt9v022->model;
> @@ -398,7 +397,7 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd,
> static int mt9v022_get_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
> return -EINVAL;
> @@ -418,7 +417,7 @@ static int mt9v022_get_register(struct soc_camera_device *icd,
> static int mt9v022_set_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
> return -EINVAL;
> @@ -487,15 +486,11 @@ static const struct v4l2_queryctrl mt9v022_controls[] = {
> }
> };
>
> -static int mt9v022_video_probe(struct soc_camera_device *);
> -static void mt9v022_video_remove(struct soc_camera_device *);
> static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *);
> static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *);
>
> static struct soc_camera_ops mt9v022_ops = {
> .owner = THIS_MODULE,
> - .probe = mt9v022_video_probe,
> - .remove = mt9v022_video_remove,
> .init = mt9v022_init,
> .release = mt9v022_release,
> .start_capture = mt9v022_start_capture,
> @@ -519,7 +514,7 @@ static struct soc_camera_ops mt9v022_ops = {
> static int mt9v022_get_control(struct soc_camera_device *icd,
> struct v4l2_control *ctrl)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> int data;
>
> switch (ctrl->id) {
> @@ -555,7 +550,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
> struct v4l2_control *ctrl)
> {
> int data;
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> const struct v4l2_queryctrl *qctrl;
>
> qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
> @@ -652,11 +647,11 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
>
> /* Interface active, can use i2c. If it fails, it can indeed mean, that
> * this wasn't our capture interface, so, we wait for the right one */
> -static int mt9v022_video_probe(struct soc_camera_device *icd)
> +static int mt9v022_video_probe(struct soc_camera_device *icd,
> + struct i2c_client *client)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> s32 data;
> int ret;
> unsigned long flags;
> @@ -665,6 +660,11 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
> to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
> return -ENODEV;
>
> + /* Switch master clock on */
> + ret = soc_camera_video_start(icd, &client->dev);
> + if (ret)
> + return ret;
> +
> /* Read out the chip version register */
> data = reg_read(client, MT9V022_CHIP_VERSION);
>
> @@ -684,6 +684,8 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
> udelay(200);
> if (reg_read(client, MT9V022_RESET)) {
> dev_err(&icd->dev, "Resetting MT9V022 failed!\n");
> + if (ret > 0)
> + ret = -EIO;
> goto ei2c;
> }
>
> @@ -700,7 +702,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
> }
>
> if (ret < 0)
> - goto eisis;
> + goto ei2c;
>
> icd->num_formats = 0;
>
> @@ -722,29 +724,24 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
> if (flags & SOCAM_DATAWIDTH_8)
> icd->num_formats++;
>
> - ret = soc_camera_video_start(icd);
> - if (ret < 0)
> - goto eisis;
> -
> dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n",
> data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ?
> "monochrome" : "colour");
>
> - return 0;
> -
> -eisis:
> ei2c:
> + soc_camera_video_stop(icd);
> +
> return ret;
> }
>
> static void mt9v022_video_remove(struct soc_camera_device *icd)
> {
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> - struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
>
> - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr,
> + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
> icd->dev.parent, icd->vdev);
> - soc_camera_video_stop(icd);
> + icd->ops = NULL;
> if (icl->free_bus)
> icl->free_bus(icl);
> }
> @@ -753,11 +750,17 @@ static int mt9v022_probe(struct i2c_client *client,
> const struct i2c_device_id *did)
> {
> struct mt9v022 *mt9v022;
> - struct soc_camera_device *icd;
> + struct soc_camera_device *icd = client->dev.platform_data;
> struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct soc_camera_link *icl;
> int ret;
>
> + if (!icd) {
> + dev_err(&client->dev, "MT9V022: missing soc-camera data!\n");
> + return -EINVAL;
> + }
> +
> + icl = to_soc_camera_link(icd);
> if (!icl) {
> dev_err(&client->dev, "MT9V022 driver needs platform data\n");
> return -EINVAL;
> @@ -774,12 +777,9 @@ static int mt9v022_probe(struct i2c_client *client,
> return -ENOMEM;
>
> mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
> - mt9v022->client = client;
> i2c_set_clientdata(client, mt9v022);
>
> - icd = &mt9v022->icd;
> icd->ops = &mt9v022_ops;
> - icd->control = &client->dev;
> icd->x_min = 1;
> icd->y_min = 4;
> icd->x_current = 1;
> @@ -789,24 +789,24 @@ static int mt9v022_probe(struct i2c_client *client,
> icd->height_min = 32;
> icd->height_max = 480;
> icd->y_skip_top = 1;
> - icd->iface = icl->bus_id;
> -
> - ret = soc_camera_device_register(icd);
> - if (ret)
> - goto eisdr;
>
> - return 0;
> + ret = mt9v022_video_probe(icd, client);
> + if (ret) {
> + i2c_set_clientdata(client, NULL);
> + kfree(mt9v022);
> + }
>
> -eisdr:
> - kfree(mt9v022);
> return ret;
> }
>
> static int mt9v022_remove(struct i2c_client *client)
> {
> struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> + struct soc_camera_device *icd = client->dev.platform_data;
>
> - soc_camera_device_unregister(&mt9v022->icd);
> + mt9v022_video_remove(icd);
> + i2c_set_clientdata(client, NULL);
> + client->driver = NULL;
> kfree(mt9v022);
>
> return 0;
> diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
> index cb13faa..ed752c5 100644
> --- a/drivers/media/video/mx3_camera.c
> +++ b/drivers/media/video/mx3_camera.c
> @@ -502,18 +502,19 @@ static int mx3_camera_add_device(struct soc_camera_device *icd)
>
> mx3_camera_activate(mx3_cam, icd);
> ret = icd->ops->init(icd);
> - if (ret < 0) {
> - clk_disable(mx3_cam->clk);
> + if (ret < 0)
> goto einit;
> - }
>
> mx3_cam->icd = icd;
>
> + dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n",
> + icd->devnum);
> +
> + return 0;
> +
> einit:
> + clk_disable(mx3_cam->clk);
> ebusy:
> - if (!ret)
> - dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n",
> - icd->devnum);
>
> return ret;
> }
> @@ -946,9 +947,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
> camera_flags = icd->ops->query_bus_param(icd);
>
> common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
> + dev_dbg(ici->dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n",
> + camera_flags, bus_flags, common_flags);
> if (!common_flags) {
> - dev_dbg(ici->dev, "no common flags: camera %lx, host %lx\n",
> - camera_flags, bus_flags);
> + dev_dbg(ici->dev, "no common flags");
> return -EINVAL;
> }
>
> @@ -1001,8 +1003,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
> SOCAM_DATAWIDTH_4;
>
> ret = icd->ops->set_bus_param(icd, common_flags);
> - if (ret < 0)
> + if (ret < 0) {
> + dev_dbg(ici->dev, "camera set_bus_param(%lx) returned %d\n",
> + common_flags, ret);
> return ret;
> + }
>
> /*
> * So far only gated clock mode is supported. Add a line
> @@ -1130,8 +1135,9 @@ static int mx3_camera_probe(struct platform_device *pdev)
> INIT_LIST_HEAD(&mx3_cam->capture);
> spin_lock_init(&mx3_cam->lock);
>
> - base = ioremap(res->start, res->end - res->start + 1);
> + base = ioremap(res->start, resource_size(res));
> if (!base) {
> + pr_err("Couldn't map %x@%x\n", resource_size(res), res->start);
> err = -ENOMEM;
> goto eioremap;
> }
> @@ -1218,3 +1224,4 @@ module_exit(mx3_camera_exit);
> MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver");
> MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
> MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:" MX3_CAM_DRV_NAME);
> diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
> index c0d9112..48f4d64 100644
> --- a/drivers/media/video/ov772x.c
> +++ b/drivers/media/video/ov772x.c
> @@ -399,8 +399,6 @@ struct ov772x_win_size {
>
> struct ov772x_priv {
> struct ov772x_camera_info *info;
> - struct i2c_client *client;
> - struct soc_camera_device icd;
> const struct ov772x_color_format *fmt;
> const struct ov772x_win_size *win;
> int model;
> @@ -619,53 +617,56 @@ static int ov772x_reset(struct i2c_client *client)
>
> static int ov772x_init(struct soc_camera_device *icd)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = dev_get_drvdata(&icd->dev);
> int ret = 0;
>
> - if (priv->info->link.power) {
> - ret = priv->info->link.power(&priv->client->dev, 1);
> + if (icl->power) {
> + ret = icl->power(&client->dev, 1);
> if (ret < 0)
> return ret;
> }
>
> - if (priv->info->link.reset)
> - ret = priv->info->link.reset(&priv->client->dev);
> + if (icl->reset)
> + ret = icl->reset(&client->dev);
>
> return ret;
> }
>
> static int ov772x_release(struct soc_camera_device *icd)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = dev_get_drvdata(&icd->dev);
> int ret = 0;
>
> - if (priv->info->link.power)
> - ret = priv->info->link.power(&priv->client->dev, 0);
> + if (icl->power)
> + ret = icl->power(&client->dev, 0);
>
> return ret;
> }
>
> static int ov772x_start_capture(struct soc_camera_device *icd)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
>
> if (!priv->win || !priv->fmt) {
> dev_err(&icd->dev, "norm or win select error\n");
> return -EPERM;
> }
>
> - ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0);
> + ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0);
>
> dev_dbg(&icd->dev,
> - "format %s, win %s\n", priv->fmt->name, priv->win->name);
> + "format %s, win %s\n", priv->fmt->name, priv->win->name);
>
> return 0;
> }
>
> static int ov772x_stop_capture(struct soc_camera_device *icd)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> - ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
> return 0;
> }
>
> @@ -677,8 +678,9 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd,
>
> static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> - struct soc_camera_link *icl = &priv->info->link;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
> + struct soc_camera_link *icl = dev_get_drvdata(&icd->dev);
> unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
> SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
> SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
> @@ -689,7 +691,8 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
> static int ov772x_get_control(struct soc_camera_device *icd,
> struct v4l2_control *ctrl)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
>
> switch (ctrl->id) {
> case V4L2_CID_VFLIP:
> @@ -705,7 +708,8 @@ static int ov772x_get_control(struct soc_camera_device *icd,
> static int ov772x_set_control(struct soc_camera_device *icd,
> struct v4l2_control *ctrl)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
> int ret = 0;
> u8 val;
>
> @@ -715,14 +719,14 @@ static int ov772x_set_control(struct soc_camera_device *icd,
> priv->flag_vflip = ctrl->value;
> if (priv->info->flags & OV772X_FLAG_VFLIP)
> val ^= VFLIP_IMG;
> - ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val);
> + ret = ov772x_mask_set(client, COM3, VFLIP_IMG, val);
> break;
> case V4L2_CID_HFLIP:
> val = ctrl->value ? HFLIP_IMG : 0x00;
> priv->flag_hflip = ctrl->value;
> if (priv->info->flags & OV772X_FLAG_HFLIP)
> val ^= HFLIP_IMG;
> - ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val);
> + ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val);
> break;
> }
>
> @@ -730,9 +734,10 @@ static int ov772x_set_control(struct soc_camera_device *icd,
> }
>
> static int ov772x_get_chip_id(struct soc_camera_device *icd,
> - struct v4l2_dbg_chip_ident *id)
> + struct v4l2_dbg_chip_ident *id)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
>
> id->ident = priv->model;
> id->revision = 0;
> @@ -744,14 +749,14 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd,
> static int ov772x_get_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> - int ret;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + int ret;
>
> reg->size = 1;
> if (reg->reg > 0xff)
> return -EINVAL;
>
> - ret = i2c_smbus_read_byte_data(priv->client, reg->reg);
> + ret = i2c_smbus_read_byte_data(client, reg->reg);
> if (ret < 0)
> return ret;
>
> @@ -763,13 +768,13 @@ static int ov772x_get_register(struct soc_camera_device *icd,
> static int ov772x_set_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->reg > 0xff ||
> reg->val > 0xff)
> return -EINVAL;
>
> - return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val);
> + return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
> }
> #endif
>
> @@ -793,9 +798,11 @@ ov772x_select_win(u32 width, u32 height)
> return win;
> }
>
> -static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> - u32 pixfmt)
> +static int ov772x_set_params(struct soc_camera_device *icd,
> + u32 width, u32 height, u32 pixfmt)
> {
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
> int ret = -EINVAL;
> u8 val;
> int i;
> @@ -821,7 +828,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> /*
> * reset hardware
> */
> - ov772x_reset(priv->client);
> + ov772x_reset(client);
>
> /*
> * Edge Ctrl
> @@ -835,17 +842,17 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> * Remove it when manual mode.
> */
>
> - ret = ov772x_mask_set(priv->client, DSPAUTO, EDGE_ACTRL, 0x00);
> + ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00);
> if (ret < 0)
> goto ov772x_set_fmt_error;
>
> - ret = ov772x_mask_set(priv->client,
> + ret = ov772x_mask_set(client,
> EDGE_TRSHLD, EDGE_THRESHOLD_MASK,
> priv->info->edgectrl.threshold);
> if (ret < 0)
> goto ov772x_set_fmt_error;
>
> - ret = ov772x_mask_set(priv->client,
> + ret = ov772x_mask_set(client,
> EDGE_STRNGT, EDGE_STRENGTH_MASK,
> priv->info->edgectrl.strength);
> if (ret < 0)
> @@ -857,13 +864,13 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> *
> * set upper and lower limit
> */
> - ret = ov772x_mask_set(priv->client,
> + ret = ov772x_mask_set(client,
> EDGE_UPPER, EDGE_UPPER_MASK,
> priv->info->edgectrl.upper);
> if (ret < 0)
> goto ov772x_set_fmt_error;
>
> - ret = ov772x_mask_set(priv->client,
> + ret = ov772x_mask_set(client,
> EDGE_LOWER, EDGE_LOWER_MASK,
> priv->info->edgectrl.lower);
> if (ret < 0)
> @@ -873,7 +880,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> /*
> * set size format
> */
> - ret = ov772x_write_array(priv->client, priv->win->regs);
> + ret = ov772x_write_array(client, priv->win->regs);
> if (ret < 0)
> goto ov772x_set_fmt_error;
>
> @@ -882,7 +889,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> */
> val = priv->fmt->dsp3;
> if (val) {
> - ret = ov772x_mask_set(priv->client,
> + ret = ov772x_mask_set(client,
> DSP_CTRL3, UV_MASK, val);
> if (ret < 0)
> goto ov772x_set_fmt_error;
> @@ -901,7 +908,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> if (priv->flag_hflip)
> val ^= HFLIP_IMG;
>
> - ret = ov772x_mask_set(priv->client,
> + ret = ov772x_mask_set(client,
> COM3, SWAP_MASK | IMG_MASK, val);
> if (ret < 0)
> goto ov772x_set_fmt_error;
> @@ -910,7 +917,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> * set COM7
> */
> val = priv->win->com7_bit | priv->fmt->com7;
> - ret = ov772x_mask_set(priv->client,
> + ret = ov772x_mask_set(client,
> COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK),
> val);
> if (ret < 0)
> @@ -920,7 +927,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
>
> ov772x_set_fmt_error:
>
> - ov772x_reset(priv->client);
> + ov772x_reset(client);
> priv->win = NULL;
> priv->fmt = NULL;
>
> @@ -930,22 +937,22 @@ ov772x_set_fmt_error:
> static int ov772x_set_crop(struct soc_camera_device *icd,
> struct v4l2_rect *rect)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
>
> if (!priv->fmt)
> return -EINVAL;
>
> - return ov772x_set_params(priv, rect->width, rect->height,
> + return ov772x_set_params(icd, rect->width, rect->height,
> priv->fmt->fourcc);
> }
>
> static int ov772x_set_fmt(struct soc_camera_device *icd,
> struct v4l2_format *f)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> struct v4l2_pix_format *pix = &f->fmt.pix;
>
> - return ov772x_set_params(priv, pix->width, pix->height,
> + return ov772x_set_params(icd, pix->width, pix->height,
> pix->pixelformat);
> }
>
> @@ -967,11 +974,13 @@ static int ov772x_try_fmt(struct soc_camera_device *icd,
> return 0;
> }
>
> -static int ov772x_video_probe(struct soc_camera_device *icd)
> +static int ov772x_video_probe(struct soc_camera_device *icd,
> + struct i2c_client *client)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
> u8 pid, ver;
> const char *devname;
> + int ret;
>
> /*
> * We must have a parent by now. And it cannot be a wrong one.
> @@ -993,11 +1002,18 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
> icd->formats = ov772x_fmt_lists;
> icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists);
>
> + /* Switch master clock on */
> + ret = soc_camera_video_start(icd, &client->dev);
> + if (ret)
> + return ret;
> +
> /*
> * check and show product ID and manufacturer ID
> */
> - pid = i2c_smbus_read_byte_data(priv->client, PID);
> - ver = i2c_smbus_read_byte_data(priv->client, VER);
> + pid = i2c_smbus_read_byte_data(client, PID);
> + ver = i2c_smbus_read_byte_data(client, VER);
> +
> + soc_camera_video_stop(icd);
>
> switch (VERSION(pid, ver)) {
> case OV7720:
> @@ -1019,21 +1035,19 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
> devname,
> pid,
> ver,
> - i2c_smbus_read_byte_data(priv->client, MIDH),
> - i2c_smbus_read_byte_data(priv->client, MIDL));
> + i2c_smbus_read_byte_data(client, MIDH),
> + i2c_smbus_read_byte_data(client, MIDL));
>
> - return soc_camera_video_start(icd);
> + return 0;
> }
>
> static void ov772x_video_remove(struct soc_camera_device *icd)
> {
> - soc_camera_video_stop(icd);
> + icd->ops = NULL;
> }
>
> static struct soc_camera_ops ov772x_ops = {
> .owner = THIS_MODULE,
> - .probe = ov772x_video_probe,
> - .remove = ov772x_video_remove,
> .init = ov772x_init,
> .release = ov772x_release,
> .start_capture = ov772x_start_capture,
> @@ -1063,13 +1077,21 @@ static int ov772x_probe(struct i2c_client *client,
> {
> struct ov772x_priv *priv;
> struct ov772x_camera_info *info;
> - struct soc_camera_device *icd;
> + struct soc_camera_device *icd = client->dev.platform_data;
> struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> + struct soc_camera_link *icl;
> int ret;
>
> - info = client->dev.platform_data;
> - if (!info)
> + if (!icd) {
> + dev_err(&client->dev, "MT9M001: missing soc-camera data!\n");
> return -EINVAL;
> + }
> +
> + icl = dev_get_drvdata(&icd->dev);
> + if (!icl)
> + return -EINVAL;
> +
> + info = container_of(icl, struct ov772x_camera_info, link);
>
> if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
> dev_err(&adapter->dev,
> @@ -1083,18 +1105,13 @@ static int ov772x_probe(struct i2c_client *client,
> return -ENOMEM;
>
> priv->info = info;
> - priv->client = client;
> i2c_set_clientdata(client, priv);
>
> - icd = &priv->icd;
> icd->ops = &ov772x_ops;
> - icd->control = &client->dev;
> icd->width_max = MAX_WIDTH;
> icd->height_max = MAX_HEIGHT;
> - icd->iface = priv->info->link.bus_id;
> -
> - ret = soc_camera_device_register(icd);
>
> + ret = ov772x_video_probe(icd, client);
> if (ret) {
> i2c_set_clientdata(client, NULL);
> kfree(priv);
> @@ -1106,8 +1123,9 @@ static int ov772x_probe(struct i2c_client *client,
> static int ov772x_remove(struct i2c_client *client)
> {
> struct ov772x_priv *priv = i2c_get_clientdata(client);
> + struct soc_camera_device *icd = client->dev.platform_data;
>
> - soc_camera_device_unregister(&priv->icd);
> + ov772x_video_remove(icd);
> i2c_set_clientdata(client, NULL);
> kfree(priv);
> return 0;
> diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
> index 2da5eef..63964d0 100644
> --- a/drivers/media/video/pxa_camera.c
> +++ b/drivers/media/video/pxa_camera.c
> @@ -841,7 +841,8 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q,
> sizeof(struct pxa_buffer), icd);
> }
>
> -static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
> +static u32 mclk_get_divisor(struct platform_device *pdev,
> + struct pxa_camera_dev *pcdev)
> {
> unsigned long mclk = pcdev->mclk;
> u32 div;
> @@ -853,7 +854,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
> /* mclk <= ciclk / 4 (27.4.2) */
> if (mclk > lcdclk / 4) {
> mclk = lcdclk / 4;
> - dev_warn(pcdev->soc_host.dev, "Limiting master clock to %lu\n", mclk);
> + dev_warn(&pdev->dev, "Limiting master clock to %lu\n", mclk);
> }
>
> /* We verify mclk != 0, so if anyone breaks it, here comes their Oops */
> @@ -863,8 +864,8 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
> if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
> pcdev->mclk = lcdclk / (2 * (div + 1));
>
> - dev_dbg(pcdev->soc_host.dev, "LCD clock %luHz, target freq %luHz, "
> - "divisor %u\n", lcdclk, mclk, div);
> + dev_dbg(&pdev->dev, "LCD clock %luHz, target freq %luHz, divisor %u\n",
> + lcdclk, mclk, div);
>
> return div;
> }
> @@ -969,15 +970,20 @@ static int pxa_camera_add_device(struct soc_camera_device *icd)
> goto ebusy;
> }
>
> - dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
> - icd->devnum);
> -
> pxa_camera_activate(pcdev);
> ret = icd->ops->init(icd);
> + if (ret < 0)
> + goto einit;
> +
> + pcdev->icd = icd;
>
> - if (!ret)
> - pcdev->icd = icd;
> + dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
> + icd->devnum);
>
> + return 0;
> +
> +einit:
> + pxa_camera_deactivate(pcdev);
> ebusy:
> return ret;
> }
> @@ -1599,7 +1605,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
> pcdev->mclk = 20000000;
> }
>
> - pcdev->mclk_divisor = mclk_get_divisor(pcdev);
> + pcdev->mclk_divisor = mclk_get_divisor(pdev, pcdev);
>
> INIT_LIST_HEAD(&pcdev->capture);
> spin_lock_init(&pcdev->lock);
> @@ -1746,3 +1752,4 @@ module_exit(pxa_camera_exit);
> MODULE_DESCRIPTION("PXA27x SoC Camera Host driver");
> MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
> MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:" PXA_CAM_DRV_NAME);
> diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
> index d369e84..ac9b467 100644
> --- a/drivers/media/video/sh_mobile_ceu_camera.c
> +++ b/drivers/media/video/sh_mobile_ceu_camera.c
> @@ -360,11 +360,13 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
> "SuperH Mobile CEU driver attached to camera %d\n",
> icd->devnum);
>
> + clk_enable(pcdev->clk);
> +
> ret = icd->ops->init(icd);
> - if (ret)
> + if (ret) {
> + clk_disable(pcdev->clk);
> goto err;
> -
> - clk_enable(pcdev->clk);
> + }
>
> ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
> while (ceu_read(pcdev, CSTSR) & 1)
> @@ -398,10 +400,10 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
> }
> spin_unlock_irqrestore(&pcdev->lock, flags);
>
> - clk_disable(pcdev->clk);
> -
> icd->ops->release(icd);
>
> + clk_disable(pcdev->clk);
> +
> dev_info(&icd->dev,
> "SuperH Mobile CEU driver detached from camera %d\n",
> icd->devnum);
> @@ -948,3 +950,4 @@ module_exit(sh_mobile_ceu_exit);
> MODULE_DESCRIPTION("SuperH Mobile CEU driver");
> MODULE_AUTHOR("Magnus Damm");
> MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:sh_mobile_ceu");
> diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
> index 03a6c29..d2b765d 100644
> --- a/drivers/media/video/soc_camera.c
> +++ b/drivers/media/video/soc_camera.c
> @@ -16,19 +16,21 @@
> * published by the Free Software Foundation.
> */
>
> -#include <linux/module.h>
> -#include <linux/init.h>
> #include <linux/device.h>
> -#include <linux/list.h>
> #include <linux/err.h>
> +#include <linux/i2c.h>
> +#include <linux/init.h>
> +#include <linux/list.h>
> #include <linux/mutex.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> #include <linux/vmalloc.h>
>
> +#include <media/soc_camera.h>
> #include <media/v4l2-common.h>
> #include <media/v4l2-ioctl.h>
> #include <media/v4l2-dev.h>
> #include <media/videobuf-core.h>
> -#include <media/soc_camera.h>
>
> /* Default to VGA resolution */
> #define DEFAULT_WIDTH 640
> @@ -36,7 +38,7 @@
>
> static LIST_HEAD(hosts);
> static LIST_HEAD(devices);
> -static DEFINE_MUTEX(list_lock);
> +static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */
>
> const struct soc_camera_data_format *soc_camera_format_by_fourcc(
> struct soc_camera_device *icd, unsigned int fourcc)
> @@ -207,6 +209,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv,
> return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK);
> }
>
> +/* Always entered with .video_lock held */
> static int soc_camera_init_user_formats(struct soc_camera_device *icd)
> {
> struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
> @@ -255,9 +258,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd)
> return 0;
> }
>
> +/* Always entered with .video_lock held */
> static void soc_camera_free_user_formats(struct soc_camera_device *icd)
> {
> + icd->current_fmt = NULL;
> vfree(icd->user_formats);
> + icd->user_formats = NULL;
> }
>
> /* Called with .vb_lock held */
> @@ -308,10 +314,6 @@ static int soc_camera_open(struct file *file)
> struct soc_camera_file *icf;
> int ret;
>
> - icf = vmalloc(sizeof(*icf));
> - if (!icf)
> - return -ENOMEM;
> -
> /*
> * It is safe to dereference these pointers now as long as a user has
> * the video device open - we are protected by the held cdev reference.
> @@ -319,8 +321,17 @@ static int soc_camera_open(struct file *file)
>
> vdev = video_devdata(file);
> icd = container_of(vdev->parent, struct soc_camera_device, dev);
> +
> + if (!icd->ops)
> + /* No device driver attached */
> + return -ENODEV;
> +
> ici = to_soc_camera_host(icd->dev.parent);
>
> + icf = vmalloc(sizeof(*icf));
> + if (!icf)
> + return -ENOMEM;
> +
> if (!try_module_get(icd->ops->owner)) {
> dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
> ret = -EINVAL;
> @@ -333,7 +344,7 @@ static int soc_camera_open(struct file *file)
> goto emgi;
> }
>
> - /* Protect against icd->remove() until we module_get() both drivers. */
> + /* Protect against icd->ops->remove() until we module_get() both drivers. */
> mutex_lock(&icd->video_lock);
>
> icf->icd = icd;
> @@ -348,11 +359,16 @@ static int soc_camera_open(struct file *file)
> .width = icd->width,
> .height = icd->height,
> .field = icd->field,
> - .pixelformat = icd->current_fmt->fourcc,
> - .colorspace = icd->current_fmt->colorspace,
> },
> };
>
> + ret = soc_camera_init_user_formats(icd);
> + if (ret < 0)
> + goto eiufmt;
> +
> + f.fmt.pix.pixelformat = icd->current_fmt->fourcc;
> + f.fmt.pix.colorspace = icd->current_fmt->colorspace;
> +
> ret = ici->ops->add(icd);
> if (ret < 0) {
> dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
> @@ -381,6 +397,8 @@ static int soc_camera_open(struct file *file)
> esfmt:
> ici->ops->remove(icd);
> eiciadd:
> + soc_camera_free_user_formats(icd);
> +eiufmt:
> icd->use_count--;
> mutex_unlock(&icd->video_lock);
> module_put(ici->ops->owner);
> @@ -400,8 +418,10 @@ static int soc_camera_close(struct file *file)
>
> mutex_lock(&icd->video_lock);
> icd->use_count--;
> - if (!icd->use_count)
> + if (!icd->use_count) {
> ici->ops->remove(icd);
> + soc_camera_free_user_formats(icd);
> + }
>
> mutex_unlock(&icd->video_lock);
>
> @@ -762,29 +782,6 @@ static int soc_camera_s_register(struct file *file, void *fh,
> }
> #endif
>
> -static int device_register_link(struct soc_camera_device *icd)
> -{
> - int ret = dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum);
> -
> - if (!ret)
> - ret = device_register(&icd->dev);
> -
> - if (ret < 0) {
> - /* Prevent calling device_unregister() */
> - icd->dev.parent = NULL;
> - dev_err(&icd->dev, "Cannot register device: %d\n", ret);
> - /* Even if probe() was unsuccessful for all registered drivers,
> - * device_register() returns 0, and we add the link, just to
> - * document this camera's control device */
> - } else if (icd->control)
> - /* Have to sysfs_remove_link() before device_unregister()? */
> - if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj,
> - "control"))
> - dev_warn(&icd->dev,
> - "Failed creating the control symlink\n");
> - return ret;
> -}
> -
> /* So far this function cannot fail */
> static void scan_add_host(struct soc_camera_host *ici)
> {
> @@ -794,103 +791,70 @@ static void scan_add_host(struct soc_camera_host *ici)
>
> list_for_each_entry(icd, &devices, list) {
> if (icd->iface == ici->nr) {
> + int ret;
> icd->dev.parent = ici->dev;
> - device_register_link(icd);
> - }
> - }
> -
> - mutex_unlock(&list_lock);
> -}
> -
> -/* return: 0 if no match found or a match found and
> - * device_register() successful, error code otherwise */
> -static int scan_add_device(struct soc_camera_device *icd)
> -{
> - struct soc_camera_host *ici;
> - int ret = 0;
> -
> - mutex_lock(&list_lock);
> -
> - list_add_tail(&icd->list, &devices);
> -
> - /* Watch out for class_for_each_device / class_find_device API by
> - * Dave Young <hidave.darkstar@gmail.com> */
> - list_for_each_entry(ici, &hosts, list) {
> - if (icd->iface == ici->nr) {
> - ret = 1;
> - icd->dev.parent = ici->dev;
> - break;
> + dev_set_name(&icd->dev, "%u-%u", icd->iface,
> + icd->devnum);
> + ret = device_register(&icd->dev);
> + if (ret < 0) {
> + icd->dev.parent = NULL;
> + dev_err(&icd->dev,
> + "Cannot register device: %d\n", ret);
> + }
> }
> }
>
> mutex_unlock(&list_lock);
> -
> - if (ret)
> - ret = device_register_link(icd);
> -
> - return ret;
> }
>
> +static int video_dev_create(struct soc_camera_device *icd);
> +/* Called during host-driver probe */
> static int soc_camera_probe(struct device *dev)
> {
> struct soc_camera_device *icd = to_soc_camera_dev(dev);
> - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> int ret;
> + struct i2c_client *client;
> + struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id);
>
> - /*
> - * Possible race scenario:
> - * modprobe <camera-host-driver> triggers __func__
> - * at this moment respective <camera-sensor-driver> gets rmmod'ed
> - * to protect take module references.
> - */
> -
> - if (!try_module_get(icd->ops->owner)) {
> - dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
> - ret = -EINVAL;
> - goto emgd;
> - }
> -
> - if (!try_module_get(ici->ops->owner)) {
> - dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
> - ret = -EINVAL;
> - goto emgi;
> + if (!adap) {
> + ret = -ENODEV;
> + dev_err(dev, "Cannot get I2C adapter %d\n", icl->i2c_adapter_id);
> + goto ei2cga;
> }
>
> - mutex_lock(&icd->video_lock);
> + dev_info(dev, "Probing %s\n", dev_name(dev));
>
> - /* We only call ->add() here to activate and probe the camera.
> - * We shall ->remove() and deactivate it immediately afterwards. */
> - ret = ici->ops->add(icd);
> - if (ret < 0)
> - goto eiadd;
> + client = i2c_new_device(adap, icl->board_info);
> + if (!client) {
> + ret = -ENOMEM;
> + goto ei2cnd;
> + }
>
> - ret = icd->ops->probe(icd);
> - if (ret >= 0) {
> - const struct v4l2_queryctrl *qctrl;
> + /*
> + * We set icd drvdata at two locations - here and in
> + * soc_camera_video_start(). Depending on the module loading /
> + * initialisation order one of these locations will be entered first
> + */
> + /* Use to_i2c_client(dev) to recover the i2c client */
> + dev_set_drvdata(&icd->dev, &client->dev);
>
> - qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
> - icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
> - qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
> - icd->exposure = qctrl ? qctrl->default_value :
> - (unsigned short)~0;
> + /* Do we have to sysfs_remove_link() before device_unregister()? */
> + if (sysfs_create_link(&dev->kobj, &to_soc_camera_control(icd)->kobj,
> + "control"))
> + dev_warn(dev, "Failed creating the control symlink\n");
>
> - ret = soc_camera_init_user_formats(icd);
> - if (ret < 0)
> - goto eiufmt;
> + ret = video_dev_create(icd);
> + if (ret < 0)
> + goto evdc;
>
> - icd->height = DEFAULT_HEIGHT;
> - icd->width = DEFAULT_WIDTH;
> - icd->field = V4L2_FIELD_ANY;
> - }
> + return 0;
>
> -eiufmt:
> - ici->ops->remove(icd);
> -eiadd:
> - mutex_unlock(&icd->video_lock);
> - module_put(ici->ops->owner);
> -emgi:
> - module_put(icd->ops->owner);
> -emgd:
> +evdc:
> + i2c_unregister_device(client);
> +ei2cnd:
> + i2c_put_adapter(adap);
> +ei2cga:
> return ret;
> }
>
> @@ -899,11 +863,23 @@ emgd:
> static int soc_camera_remove(struct device *dev)
> {
> struct soc_camera_device *icd = to_soc_camera_dev(dev);
> + struct video_device *vdev = icd->vdev;
>
> - if (icd->ops->remove)
> - icd->ops->remove(icd);
> + BUG_ON(!dev->parent);
>
> - soc_camera_free_user_formats(icd);
> + if (vdev) {
> + mutex_lock(&icd->video_lock);
> + video_unregister_device(vdev);
> + icd->vdev = NULL;
> + mutex_unlock(&icd->video_lock);
> + }
> +
> + if (to_soc_camera_control(icd)) {
> + struct i2c_client *client =
> + to_i2c_client(to_soc_camera_control(icd));
> + i2c_unregister_device(client);
> + i2c_put_adapter(client->adapter);
> + }
>
> return 0;
> }
> @@ -998,10 +974,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
>
> list_for_each_entry(icd, &devices, list) {
> if (icd->dev.parent == ici->dev) {
> + /* The bus->remove will be called */
> device_unregister(&icd->dev);
> /* Not before device_unregister(), .remove
> * needs parent to call ici->ops->remove() */
> icd->dev.parent = NULL;
> +
> + /* If the host module is loaded again, device_register()
> + * would complain "already initialised" */
> memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj));
> }
> }
> @@ -1013,26 +993,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
> EXPORT_SYMBOL(soc_camera_host_unregister);
>
> /* Image capture device */
> -int soc_camera_device_register(struct soc_camera_device *icd)
> +static int soc_camera_device_register(struct soc_camera_device *icd)
> {
> struct soc_camera_device *ix;
> int num = -1, i;
>
> - if (!icd || !icd->ops ||
> - !icd->ops->probe ||
> - !icd->ops->init ||
> - !icd->ops->release ||
> - !icd->ops->start_capture ||
> - !icd->ops->stop_capture ||
> - !icd->ops->set_crop ||
> - !icd->ops->set_fmt ||
> - !icd->ops->try_fmt ||
> - !icd->ops->query_bus_param ||
> - !icd->ops->set_bus_param)
> - return -EINVAL;
> -
> for (i = 0; i < 256 && num < 0; i++) {
> num = i;
> + /* Check if this index is available on this interface */
> list_for_each_entry(ix, &devices, list) {
> if (ix->iface == icd->iface && ix->devnum == i) {
> num = -1;
> @@ -1054,21 +1022,15 @@ int soc_camera_device_register(struct soc_camera_device *icd)
> icd->host_priv = NULL;
> mutex_init(&icd->video_lock);
>
> - return scan_add_device(icd);
> + list_add_tail(&icd->list, &devices);
> +
> + return 0;
> }
> -EXPORT_SYMBOL(soc_camera_device_register);
>
> -void soc_camera_device_unregister(struct soc_camera_device *icd)
> +static void soc_camera_device_unregister(struct soc_camera_device *icd)
> {
> - mutex_lock(&list_lock);
> list_del(&icd->list);
> -
> - /* The bus->remove will be eventually called */
> - if (icd->dev.parent)
> - device_unregister(&icd->dev);
> - mutex_unlock(&list_lock);
> }
> -EXPORT_SYMBOL(soc_camera_device_unregister);
>
> static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
> .vidioc_querycap = soc_camera_querycap,
> @@ -1099,22 +1061,14 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
> #endif
> };
>
> -/*
> - * Usually called from the struct soc_camera_ops .probe() method, i.e., from
> - * soc_camera_probe() above with .video_lock held
> - */
> -int soc_camera_video_start(struct soc_camera_device *icd)
> +static int video_dev_create(struct soc_camera_device *icd)
> {
> struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
> - int err = -ENOMEM;
> - struct video_device *vdev;
> -
> - if (!icd->dev.parent)
> - return -ENODEV;
> + int ret;
> + struct video_device *vdev = video_device_alloc();
>
> - vdev = video_device_alloc();
> if (!vdev)
> - goto evidallocd;
> + return -ENOMEM;
> dev_dbg(ici->dev, "Allocated video_device %p\n", vdev);
>
> strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
> @@ -1125,10 +1079,10 @@ int soc_camera_video_start(struct soc_camera_device *icd)
> vdev->ioctl_ops = &soc_camera_ioctl_ops;
> vdev->release = video_device_release;
> vdev->minor = -1;
> - vdev->tvnorms = V4L2_STD_UNKNOWN,
> + vdev->tvnorms = V4L2_STD_UNKNOWN;
>
> - err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
> - if (err < 0) {
> + ret = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
> + if (ret < 0) {
> dev_err(vdev->parent, "video_register_device failed\n");
> goto evidregd;
> }
> @@ -1138,27 +1092,99 @@ int soc_camera_video_start(struct soc_camera_device *icd)
>
> evidregd:
> video_device_release(vdev);
> -evidallocd:
> - return err;
> + return ret;
> +}
> +
> +/*
> + * Usually called from the struct soc_camera_ops .probe() method, i.e., from
> + * soc_camera_probe() above with .video_lock held
> + */
> +int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev)
> +{
> + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
> + const struct v4l2_queryctrl *qctrl;
> +
> + if (!icd->dev.parent)
> + return -ENODEV;
> +
> + if (!icd->ops ||
> + !icd->ops->init ||
> + !icd->ops->release ||
> + !icd->ops->start_capture ||
> + !icd->ops->stop_capture ||
> + !icd->ops->set_fmt ||
> + !icd->ops->try_fmt ||
> + !icd->ops->query_bus_param ||
> + !icd->ops->set_bus_param)
> + return -EINVAL;
> +
> + /* See comment in soc_camera_probe() */
> + dev_set_drvdata(&icd->dev, dev);
> +
> + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
> + icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
> + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
> + icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0;
> +
> + return ici->ops->add(icd);
> }
> EXPORT_SYMBOL(soc_camera_video_start);
>
> void soc_camera_video_stop(struct soc_camera_device *icd)
> {
> - struct video_device *vdev = icd->vdev;
> + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
>
> dev_dbg(&icd->dev, "%s\n", __func__);
>
> - if (!icd->dev.parent || !vdev)
> - return;
> -
> - mutex_lock(&icd->video_lock);
> - video_unregister_device(vdev);
> - icd->vdev = NULL;
> - mutex_unlock(&icd->video_lock);
> + ici->ops->remove(icd);
> }
> EXPORT_SYMBOL(soc_camera_video_stop);
>
> +static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
> +{
> + struct soc_camera_link *icl = pdev->dev.platform_data;
> + struct soc_camera_device *icd;
> +
> + if (!icl)
> + return -EINVAL;
> +
> + icd = kzalloc(sizeof(*icd), GFP_KERNEL);
> + if (!icd)
> + return -ENOMEM;
> +
> + icd->iface = icl->bus_id;
> + icl->board_info->platform_data = icd;
> + platform_set_drvdata(pdev, icd);
> + icd->dev.platform_data = icl;
> +
> + return soc_camera_device_register(icd);
> +}
> +
> +/* Only called on rmmod for each platform device, since they are not
> + * hot-plugg...
>
> [Message clipped]
--
========================================================
DongSoo, Nathaniel Kim
Engineer
Mobile S/W Platform Lab.
Digital Media & Communications R&D Centre
Samsung Electronics CO., LTD.
e-mail : dongsoo.kim@gmail.com
dongsoo45.kim@samsung.com
========================================================
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [PATCH 5/5] soc-camera: Convert to a platform driver
2009-04-16 2:19 ` Dongsoo, Nathaniel Kim
@ 2009-04-16 8:58 ` Guennadi Liakhovetski
2009-04-16 10:00 ` Dongsoo, Nathaniel Kim
0 siblings, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-16 8:58 UTC (permalink / raw)
To: Dongsoo, Nathaniel Kim; +Cc: Linux Media Mailing List, Robert Jarzmik
On Thu, 16 Apr 2009, Dongsoo, Nathaniel Kim wrote:
> Hello Guennadi,
>
>
> Reviewing your patch, I've got curious about a thing.
> I think your soc camera subsystem is covering multiple camera
> devices(sensors) in one target board, but if that is true I'm afraid
> I'm confused how to handle them properly.
> Because according to your patch, video_dev_create() takes camera
> device as parameter and it seems to be creating device node for each
> camera devices.
This patch is a preparatory step for the v4l2-(sub)dev conversion. With it
yes (I think) a video device will be created for every registered on the
platform level camera, but only the one(s) that probed successfully will
actually work, others will return -ENODEV on open().
> It means, if I have one camera host and several camera devices, there
> should be several device nodes for camera devices but cannot be used
> at the same time. Because typical camera host(camera interface) can
> handle only one camera device at a time. But multiple device nodes
> mean "we can open and handle them at the same time".
>
> How about registering camera host device as v4l2 device and make
> camera device a input device which could be handled using
> VIDIOC_S_INPUT/G_INPUT api?
There are also cases, when you have several cameras simultaneously (think
for example about stereo vision), even though we don't have any such cases
just yet.
> Actually, I'm working on S3C64xx camera interface driver with soc
> camera subsystem,
Looking forward to it!:-)
> and I'm facing that issue right now because I've got
> dual camera on my target board.
Good, I think, there also has been a similar design based on a pxa270 SoC.
How are cameras switched in your case? You probably have some additional
hardware logic to switch between them, right? So, you need some code to
control that. I think, you should even be able to do this automatically in
your platform code using power hooks from the struct soc_camera_link. You
could fail to power on a camera if another camera is currently active. In
fact, I have to add a return code test to the call to icl->power(icl, 1)
in soc_camera_open(), I'll do this for the final v4l2-dev version. Would
this work for you or do you have another requirements? In which case, can
you describe your use-case in more detail - should both cameras be open by
applications simultaneously (looks like not), do you need a more explicit
switching control, than just "first open switches," which shouldn't be the
case, since you can even create a separate task, that does nothing but
just keeps the required camera device open.
> I hope you to consider this concept, and also want to know your opinion.
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 5/5] soc-camera: Convert to a platform driver
2009-04-16 8:58 ` Guennadi Liakhovetski
@ 2009-04-16 10:00 ` Dongsoo, Nathaniel Kim
2009-04-16 10:30 ` Guennadi Liakhovetski
0 siblings, 1 reply; 46+ messages in thread
From: Dongsoo, Nathaniel Kim @ 2009-04-16 10:00 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: Linux Media Mailing List, Robert Jarzmik
Hello Guennadi,
On Thu, Apr 16, 2009 at 5:58 PM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> On Thu, 16 Apr 2009, Dongsoo, Nathaniel Kim wrote:
>
>> Hello Guennadi,
>>
>>
>> Reviewing your patch, I've got curious about a thing.
>> I think your soc camera subsystem is covering multiple camera
>> devices(sensors) in one target board, but if that is true I'm afraid
>> I'm confused how to handle them properly.
>> Because according to your patch, video_dev_create() takes camera
>> device as parameter and it seems to be creating device node for each
>> camera devices.
>
> This patch is a preparatory step for the v4l2-(sub)dev conversion. With it
> yes (I think) a video device will be created for every registered on the
> platform level camera, but only the one(s) that probed successfully will
> actually work, others will return -ENODEV on open().
>
>> It means, if I have one camera host and several camera devices, there
>> should be several device nodes for camera devices but cannot be used
>> at the same time. Because typical camera host(camera interface) can
>> handle only one camera device at a time. But multiple device nodes
>> mean "we can open and handle them at the same time".
>>
>> How about registering camera host device as v4l2 device and make
>> camera device a input device which could be handled using
>> VIDIOC_S_INPUT/G_INPUT api?
>
> There are also cases, when you have several cameras simultaneously (think
> for example about stereo vision), even though we don't have any such cases
> just yet.
I think, there are some specific camera interfaces for stereo camera.
Like stereo camera controller chip from Epson.
But in case of camera interface which can handle only one single
camera at a time, I'm strongly believing that we should use only one
device node for camera.
I mean device node should be the camera interface not the sensor
device. If you are using stereo camera controller chip, you can make
that with a couple of device nodes, like /dev/video0 and /dev/video1.
>
>> Actually, I'm working on S3C64xx camera interface driver with soc
>> camera subsystem,
>
> Looking forward to it!:-)
>
>> and I'm facing that issue right now because I've got
>> dual camera on my target board.
>
> Good, I think, there also has been a similar design based on a pxa270 SoC.
> How are cameras switched in your case? You probably have some additional
> hardware logic to switch between them, right? So, you need some code to
> control that. I think, you should even be able to do this automatically in
> your platform code using power hooks from the struct soc_camera_link. You
> could fail to power on a camera if another camera is currently active. In
> fact, I have to add a return code test to the call to icl->power(icl, 1)
> in soc_camera_open(), I'll do this for the final v4l2-dev version. Would
> this work for you or do you have another requirements? In which case, can
> you describe your use-case in more detail - should both cameras be open by
> applications simultaneously (looks like not), do you need a more explicit
> switching control, than just "first open switches," which shouldn't be the
> case, since you can even create a separate task, that does nothing but
> just keeps the required camera device open.
>
Yes exactly right. My H/W is designed to share data pins and mclk,
pclk pins between both of cameras.
And they have to work mutually exclusive.
For now I'm working on s3c64xx with soc camera subsystem, so no way to
make dual camera control with VIDIOC_S_INPUT, VIDIOC_G_INPUT. But the
prior version of my driver was made to control dual camera with those
S_INPUT/G_INPUT api.
Actually with single device node and switching camera with S_INPUT and
G_INPUT, there is no way to mis-control dual camera.
Because both of cameras work mutually exclusive.
To make it easier, you can take a look at my presentation file which I
gave a talk at CELF ELC2009 in San Francisco.
Here it is the presentation file
http://tree.celinuxforum.org/CelfPubWiki/ELC2009Presentations?action=AttachFile&do=get&target=Framework_for_digital_camera_in_linux-in_detail.ppt
I think it is more decent way to control dual camera. No need to check
whether the sensor is available or not using this way. Just use
G_INPUT to check current active sensor and do S_INPUT to switch into
another one.
Cheers,
Nate
>> I hope you to consider this concept, and also want to know your opinion.
>
> Thanks
> Guennadi
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
>
--
========================================================
DongSoo, Nathaniel Kim
Engineer
Mobile S/W Platform Lab.
Digital Media & Communications R&D Centre
Samsung Electronics CO., LTD.
e-mail : dongsoo.kim@gmail.com
dongsoo45.kim@samsung.com
========================================================
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [PATCH 5/5] soc-camera: Convert to a platform driver
2009-04-16 10:00 ` Dongsoo, Nathaniel Kim
@ 2009-04-16 10:30 ` Guennadi Liakhovetski
2009-04-16 11:09 ` Dongsoo, Nathaniel Kim
0 siblings, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-16 10:30 UTC (permalink / raw)
To: Dongsoo, Nathaniel Kim; +Cc: Linux Media Mailing List, Robert Jarzmik
On Thu, 16 Apr 2009, Dongsoo, Nathaniel Kim wrote:
> Hello Guennadi,
>
> On Thu, Apr 16, 2009 at 5:58 PM, Guennadi Liakhovetski
> <g.liakhovetski@gmx.de> wrote:
> > On Thu, 16 Apr 2009, Dongsoo, Nathaniel Kim wrote:
> >
> >> Hello Guennadi,
> >>
> >>
> >> Reviewing your patch, I've got curious about a thing.
> >> I think your soc camera subsystem is covering multiple camera
> >> devices(sensors) in one target board, but if that is true I'm afraid
> >> I'm confused how to handle them properly.
> >> Because according to your patch, video_dev_create() takes camera
> >> device as parameter and it seems to be creating device node for each
> >> camera devices.
> >
> > This patch is a preparatory step for the v4l2-(sub)dev conversion. With it
> > yes (I think) a video device will be created for every registered on the
> > platform level camera, but only the one(s) that probed successfully will
> > actually work, others will return -ENODEV on open().
> >
> >> It means, if I have one camera host and several camera devices, there
> >> should be several device nodes for camera devices but cannot be used
> >> at the same time. Because typical camera host(camera interface) can
> >> handle only one camera device at a time. But multiple device nodes
> >> mean "we can open and handle them at the same time".
> >>
> >> How about registering camera host device as v4l2 device and make
> >> camera device a input device which could be handled using
> >> VIDIOC_S_INPUT/G_INPUT api?
> >
> > There are also cases, when you have several cameras simultaneously (think
> > for example about stereo vision), even though we don't have any such cases
> > just yet.
>
> I think, there are some specific camera interfaces for stereo camera.
> Like stereo camera controller chip from Epson.
>
> But in case of camera interface which can handle only one single
> camera at a time, I'm strongly believing that we should use only one
> device node for camera.
> I mean device node should be the camera interface not the sensor
> device. If you are using stereo camera controller chip, you can make
> that with a couple of device nodes, like /dev/video0 and /dev/video1.
There are also some generic CMOS camera sensors, that support stereo mode,
e.g., mt9v022. In this case you would do the actual stereo processing in
host software, I think. The sensors just provide some synchronisation
possibilities. And you would need both sensors in user-space over video0
and video1. Also, i.MX31 datasheet says the (single) camera interface can
handle up to two cameras (simultaneously), however, I haven't found any
details how this could be supported in software, but I didn't look hard
either, because I didn't need it until now.
> >> Actually, I'm working on S3C64xx camera interface driver with soc
> >> camera subsystem,
> >
> > Looking forward to it!:-)
> >
> >> and I'm facing that issue right now because I've got
> >> dual camera on my target board.
> >
> > Good, I think, there also has been a similar design based on a pxa270 SoC.
> > How are cameras switched in your case? You probably have some additional
> > hardware logic to switch between them, right? So, you need some code to
> > control that. I think, you should even be able to do this automatically in
> > your platform code using power hooks from the struct soc_camera_link. You
> > could fail to power on a camera if another camera is currently active. In
> > fact, I have to add a return code test to the call to icl->power(icl, 1)
> > in soc_camera_open(), I'll do this for the final v4l2-dev version. Would
> > this work for you or do you have another requirements? In which case, can
> > you describe your use-case in more detail - should both cameras be open by
> > applications simultaneously (looks like not), do you need a more explicit
> > switching control, than just "first open switches," which shouldn't be the
> > case, since you can even create a separate task, that does nothing but
> > just keeps the required camera device open.
> >
>
> Yes exactly right. My H/W is designed to share data pins and mclk,
> pclk pins between both of cameras.
> And they have to work mutually exclusive.
> For now I'm working on s3c64xx with soc camera subsystem, so no way to
> make dual camera control with VIDIOC_S_INPUT, VIDIOC_G_INPUT. But the
> prior version of my driver was made to control dual camera with those
> S_INPUT/G_INPUT api.
> Actually with single device node and switching camera with S_INPUT and
> G_INPUT, there is no way to mis-control dual camera.
> Because both of cameras work mutually exclusive.
>
> To make it easier, you can take a look at my presentation file which I
> gave a talk at CELF ELC2009 in San Francisco.
> Here it is the presentation file
>
> http://tree.celinuxforum.org/CelfPubWiki/ELC2009Presentations?action=AttachFile&do=get&target=Framework_for_digital_camera_in_linux-in_detail.ppt
>
> I think it is more decent way to control dual camera. No need to check
> whether the sensor is available or not using this way. Just use
> G_INPUT to check current active sensor and do S_INPUT to switch into
> another one.
I understand your idea, but I don't see any significant advantages with it
or any problems with the current implementation. Notice, that this "one
video device node per one camera client" concept has been there since the
first version of soc-camera, it is not something new, that is coming now
with the v4l2-subdev conversion. So, unless you provide some strong
reasons I don't see a need to change this concept so far.
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 5/5] soc-camera: Convert to a platform driver
2009-04-16 10:30 ` Guennadi Liakhovetski
@ 2009-04-16 11:09 ` Dongsoo, Nathaniel Kim
2009-04-16 12:06 ` Guennadi Liakhovetski
0 siblings, 1 reply; 46+ messages in thread
From: Dongsoo, Nathaniel Kim @ 2009-04-16 11:09 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: Linux Media Mailing List, Robert Jarzmik
Hi Guennadi,
On Thu, Apr 16, 2009 at 7:30 PM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> On Thu, 16 Apr 2009, Dongsoo, Nathaniel Kim wrote:
>
>> Hello Guennadi,
>>
>> On Thu, Apr 16, 2009 at 5:58 PM, Guennadi Liakhovetski
>> <g.liakhovetski@gmx.de> wrote:
>> > On Thu, 16 Apr 2009, Dongsoo, Nathaniel Kim wrote:
>> >
>> >> Hello Guennadi,
>> >>
>> >>
>> >> Reviewing your patch, I've got curious about a thing.
>> >> I think your soc camera subsystem is covering multiple camera
>> >> devices(sensors) in one target board, but if that is true I'm afraid
>> >> I'm confused how to handle them properly.
>> >> Because according to your patch, video_dev_create() takes camera
>> >> device as parameter and it seems to be creating device node for each
>> >> camera devices.
>> >
>> > This patch is a preparatory step for the v4l2-(sub)dev conversion. With it
>> > yes (I think) a video device will be created for every registered on the
>> > platform level camera, but only the one(s) that probed successfully will
>> > actually work, others will return -ENODEV on open().
>> >
>> >> It means, if I have one camera host and several camera devices, there
>> >> should be several device nodes for camera devices but cannot be used
>> >> at the same time. Because typical camera host(camera interface) can
>> >> handle only one camera device at a time. But multiple device nodes
>> >> mean "we can open and handle them at the same time".
>> >>
>> >> How about registering camera host device as v4l2 device and make
>> >> camera device a input device which could be handled using
>> >> VIDIOC_S_INPUT/G_INPUT api?
>> >
>> > There are also cases, when you have several cameras simultaneously (think
>> > for example about stereo vision), even though we don't have any such cases
>> > just yet.
>>
>> I think, there are some specific camera interfaces for stereo camera.
>> Like stereo camera controller chip from Epson.
>>
>> But in case of camera interface which can handle only one single
>> camera at a time, I'm strongly believing that we should use only one
>> device node for camera.
>> I mean device node should be the camera interface not the sensor
>> device. If you are using stereo camera controller chip, you can make
>> that with a couple of device nodes, like /dev/video0 and /dev/video1.
>
> There are also some generic CMOS camera sensors, that support stereo mode,
> e.g., mt9v022. In this case you would do the actual stereo processing in
> host software, I think. The sensors just provide some synchronisation
> possibilities. And you would need both sensors in user-space over video0
> and video1. Also, i.MX31 datasheet says the (single) camera interface can
> handle up to two cameras (simultaneously), however, I haven't found any
> details how this could be supported in software, but I didn't look hard
> either, because I didn't need it until now.
Oh, interesting. I should look for mt9v022 datasheet.
BTW, also on OMAP3 user manual you can see that two cameras could be
opened at once (with different clock and so on), but it says also that
only one camera's data could be handled by ISP in OMAP.
I think the freescale CPU case could be the same condition.(sorry I'm not sure)
>
>> >> Actually, I'm working on S3C64xx camera interface driver with soc
>> >> camera subsystem,
>> >
>> > Looking forward to it!:-)
>> >
>> >> and I'm facing that issue right now because I've got
>> >> dual camera on my target board.
>> >
>> > Good, I think, there also has been a similar design based on a pxa270 SoC.
>> > How are cameras switched in your case? You probably have some additional
>> > hardware logic to switch between them, right? So, you need some code to
>> > control that. I think, you should even be able to do this automatically in
>> > your platform code using power hooks from the struct soc_camera_link. You
>> > could fail to power on a camera if another camera is currently active. In
>> > fact, I have to add a return code test to the call to icl->power(icl, 1)
>> > in soc_camera_open(), I'll do this for the final v4l2-dev version. Would
>> > this work for you or do you have another requirements? In which case, can
>> > you describe your use-case in more detail - should both cameras be open by
>> > applications simultaneously (looks like not), do you need a more explicit
>> > switching control, than just "first open switches," which shouldn't be the
>> > case, since you can even create a separate task, that does nothing but
>> > just keeps the required camera device open.
>> >
>>
>> Yes exactly right. My H/W is designed to share data pins and mclk,
>> pclk pins between both of cameras.
>> And they have to work mutually exclusive.
>> For now I'm working on s3c64xx with soc camera subsystem, so no way to
>> make dual camera control with VIDIOC_S_INPUT, VIDIOC_G_INPUT. But the
>> prior version of my driver was made to control dual camera with those
>> S_INPUT/G_INPUT api.
>> Actually with single device node and switching camera with S_INPUT and
>> G_INPUT, there is no way to mis-control dual camera.
>> Because both of cameras work mutually exclusive.
>>
>> To make it easier, you can take a look at my presentation file which I
>> gave a talk at CELF ELC2009 in San Francisco.
>> Here it is the presentation file
>>
>> http://tree.celinuxforum.org/CelfPubWiki/ELC2009Presentations?action=AttachFile&do=get&target=Framework_for_digital_camera_in_linux-in_detail.ppt
>>
>> I think it is more decent way to control dual camera. No need to check
>> whether the sensor is available or not using this way. Just use
>> G_INPUT to check current active sensor and do S_INPUT to switch into
>> another one.
>
> I understand your idea, but I don't see any significant advantages with it
> or any problems with the current implementation. Notice, that this "one
> video device node per one camera client" concept has been there since the
> first version of soc-camera, it is not something new, that is coming now
> with the v4l2-subdev conversion. So, unless you provide some strong
> reasons I don't see a need to change this concept so far.
>
My concern is all about the logical thing. "Why can't we open device
node even if it is not opened from any other process."
I have been working on dual camera with Linux for few years, and
everybody who I'm working with wants not to fail opening camera device
node in the first place. Actually I'm mobile phone developer and I've
been seeing so many exceptional cases in field with dual camera
applications. With all my experiences, I got my conclusion which is
"Don't make user get confused with device opening failure". I want you
to know that no offence but just want to make it better.
But the mt9v022 case, I should need some research.
Cheers,
Nate
> Thanks
> Guennadi
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
>
--
========================================================
DongSoo, Nathaniel Kim
Engineer
Mobile S/W Platform Lab.
Digital Media & Communications R&D Centre
Samsung Electronics CO., LTD.
e-mail : dongsoo.kim@gmail.com
dongsoo45.kim@samsung.com
========================================================
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [PATCH 5/5] soc-camera: Convert to a platform driver
2009-04-16 11:09 ` Dongsoo, Nathaniel Kim
@ 2009-04-16 12:06 ` Guennadi Liakhovetski
2009-04-16 12:48 ` Dongsoo, Nathaniel Kim
0 siblings, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-16 12:06 UTC (permalink / raw)
To: Dongsoo, Nathaniel Kim; +Cc: Linux Media Mailing List, Robert Jarzmik
On Thu, 16 Apr 2009, Dongsoo, Nathaniel Kim wrote:
> My concern is all about the logical thing. "Why can't we open device
> node even if it is not opened from any other process."
The answer is of course "because the other node is currently active," but
I can understand the sort of "confusion" that the user might have: we have
two "independent" device nodes, but only one of them can be active at any
given time. So, in a way you're right, this might not be very intuitive.
> I have been working on dual camera with Linux for few years, and
> everybody who I'm working with wants not to fail opening camera device
> node in the first place. Actually I'm mobile phone developer and I've
> been seeing so many exceptional cases in field with dual camera
> applications. With all my experiences, I got my conclusion which is
> "Don't make user get confused with device opening failure". I want you
> to know that no offence but just want to make it better.
Sure, I appreciate your opinion and respect your experience, but let's
have a look at the current concept:
1. the platform has N cameras on camera interface X
2. soc_camera.c finds the matching interface X and creates M (<= N) nodes
for all successfully probed devices.
3. in the beginning, as long as no device is open, all cameras are powered
down / inactive.
4. you then open() one of them, it gets powered on / activated, the others
become unaccessible as long as one is used.
5. this way switching is easy - you're sure, that when no device is open,
all cameras are powered down, so, you can safely select any of them.
6. module reference-counting is easy too - every open() of a device-node
increments the use-count
With your proposed approach:
1. the platform has N cameras on camera interface X.
2. as long as at least one camera probed successfully for interface X, you
create a videoX device and count inputs for it - successfully probed
cameras.
3. you open videoX, one "default" camera gets activated immediately - not
all applications issue S_INPUT, so, there has to be a default.
4. if an S_INPUT is issued, you have to verify, whether any camera is
currently active / capturing, if none - switch to the requested one, if
one is active - return -EBUSY.
5. reference-counting and guaranteeing consistency is more difficult, as
well as handling camera driver loading / unloading.
So, I would say, your approach adds complexity and asymmetry. Can it be
that one camera client has several inputs itself? E.g., a decoder? In any
case, I wouldn't do this now, if we do decide in favour of your approach,
then only after the v4l2-device transition, please.
> But the mt9v022 case, I should need some research.
Ok.
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 5/5] soc-camera: Convert to a platform driver
2009-04-16 12:06 ` Guennadi Liakhovetski
@ 2009-04-16 12:48 ` Dongsoo, Nathaniel Kim
2009-04-16 12:59 ` Guennadi Liakhovetski
0 siblings, 1 reply; 46+ messages in thread
From: Dongsoo, Nathaniel Kim @ 2009-04-16 12:48 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: Linux Media Mailing List, Robert Jarzmik
Hello Guennadi,
On Thu, Apr 16, 2009 at 9:06 PM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> On Thu, 16 Apr 2009, Dongsoo, Nathaniel Kim wrote:
>
>> My concern is all about the logical thing. "Why can't we open device
>> node even if it is not opened from any other process."
>
> The answer is of course "because the other node is currently active," but
> I can understand the sort of "confusion" that the user might have: we have
> two "independent" device nodes, but only one of them can be active at any
> given time. So, in a way you're right, this might not be very intuitive.
>
>> I have been working on dual camera with Linux for few years, and
>> everybody who I'm working with wants not to fail opening camera device
>> node in the first place. Actually I'm mobile phone developer and I've
>> been seeing so many exceptional cases in field with dual camera
>> applications. With all my experiences, I got my conclusion which is
>> "Don't make user get confused with device opening failure". I want you
>> to know that no offence but just want to make it better.
>
> Sure, I appreciate your opinion and respect your experience, but let's
> have a look at the current concept:
>
> 1. the platform has N cameras on camera interface X
> 2. soc_camera.c finds the matching interface X and creates M (<= N) nodes
> for all successfully probed devices.
> 3. in the beginning, as long as no device is open, all cameras are powered
> down / inactive.
> 4. you then open() one of them, it gets powered on / activated, the others
> become unaccessible as long as one is used.
> 5. this way switching is easy - you're sure, that when no device is open,
> all cameras are powered down, so, you can safely select any of them.
> 6. module reference-counting is easy too - every open() of a device-node
> increments the use-count
>
Honestly it is not that bad. but in situation of multiple processes
trying to access camera devices like process A already opened video0
and process B tries to open video1, process B should face an error
returns even though process B checked for video1 is already opened or
not and verified that it is not opened.
> With your proposed approach:
>
> 1. the platform has N cameras on camera interface X.
> 2. as long as at least one camera probed successfully for interface X, you
> create a videoX device and count inputs for it - successfully probed
> cameras.
> 3. you open videoX, one "default" camera gets activated immediately - not
> all applications issue S_INPUT, so, there has to be a default.
> 4. if an S_INPUT is issued, you have to verify, whether any camera is
> currently active / capturing, if none - switch to the requested one, if
> one is active - return -EBUSY.
> 5. reference-counting and guaranteeing consistency is more difficult, as
> well as handling camera driver loading / unloading.
Oops I forgot to say that we need to enforce legacy v4l2 applications
to use VIDIOC_S_INPUT after opening device.
And every S_INPUT issuing should come after G_INPUT like every "set"
API in v4l2.
>
> So, I would say, your approach adds complexity and asymmetry. Can it be
> that one camera client has several inputs itself? E.g., a decoder? In any
> case, I wouldn't do this now, if we do decide in favour of your approach,
> then only after the v4l2-device transition, please.
>
Of course. I didn't mean to disturb your transition job. Please do
your priority job first.
And about camera client with several inputs question, I will say that
almost every 3G UMTS phone has dual camera on it. And we can consider
every 3G UMTS smart phones have dual camera on it with soc camera
solution.
BTW, thank you for this conversation. It was a pleasure to discuss
about this issue with you.
Cheers,
Nate
>> But the mt9v022 case, I should need some research.
>
> Ok.
>
> Thanks
> Guennadi
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
>
--
========================================================
DongSoo, Nathaniel Kim
Engineer
Mobile S/W Platform Lab.
Digital Media & Communications R&D Centre
Samsung Electronics CO., LTD.
e-mail : dongsoo.kim@gmail.com
dongsoo45.kim@samsung.com
========================================================
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [PATCH 5/5] soc-camera: Convert to a platform driver
2009-04-16 12:48 ` Dongsoo, Nathaniel Kim
@ 2009-04-16 12:59 ` Guennadi Liakhovetski
2009-04-16 14:44 ` Dongsoo Kim
0 siblings, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-16 12:59 UTC (permalink / raw)
To: Dongsoo, Nathaniel Kim; +Cc: Linux Media Mailing List, Robert Jarzmik
On Thu, 16 Apr 2009, Dongsoo, Nathaniel Kim wrote:
> Hello Guennadi,
>
> On Thu, Apr 16, 2009 at 9:06 PM, Guennadi Liakhovetski
> <g.liakhovetski@gmx.de> wrote:
> > 3. you open videoX, one "default" camera gets activated immediately - not
> > all applications issue S_INPUT, so, there has to be a default.
> > 4. if an S_INPUT is issued, you have to verify, whether any camera is
> > currently active / capturing, if none - switch to the requested one, if
> > one is active - return -EBUSY.
> > 5. reference-counting and guaranteeing consistency is more difficult, as
> > well as handling camera driver loading / unloading.
>
> Oops I forgot to say that we need to enforce legacy v4l2 applications
> to use VIDIOC_S_INPUT after opening device.
> And every S_INPUT issuing should come after G_INPUT like every "set"
> API in v4l2.
Hm? Does the API require it? If not, I don't think we should inforce it.
And what do you mean "legacy v4l2 applications" - which applications are
not "legacy"?
> > So, I would say, your approach adds complexity and asymmetry. Can it be
> > that one camera client has several inputs itself? E.g., a decoder? In any
> > case, I wouldn't do this now, if we do decide in favour of your approach,
> > then only after the v4l2-device transition, please.
> >
>
> Of course. I didn't mean to disturb your transition job. Please do
> your priority job first.
>
> And about camera client with several inputs question, I will say that
> almost every 3G UMTS phone has dual camera on it. And we can consider
> every 3G UMTS smart phones have dual camera on it with soc camera
> solution.
No, sorry, this wasn't my question. By "client" I meant one camera or
decoder or whatever chip connects to a camera host. I.e., if we have a
single chip with several inputs, that should logically be handled with
S_INPUT ioctl, this would further add to the confusion of using different
inputs on one video device to switch between chips or inputs / functions
on one chip.
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 5/5] soc-camera: Convert to a platform driver
2009-04-16 12:59 ` Guennadi Liakhovetski
@ 2009-04-16 14:44 ` Dongsoo Kim
2009-04-16 14:56 ` Guennadi Liakhovetski
0 siblings, 1 reply; 46+ messages in thread
From: Dongsoo Kim @ 2009-04-16 14:44 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: Linux Media Mailing List, Robert Jarzmik
2009. 04. 16, 오후 9:59, Guennadi Liakhovetski 작성:
> On Thu, 16 Apr 2009, Dongsoo, Nathaniel Kim wrote:
>
>> Hello Guennadi,
>>
>> On Thu, Apr 16, 2009 at 9:06 PM, Guennadi Liakhovetski
>> <g.liakhovetski@gmx.de> wrote:
>>> 3. you open videoX, one "default" camera gets activated
>>> immediately - not
>>> all applications issue S_INPUT, so, there has to be a default.
>>> 4. if an S_INPUT is issued, you have to verify, whether any camera
>>> is
>>> currently active / capturing, if none - switch to the requested
>>> one, if
>>> one is active - return -EBUSY.
>>> 5. reference-counting and guaranteeing consistency is more
>>> difficult, as
>>> well as handling camera driver loading / unloading.
>>
>> Oops I forgot to say that we need to enforce legacy v4l2 applications
>> to use VIDIOC_S_INPUT after opening device.
>> And every S_INPUT issuing should come after G_INPUT like every "set"
>> API in v4l2.
>
> Hm? Does the API require it? If not, I don't think we should inforce
> it.
No I don't think so, but we can use that to be sure.
>
> And what do you mean "legacy v4l2 applications" - which applications
> are
>
> not "legacy"?
I mean upcoming applications in the future, like LiMo based platform
from several mobile phone vendors.
And we can also expect for 3rd party applications if the camera APIs
are well made and standardized.
>
>
>>> So, I would say, your approach adds complexity and asymmetry. Can
>>> it be
>>> that one camera client has several inputs itself? E.g., a decoder?
>>> In any
>>> case, I wouldn't do this now, if we do decide in favour of your
>>> approach,
>>> then only after the v4l2-device transition, please.
>>>
>>
>> Of course. I didn't mean to disturb your transition job. Please do
>> your priority job first.
>>
>> And about camera client with several inputs question, I will say that
>> almost every 3G UMTS phone has dual camera on it. And we can consider
>> every 3G UMTS smart phones have dual camera on it with soc camera
>> solution.
>
> No, sorry, this wasn't my question. By "client" I meant one camera or
> decoder or whatever chip connects to a camera host. I.e., if we have a
> single chip with several inputs, that should logically be handled with
> S_INPUT ioctl, this would further add to the confusion of using
> different
> inputs on one video device to switch between chips or inputs /
> functions
> on one chip.
Yes exactly. It was "single chip with several inputs." that I
intended to tell. but still don't get what the confusion you mean.
Sorry ;-()
Cheers,
Nate
>
>
> Thanks
> Guennadi
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 5/5] soc-camera: Convert to a platform driver
2009-04-16 14:44 ` Dongsoo Kim
@ 2009-04-16 14:56 ` Guennadi Liakhovetski
2009-04-16 15:15 ` Dongsoo Kim
0 siblings, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-16 14:56 UTC (permalink / raw)
To: Dongsoo Kim; +Cc: Linux Media Mailing List, Robert Jarzmik
On Thu, 16 Apr 2009, Dongsoo Kim wrote:
> > > And about camera client with several inputs question, I will say that
> > > almost every 3G UMTS phone has dual camera on it. And we can consider
> > > every 3G UMTS smart phones have dual camera on it with soc camera
> > > solution.
> >
> > No, sorry, this wasn't my question. By "client" I meant one camera or
> > decoder or whatever chip connects to a camera host. I.e., if we have a
> > single chip with several inputs, that should logically be handled with
> > S_INPUT ioctl, this would further add to the confusion of using different
> > inputs on one video device to switch between chips or inputs / functions
> > on one chip.
>
> Yes exactly. It was "single chip with several inputs." that I intended to
> tell. but still don't get what the confusion you mean. Sorry ;-()
> Cheers,
Wow, so, on those phone a "dual camera" is a single (CMOS) controller with
two sensors / lenses / filters?... Cool, do you have an example of such a
camera to look for on the net? Preferably with a datasheet available.
"Confusion" I meant that in this case switching between inputs sometimes
switches you to another controller and sometimes to another function
within the same controller...
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 5/5] soc-camera: Convert to a platform driver
2009-04-16 14:56 ` Guennadi Liakhovetski
@ 2009-04-16 15:15 ` Dongsoo Kim
0 siblings, 0 replies; 46+ messages in thread
From: Dongsoo Kim @ 2009-04-16 15:15 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: Linux Media Mailing List, Robert Jarzmik
2009. 04. 16, 오후 11:56, Guennadi Liakhovetski 작성:
> On Thu, 16 Apr 2009, Dongsoo Kim wrote:
>
>>>> And about camera client with several inputs question, I will say
>>>> that
>>>> almost every 3G UMTS phone has dual camera on it. And we can
>>>> consider
>>>> every 3G UMTS smart phones have dual camera on it with soc camera
>>>> solution.
>>>
>>> No, sorry, this wasn't my question. By "client" I meant one camera
>>> or
>>> decoder or whatever chip connects to a camera host. I.e., if we
>>> have a
>>> single chip with several inputs, that should logically be handled
>>> with
>>> S_INPUT ioctl, this would further add to the confusion of using
>>> different
>>> inputs on one video device to switch between chips or inputs /
>>> functions
>>> on one chip.
>>
>> Yes exactly. It was "single chip with several inputs." that I
>> intended to
>> tell. but still don't get what the confusion you mean. Sorry ;-()
>> Cheers,
>
> Wow, so, on those phone a "dual camera" is a single (CMOS)
> controller with
> two sensors / lenses / filters?... Cool, do you have an example of
> such a
> camera to look for on the net? Preferably with a datasheet available.
>
Oops sorry I didn't mean that.
I just meant one single camera interface on Application Processor and
two camera modules (sensor, lens, isp) connected. Sorry I explained
badly.
I considered this as single camera interface with several inputs.
> "Confusion" I meant that in this case switching between inputs
> sometimes
> switches you to another controller and sometimes to another function
> within the same controller...
I think we don't need to worry about that if we can query camera
inputs clearly.
Cheers,
Nate
>
>
> Thanks
> Guennadi
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-15 12:17 [PATCH 0/5] soc-camera: convert to platform device Guennadi Liakhovetski
` (4 preceding siblings ...)
2009-04-15 12:20 ` [PATCH 5/5] soc-camera: Convert to a platform driver Guennadi Liakhovetski
@ 2009-04-15 20:36 ` Robert Jarzmik
2009-04-16 17:49 ` Robert Jarzmik
2009-04-17 7:29 ` Dongsoo, Nathaniel Kim
2009-04-17 7:40 ` Magnus Damm
7 siblings, 1 reply; 46+ messages in thread
From: Robert Jarzmik @ 2009-04-15 20:36 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: Linux Media Mailing List
Guennadi Liakhovetski <g.liakhovetski@gmx.de> writes:
> This patch series is a preparation for the v4l2-subdev conversion. Please,
> review and test. My current patch-stack in the form of a
> (manually-created) quilt-series is at
> http://www.open-technology.de/download/20090415/ based on linux-next
> history branch, commit ID in 0000-base file. Don't be surprised, that
> patch-set also contains a few not directly related patches.
Right, apart from a few comments, the bright side is your serie resists my full
test campaign.
I need to make some additionnal tests with I2C loading/unloading, but otherwise
it works perfectly for (soc_camera / pxa_camera /mt9m111 combination).
Cheers.
--
Robert
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-15 20:36 ` [PATCH 0/5] soc-camera: convert to platform device Robert Jarzmik
@ 2009-04-16 17:49 ` Robert Jarzmik
2009-04-16 18:14 ` Guennadi Liakhovetski
0 siblings, 1 reply; 46+ messages in thread
From: Robert Jarzmik @ 2009-04-16 17:49 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: Linux Media Mailing List
Robert Jarzmik <robert.jarzmik@free.fr> writes:
> I need to make some additionnal tests with I2C loading/unloading, but otherwise
> it works perfectly for (soc_camera / pxa_camera /mt9m111 combination).
Guennadi,
I made some testing, and there is something I don't understand in the new device
model.
This is the testcase I'm considering :
- I unload i2c-pxa, pxa-camera, mt9m111, soc-camera modules
- I load pxa-camera, mt9m111, soc-camera modules
- I then load i2c-pxa
=> the mt9m111 is not detected
- I unload and reload mt9m111 and pxa_camera
=> not any better
- I unload soc_camera, mt9m111, pxa_camera and reload
=> this time the video device is detected
What I'm getting at is that if soc_camera is loaded before the i2c host driver,
no camera will get any chance to work. Is that normal considering the new driver
model ?
I was naively thinking that there would be a "rescan" when the "control" was
being available for a sensor.
Cheers.
--
Robert
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-16 17:49 ` Robert Jarzmik
@ 2009-04-16 18:14 ` Guennadi Liakhovetski
2009-04-16 19:04 ` Robert Jarzmik
0 siblings, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-16 18:14 UTC (permalink / raw)
To: Robert Jarzmik; +Cc: Linux Media Mailing List
On Thu, 16 Apr 2009, Robert Jarzmik wrote:
> Robert Jarzmik <robert.jarzmik@free.fr> writes:
>
> > I need to make some additionnal tests with I2C loading/unloading, but otherwise
> > it works perfectly for (soc_camera / pxa_camera /mt9m111 combination).
>
> Guennadi,
>
> I made some testing, and there is something I don't understand in the new device
> model.
> This is the testcase I'm considering :
> - I unload i2c-pxa, pxa-camera, mt9m111, soc-camera modules
> - I load pxa-camera, mt9m111, soc-camera modules
> - I then load i2c-pxa
> => the mt9m111 is not detected
correct
> - I unload and reload mt9m111 and pxa_camera
> => not any better
Actually, I think, in this case it should be found again, as long as you
reload pxa-camera while i2c-pxa is already loaded.
> - I unload soc_camera, mt9m111, pxa_camera and reload
> => this time the video device is detected
>
> What I'm getting at is that if soc_camera is loaded before the i2c host driver,
> no camera will get any chance to work. Is that normal considering the new driver
> model ?
> I was naively thinking that there would be a "rescan" when the "control" was
> being available for a sensor.
Yes, unfortunately, it is "normal":-( On the one hand, we shouldn't really
spend _too_ much time on this intermediate version, because, as I said, it
is just a preparatory step for v4l2-subdev. We just have to make sure it
doesn't introduce any significant regressions and doesn't crash too often.
OTOH, this is also how it is with v4l2-subdev. With it you first must have
the i2c-adapter driver loaded. Then, when a match between a camera host
and a camera client (sensor) platform device is detected, it is reported
to the v4l2-subdev core, which loads the respective camera i2c driver. If
you then unload the camera-host and i2c adapter drivers, and then you load
the camera-host driver, it then fails to get the adapter, and if you then
load it, nothing else happens. To reprobe you have to unload and reload
the camera host driver.
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-16 18:14 ` Guennadi Liakhovetski
@ 2009-04-16 19:04 ` Robert Jarzmik
0 siblings, 0 replies; 46+ messages in thread
From: Robert Jarzmik @ 2009-04-16 19:04 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: Linux Media Mailing List
Guennadi Liakhovetski <g.liakhovetski@gmx.de> writes:
>> - I unload and reload mt9m111 and pxa_camera
>> => not any better
>
> Actually, I think, in this case it should be found again, as long as you
> reload pxa-camera while i2c-pxa is already loaded.
Damn, you're right. I cross-checked, and reloading pxa_camera rescans the
sensor.
>> What I'm getting at is that if soc_camera is loaded before the i2c host driver,
>> no camera will get any chance to work. Is that normal considering the new driver
>> model ?
>> I was naively thinking that there would be a "rescan" when the "control" was
>> being available for a sensor.
>
> Yes, unfortunately, it is "normal":-( On the one hand, we shouldn't really
> spend _too_ much time on this intermediate version, because, as I said, it
> is just a preparatory step for v4l2-subdev. We just have to make sure it
> doesn't introduce any significant regressions and doesn't crash too often.
OK. So from my side everything is OK (let aside my nitpicking in mioa701.c and
mt9m111.c).
> OTOH, this is also how it is with v4l2-subdev. With it you first must have
> the i2c-adapter driver loaded. Then, when a match between a camera host
> and a camera client (sensor) platform device is detected, it is reported
> to the v4l2-subdev core, which loads the respective camera i2c driver.
OK, why not.
> If you then unload the camera-host and i2c adapter drivers, and then you load
> the camera-host driver, it then fails to get the adapter, and if you then load
> it, nothing else happens. To reprobe you have to unload and reload the camera
> host driver.
So be it. I'm sure we'll be through it once more in the v4l2-subdev transition,
so I'll let aside any objection I could mutter :)
Cheers.
--
Robert
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-15 12:17 [PATCH 0/5] soc-camera: convert to platform device Guennadi Liakhovetski
` (5 preceding siblings ...)
2009-04-15 20:36 ` [PATCH 0/5] soc-camera: convert to platform device Robert Jarzmik
@ 2009-04-17 7:29 ` Dongsoo, Nathaniel Kim
2009-04-17 7:48 ` Guennadi Liakhovetski
2009-04-17 7:40 ` Magnus Damm
7 siblings, 1 reply; 46+ messages in thread
From: Dongsoo, Nathaniel Kim @ 2009-04-17 7:29 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: Linux Media Mailing List, Robert Jarzmik
Hello,
I've got one more thing to ask.
Is SoC camera framework supporting for selecting video standards
between camera interface and external camera module? I mean ITU-R BT
601 and 656 things.
Or any different way that I'm not aware is supported?
On Wed, Apr 15, 2009 at 9:17 PM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> This patch series is a preparation for the v4l2-subdev conversion. Please,
> review and test. My current patch-stack in the form of a
> (manually-created) quilt-series is at
> http://www.open-technology.de/download/20090415/ based on linux-next
> history branch, commit ID in 0000-base file. Don't be surprised, that
> patch-set also contains a few not directly related patches.
>
> Thanks
> Guennadi
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
========================================================
DongSoo, Nathaniel Kim
Engineer
Mobile S/W Platform Lab.
Digital Media & Communications R&D Centre
Samsung Electronics CO., LTD.
e-mail : dongsoo.kim@gmail.com
dongsoo45.kim@samsung.com
========================================================
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-17 7:29 ` Dongsoo, Nathaniel Kim
@ 2009-04-17 7:48 ` Guennadi Liakhovetski
2009-04-17 7:50 ` Dongsoo, Nathaniel Kim
0 siblings, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-17 7:48 UTC (permalink / raw)
To: Dongsoo, Nathaniel Kim; +Cc: Linux Media Mailing List, Robert Jarzmik
On Fri, 17 Apr 2009, Dongsoo, Nathaniel Kim wrote:
> I've got one more thing to ask.
> Is SoC camera framework supporting for selecting video standards
> between camera interface and external camera module? I mean ITU-R BT
> 601 and 656 things.
> Or any different way that I'm not aware is supported?
I thought someone did it already, maybe there were some patches that
didn't make it in yet, cannot find ATM. In any case, we do have a pretty
advanced (!:-)) bus parameter negotiation infrastructure, so, you would
just have a couple more SOCAM_* flags, like SOCAM_BT601, SOCAM_BT656 or
similar and use them to configure your host-camera link, depending upon
their capabilities and platform flags. See for example how SOCAM_MASTER /
SOCAM_SLAVE is selected. Also don't forget to extend the
soc_camera_bus_param_compatible() function.
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-17 7:48 ` Guennadi Liakhovetski
@ 2009-04-17 7:50 ` Dongsoo, Nathaniel Kim
0 siblings, 0 replies; 46+ messages in thread
From: Dongsoo, Nathaniel Kim @ 2009-04-17 7:50 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: Linux Media Mailing List, Robert Jarzmik
On Fri, Apr 17, 2009 at 4:48 PM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> On Fri, 17 Apr 2009, Dongsoo, Nathaniel Kim wrote:
>
>> I've got one more thing to ask.
>> Is SoC camera framework supporting for selecting video standards
>> between camera interface and external camera module? I mean ITU-R BT
>> 601 and 656 things.
>> Or any different way that I'm not aware is supported?
>
> I thought someone did it already, maybe there were some patches that
> didn't make it in yet, cannot find ATM. In any case, we do have a pretty
> advanced (!:-)) bus parameter negotiation infrastructure, so, you would
> just have a couple more SOCAM_* flags, like SOCAM_BT601, SOCAM_BT656 or
> similar and use them to configure your host-camera link, depending upon
> their capabilities and platform flags. See for example how SOCAM_MASTER /
> SOCAM_SLAVE is selected. Also don't forget to extend the
> soc_camera_bus_param_compatible() function.
Pretty cool! I didn't realize that.
Cheers
>
> Thanks
> Guennadi
> ---
> Guennadi Liakhovetski, Ph.D.
> Freelance Open-Source Software Developer
>
--
========================================================
DongSoo, Nathaniel Kim
Engineer
Mobile S/W Platform Lab.
Digital Media & Communications R&D Centre
Samsung Electronics CO., LTD.
e-mail : dongsoo.kim@gmail.com
dongsoo45.kim@samsung.com
========================================================
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-15 12:17 [PATCH 0/5] soc-camera: convert to platform device Guennadi Liakhovetski
` (6 preceding siblings ...)
2009-04-17 7:29 ` Dongsoo, Nathaniel Kim
@ 2009-04-17 7:40 ` Magnus Damm
2009-04-17 7:51 ` Guennadi Liakhovetski
2009-04-17 18:38 ` [PATCH 5/5 v2] soc-camera: Convert to a platform driver Guennadi Liakhovetski
7 siblings, 2 replies; 46+ messages in thread
From: Magnus Damm @ 2009-04-17 7:40 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: Linux Media Mailing List, Robert Jarzmik
Hi Guennadi,
On Wed, Apr 15, 2009 at 9:17 PM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> This patch series is a preparation for the v4l2-subdev conversion. Please,
> review and test. My current patch-stack in the form of a
> (manually-created) quilt-series is at
> http://www.open-technology.de/download/20090415/ based on linux-next
> history branch, commit ID in 0000-base file. Don't be surprised, that
> patch-set also contains a few not directly related patches.
Testing on Migo-R board with 2.6.30-rc2-git-something and the
following cherry-picked patches:
0007-driver-core-fix-driver_match_device.patch
0033-soc-camera-host-driver-cleanup.patch
0034-soc-camera-remove-an-extra-device-generation-from-s.patch
0035-soc-camera-simplify-register-access-routines-in-mul.patch
and part of 0036 (avoiding rejects, ap325 seems broken btw)
It compiles just fine, boots up allright, but I can't open /dev/video0 anymore.
It's still supposed to work with all drivers compiled-in, right?
I'll investigate a bit more and update to latest linux-2.6 git.
/ magnus
^ permalink raw reply [flat|nested] 46+ messages in thread* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-17 7:40 ` Magnus Damm
@ 2009-04-17 7:51 ` Guennadi Liakhovetski
2009-04-17 10:31 ` Magnus Damm
2009-04-17 18:38 ` [PATCH 5/5 v2] soc-camera: Convert to a platform driver Guennadi Liakhovetski
1 sibling, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-17 7:51 UTC (permalink / raw)
To: Magnus Damm; +Cc: Linux Media Mailing List, Robert Jarzmik
On Fri, 17 Apr 2009, Magnus Damm wrote:
> Hi Guennadi,
>
> On Wed, Apr 15, 2009 at 9:17 PM, Guennadi Liakhovetski
> <g.liakhovetski@gmx.de> wrote:
> > This patch series is a preparation for the v4l2-subdev conversion. Please,
> > review and test. My current patch-stack in the form of a
> > (manually-created) quilt-series is at
> > http://www.open-technology.de/download/20090415/ based on linux-next
> > history branch, commit ID in 0000-base file. Don't be surprised, that
> > patch-set also contains a few not directly related patches.
>
> Testing on Migo-R board with 2.6.30-rc2-git-something and the
> following cherry-picked patches:
>
> 0007-driver-core-fix-driver_match_device.patch
> 0033-soc-camera-host-driver-cleanup.patch
> 0034-soc-camera-remove-an-extra-device-generation-from-s.patch
> 0035-soc-camera-simplify-register-access-routines-in-mul.patch
> and part of 0036 (avoiding rejects, ap325 seems broken btw)
Have I broken it or is it unrelated?
> It compiles just fine, boots up allright, but I can't open /dev/video0 anymore.
>
> It's still supposed to work with all drivers compiled-in, right?
>
> I'll investigate a bit more and update to latest linux-2.6 git.
Ok, if you don't find the reason soon enough, you can just leave it and
I'll look at it myself.
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-17 7:51 ` Guennadi Liakhovetski
@ 2009-04-17 10:31 ` Magnus Damm
2009-04-17 10:43 ` Guennadi Liakhovetski
2009-04-20 0:12 ` Kuninori Morimoto
0 siblings, 2 replies; 46+ messages in thread
From: Magnus Damm @ 2009-04-17 10:31 UTC (permalink / raw)
To: Guennadi Liakhovetski
Cc: Linux Media Mailing List, Robert Jarzmik, Kuninori Morimoto
On Fri, Apr 17, 2009 at 4:51 PM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> On Fri, 17 Apr 2009, Magnus Damm wrote:
>> On Wed, Apr 15, 2009 at 9:17 PM, Guennadi Liakhovetski
>> <g.liakhovetski@gmx.de> wrote:
>> > This patch series is a preparation for the v4l2-subdev conversion. Please,
>> > review and test. My current patch-stack in the form of a
>> > (manually-created) quilt-series is at
>> > http://www.open-technology.de/download/20090415/ based on linux-next
>> > history branch, commit ID in 0000-base file. Don't be surprised, that
>> > patch-set also contains a few not directly related patches.
>>
>> Testing on Migo-R board with 2.6.30-rc2-git-something and the
>> following cherry-picked patches:
>>
>> 0007-driver-core-fix-driver_match_device.patch
>> 0033-soc-camera-host-driver-cleanup.patch
>> 0034-soc-camera-remove-an-extra-device-generation-from-s.patch
>> 0035-soc-camera-simplify-register-access-routines-in-mul.patch
>> and part of 0036 (avoiding rejects, ap325 seems broken btw)
>
> Have I broken it or is it unrelated?
2.6.30-rc seems broken on Migo-R. A quick check suggests the following:
V4L/DVB (10141): OK
V4L/DVB (10672): BAD
V4L/DVB (11024): BAD
OK means mplayer capture works as excepted with CEU and ov772x.
BAD means failure to open() /dev/video0 in the case of CEU. vivi works fine.
Morimoto-san and/or Guennadi, do you see the same thing?
Cheers,
/ magnus
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-17 10:31 ` Magnus Damm
@ 2009-04-17 10:43 ` Guennadi Liakhovetski
2009-04-20 7:14 ` Magnus Damm
2009-04-20 0:12 ` Kuninori Morimoto
1 sibling, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-17 10:43 UTC (permalink / raw)
To: Magnus Damm; +Cc: Linux Media Mailing List, Robert Jarzmik, Kuninori Morimoto
On Fri, 17 Apr 2009, Magnus Damm wrote:
> On Fri, Apr 17, 2009 at 4:51 PM, Guennadi Liakhovetski
> <g.liakhovetski@gmx.de> wrote:
> > On Fri, 17 Apr 2009, Magnus Damm wrote:
> >> On Wed, Apr 15, 2009 at 9:17 PM, Guennadi Liakhovetski
> >> <g.liakhovetski@gmx.de> wrote:
> >> > This patch series is a preparation for the v4l2-subdev conversion. Please,
> >> > review and test. My current patch-stack in the form of a
> >> > (manually-created) quilt-series is at
> >> > http://www.open-technology.de/download/20090415/ based on linux-next
> >> > history branch, commit ID in 0000-base file. Don't be surprised, that
> >> > patch-set also contains a few not directly related patches.
> >>
> >> Testing on Migo-R board with 2.6.30-rc2-git-something and the
> >> following cherry-picked patches:
> >>
> >> 0007-driver-core-fix-driver_match_device.patch
> >> 0033-soc-camera-host-driver-cleanup.patch
> >> 0034-soc-camera-remove-an-extra-device-generation-from-s.patch
> >> 0035-soc-camera-simplify-register-access-routines-in-mul.patch
> >> and part of 0036 (avoiding rejects, ap325 seems broken btw)
> >
> > Have I broken it or is it unrelated?
>
> 2.6.30-rc seems broken on Migo-R. A quick check suggests the following:
Ok, before we come to Migo-R, what is with ap325? Have I broken it with
this my series or is it a different problem?
> V4L/DVB (10141): OK
> V4L/DVB (10672): BAD
> V4L/DVB (11024): BAD
These seem to be pretty random snapshots... Are they all on Linus' master
or on next or on v4l-dvb? You did pick up the
0007-driver-core-fix-driver_match_device.patch
above, so, you know about that problem (I am very much surprised in fact
that patch is still not in the mainline, just sent a reminder...), and you
did use it in all your tests with kernels past
49b420a13ff95b449947181190b08367348e3e1b didn't you?
> OK means mplayer capture works as excepted with CEU and ov772x.
> BAD means failure to open() /dev/video0 in the case of CEU. vivi works fine.
>
> Morimoto-san and/or Guennadi, do you see the same thing?
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-17 10:43 ` Guennadi Liakhovetski
@ 2009-04-20 7:14 ` Magnus Damm
2009-04-20 7:22 ` Guennadi Liakhovetski
0 siblings, 1 reply; 46+ messages in thread
From: Magnus Damm @ 2009-04-20 7:14 UTC (permalink / raw)
To: Guennadi Liakhovetski
Cc: Linux Media Mailing List, Robert Jarzmik, Kuninori Morimoto
On Fri, Apr 17, 2009 at 7:43 PM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> On Fri, 17 Apr 2009, Magnus Damm wrote:
>> On Fri, Apr 17, 2009 at 4:51 PM, Guennadi Liakhovetski
>> <g.liakhovetski@gmx.de> wrote:
>> > On Fri, 17 Apr 2009, Magnus Damm wrote:
>> >> On Wed, Apr 15, 2009 at 9:17 PM, Guennadi Liakhovetski
>> >> <g.liakhovetski@gmx.de> wrote:
>> >> > This patch series is a preparation for the v4l2-subdev conversion. Please,
>> >> > review and test. My current patch-stack in the form of a
>> >> > (manually-created) quilt-series is at
>> >> > http://www.open-technology.de/download/20090415/ based on linux-next
>> >> > history branch, commit ID in 0000-base file. Don't be surprised, that
>> >> > patch-set also contains a few not directly related patches.
>> >>
>> >> Testing on Migo-R board with 2.6.30-rc2-git-something and the
>> >> following cherry-picked patches:
>> >>
>> >> 0007-driver-core-fix-driver_match_device.patch
>> >> 0033-soc-camera-host-driver-cleanup.patch
>> >> 0034-soc-camera-remove-an-extra-device-generation-from-s.patch
>> >> 0035-soc-camera-simplify-register-access-routines-in-mul.patch
>> >> and part of 0036 (avoiding rejects, ap325 seems broken btw)
>> >
>> > Have I broken it or is it unrelated?
>>
>> 2.6.30-rc seems broken on Migo-R. A quick check suggests the following:
>
> Ok, before we come to Migo-R, what is with ap325? Have I broken it with
> this my series or is it a different problem?
Not sure. I used 2.6.30-rc but I guess your patches are aimed at linux-next.
>> V4L/DVB (10141): OK
>> V4L/DVB (10672): BAD
>> V4L/DVB (11024): BAD
>
> These seem to be pretty random snapshots... Are they all on Linus' master
> or on next or on v4l-dvb? You did pick up the
>
> 0007-driver-core-fix-driver_match_device.patch
Yeah, I tried that one. I'm not sure what was the problem, but it's gone now.
Today I've tested the following on top of linux-2.6 (stable 2.6.30-rc)
d91dfbb41bb2e9bdbfbd2cc7078ed7436eab027a
0033-soc-camera-host-driver-cleanup.patch
0034-soc-camera-remove-an-extra-device-generation-from-s.patch
0035-soc-camera-simplify-register-access-routines-in-mul.patch
So far OK.
However, applying 0036- or v2 from the mailing list results in rejects
(probably because linux-next vs linux-2.6 differences) but the files
should not affect Migo-R.
So with 0036 or v2 applied it builds ok for Migo-R, but I can't open
/dev/video0 for some reason. Reverting the patch and only using
0033->0035 above results in ok /dev/video0 opening.
What are your dependencies?
I'll try out your 20090415/series on top of the matching linux-next for now.
/ magnus
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-20 7:14 ` Magnus Damm
@ 2009-04-20 7:22 ` Guennadi Liakhovetski
2009-04-20 8:00 ` Magnus Damm
0 siblings, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-20 7:22 UTC (permalink / raw)
To: Magnus Damm; +Cc: Linux Media Mailing List, Robert Jarzmik, Kuninori Morimoto
On Mon, 20 Apr 2009, Magnus Damm wrote:
> On Fri, Apr 17, 2009 at 7:43 PM, Guennadi Liakhovetski
> <g.liakhovetski@gmx.de> wrote:
> > On Fri, 17 Apr 2009, Magnus Damm wrote:
> >> On Fri, Apr 17, 2009 at 4:51 PM, Guennadi Liakhovetski
> >> <g.liakhovetski@gmx.de> wrote:
> >> > On Fri, 17 Apr 2009, Magnus Damm wrote:
> >> >> On Wed, Apr 15, 2009 at 9:17 PM, Guennadi Liakhovetski
> >> >> <g.liakhovetski@gmx.de> wrote:
> >> >> > This patch series is a preparation for the v4l2-subdev conversion. Please,
> >> >> > review and test. My current patch-stack in the form of a
> >> >> > (manually-created) quilt-series is at
> >> >> > http://www.open-technology.de/download/20090415/ based on linux-next
> >> >> > history branch, commit ID in 0000-base file. Don't be surprised, that
> >> >> > patch-set also contains a few not directly related patches.
> >> >>
> >> >> Testing on Migo-R board with 2.6.30-rc2-git-something and the
> >> >> following cherry-picked patches:
> >> >>
> >> >> 0007-driver-core-fix-driver_match_device.patch
> >> >> 0033-soc-camera-host-driver-cleanup.patch
> >> >> 0034-soc-camera-remove-an-extra-device-generation-from-s.patch
> >> >> 0035-soc-camera-simplify-register-access-routines-in-mul.patch
> >> >> and part of 0036 (avoiding rejects, ap325 seems broken btw)
> >> >
> >> > Have I broken it or is it unrelated?
> >>
> >> 2.6.30-rc seems broken on Migo-R. A quick check suggests the following:
> >
> > Ok, before we come to Migo-R, what is with ap325? Have I broken it with
> > this my series or is it a different problem?
>
> Not sure. I used 2.6.30-rc but I guess your patches are aimed at linux-next.
>
> >> V4L/DVB (10141): OK
> >> V4L/DVB (10672): BAD
> >> V4L/DVB (11024): BAD
> >
> > These seem to be pretty random snapshots... Are they all on Linus' master
> > or on next or on v4l-dvb? You did pick up the
> >
> > 0007-driver-core-fix-driver_match_device.patch
>
> Yeah, I tried that one. I'm not sure what was the problem, but it's gone now.
>
> Today I've tested the following on top of linux-2.6 (stable 2.6.30-rc)
> d91dfbb41bb2e9bdbfbd2cc7078ed7436eab027a
>
> 0033-soc-camera-host-driver-cleanup.patch
> 0034-soc-camera-remove-an-extra-device-generation-from-s.patch
> 0035-soc-camera-simplify-register-access-routines-in-mul.patch
>
> So far OK.
> However, applying 0036- or v2 from the mailing list results in rejects
> (probably because linux-next vs linux-2.6 differences) but the files
> should not affect Migo-R.
>
> So with 0036 or v2 applied it builds ok for Migo-R, but I can't open
> /dev/video0 for some reason. Reverting the patch and only using
> 0033->0035 above results in ok /dev/video0 opening.
Did you have video drivers build in or as modules? If modules - in which
order did you load them? Unfortunately, at the moment it might be
important:-( What's in dmesg after loading all drivers?
> What are your dependencies?
>
> I'll try out your 20090415/series on top of the matching linux-next for now.
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-20 7:22 ` Guennadi Liakhovetski
@ 2009-04-20 8:00 ` Magnus Damm
2009-04-20 8:14 ` Guennadi Liakhovetski
0 siblings, 1 reply; 46+ messages in thread
From: Magnus Damm @ 2009-04-20 8:00 UTC (permalink / raw)
To: Guennadi Liakhovetski
Cc: Linux Media Mailing List, Robert Jarzmik, Kuninori Morimoto
On Mon, Apr 20, 2009 at 4:22 PM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> On Mon, 20 Apr 2009, Magnus Damm wrote:
>> On Fri, Apr 17, 2009 at 7:43 PM, Guennadi Liakhovetski
>> <g.liakhovetski@gmx.de> wrote:
>> > On Fri, 17 Apr 2009, Magnus Damm wrote:
>> >> On Fri, Apr 17, 2009 at 4:51 PM, Guennadi Liakhovetski
>> >> <g.liakhovetski@gmx.de> wrote:
>> >> > On Fri, 17 Apr 2009, Magnus Damm wrote:
>> >> >> On Wed, Apr 15, 2009 at 9:17 PM, Guennadi Liakhovetski
>> >> >> <g.liakhovetski@gmx.de> wrote:
>> >> >> > This patch series is a preparation for the v4l2-subdev conversion. Please,
>> >> >> > review and test. My current patch-stack in the form of a
>> >> >> > (manually-created) quilt-series is at
>> >> >> > http://www.open-technology.de/download/20090415/ based on linux-next
>> >> >> > history branch, commit ID in 0000-base file. Don't be surprised, that
>> >> >> > patch-set also contains a few not directly related patches.
>> Today I've tested the following on top of linux-2.6 (stable 2.6.30-rc)
>> d91dfbb41bb2e9bdbfbd2cc7078ed7436eab027a
>>
>> 0033-soc-camera-host-driver-cleanup.patch
>> 0034-soc-camera-remove-an-extra-device-generation-from-s.patch
>> 0035-soc-camera-simplify-register-access-routines-in-mul.patch
>>
>> So far OK.
>> However, applying 0036- or v2 from the mailing list results in rejects
>> (probably because linux-next vs linux-2.6 differences) but the files
>> should not affect Migo-R.
>>
>> So with 0036 or v2 applied it builds ok for Migo-R, but I can't open
>> /dev/video0 for some reason. Reverting the patch and only using
>> 0033->0035 above results in ok /dev/video0 opening.
>
> Did you have video drivers build in or as modules? If modules - in which
> order did you load them? Unfortunately, at the moment it might be
> important:-( What's in dmesg after loading all drivers?
They are compiled-in. No modules.
>> What are your dependencies?
>>
>> I'll try out your 20090415/series on top of the matching linux-next for now.
So linux-next fa169db2b277ebafa466d625ed2d16b2d2a4bc82 with
20090415/series applies without any rejects and compiles just fine for
Migo-R. However, during runtime I experience the same problem as with
2.6.30-rc plus 0033->0035 + 0036 or v2:
/ # /mplayer -flip -vf mirror -quiet tv://
MPlayer dev-SVN-rUNKNOWN-4.2-SH4-LINUX_v0701 (C) 2000-2008 MPlayer Team
Playing tv://.
TV file format detected.
Selected driver: v4l2
name: Video 4 Linux 2 input
author: Martin Olschewski <olschewski@zpr.uni-koeln.de>
comment: first try, more to come ;-)
v4l2: unable to open '/dev/video0': No such device or address
v4l2: ioctl set mute failed: Bad file descriptor
v4l2: 0 frames successfully processed, 0 frames dropped.
Exiting... (End of file)
/ #
Removing 0036 unbreaks the code and mplayer/capture.c works as expected.
I also tried out v2 of your soc-camera-platform patch but it still
does not work.
Can you please test on your Migo-R board? I'd be happy to assist you
in setting up your environment.
/ magnus
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-20 8:00 ` Magnus Damm
@ 2009-04-20 8:14 ` Guennadi Liakhovetski
2009-04-20 8:54 ` Magnus Damm
0 siblings, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-20 8:14 UTC (permalink / raw)
To: Magnus Damm; +Cc: Linux Media Mailing List, Robert Jarzmik, Kuninori Morimoto
On Mon, 20 Apr 2009, Magnus Damm wrote:
> So linux-next fa169db2b277ebafa466d625ed2d16b2d2a4bc82 with
> 20090415/series applies without any rejects and compiles just fine for
> Migo-R. However, during runtime I experience the same problem as with
> 2.6.30-rc plus 0033->0035 + 0036 or v2:
>
> / # /mplayer -flip -vf mirror -quiet tv://
> MPlayer dev-SVN-rUNKNOWN-4.2-SH4-LINUX_v0701 (C) 2000-2008 MPlayer Team
>
> Playing tv://.
> TV file format detected.
> Selected driver: v4l2
> name: Video 4 Linux 2 input
> author: Martin Olschewski <olschewski@zpr.uni-koeln.de>
> comment: first try, more to come ;-)
> v4l2: unable to open '/dev/video0': No such device or address
> v4l2: ioctl set mute failed: Bad file descriptor
> v4l2: 0 frames successfully processed, 0 frames dropped.
>
>
> Exiting... (End of file)
> / #
>
> Removing 0036 unbreaks the code and mplayer/capture.c works as expected.
>
> I also tried out v2 of your soc-camera-platform patch but it still
> does not work.
>
> Can you please test on your Migo-R board? I'd be happy to assist you
> in setting up your environment.
I did test it and it worked - exactly as you say - with the entire patch
stack + v2 of "soc-camera: convert to platform device," the only
difference that I can see so far, is that I used modules. So, you can
either look in dmesg for driver initialisation whether ov772x and tw9910
have found theit i2c chips, or just wait until I test a monolitic build
myself. It can be problematic if the i2c-host driver initialises too
late... If you want to test a modular build it would be enough to just
have sh_mobile_ceu_camera.ko as a module, the rest can stay built in.
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-20 8:14 ` Guennadi Liakhovetski
@ 2009-04-20 8:54 ` Magnus Damm
2009-04-20 13:50 ` v4l2-subdev " Guennadi Liakhovetski
0 siblings, 1 reply; 46+ messages in thread
From: Magnus Damm @ 2009-04-20 8:54 UTC (permalink / raw)
To: Guennadi Liakhovetski
Cc: Linux Media Mailing List, Robert Jarzmik, Kuninori Morimoto
On Mon, Apr 20, 2009 at 5:14 PM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> On Mon, 20 Apr 2009, Magnus Damm wrote:
>> Can you please test on your Migo-R board? I'd be happy to assist you
>> in setting up your environment.
>
> I did test it and it worked - exactly as you say - with the entire patch
> stack + v2 of "soc-camera: convert to platform device," the only
> difference that I can see so far, is that I used modules. So, you can
> either look in dmesg for driver initialisation whether ov772x and tw9910
> have found theit i2c chips, or just wait until I test a monolitic build
> myself. It can be problematic if the i2c-host driver initialises too
> late... If you want to test a modular build it would be enough to just
> have sh_mobile_ceu_camera.ko as a module, the rest can stay built in.
I prefer to wait then. Please consider the built-in case broken.
Usually I get some output similar to this during boot:
camera 0-0: SuperH Mobile CEU driver attached to camera 0
camera 0-0: ov7725 Product ID 77:21 Manufacturer ID 7f:a2
camera 0-0: SuperH Mobile CEU driver detached from camera 0
But with the "convert to platform device" patch appied I see nothing like that.
The migor_defconfig should give you the static non-module
configuration that is broken.
Cheers,
/ magnus
^ permalink raw reply [flat|nested] 46+ messages in thread
* v4l2-subdev Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-20 8:54 ` Magnus Damm
@ 2009-04-20 13:50 ` Guennadi Liakhovetski
2009-04-20 14:04 ` Mark Brown
0 siblings, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-20 13:50 UTC (permalink / raw)
To: Magnus Damm
Cc: Linux Media Mailing List, Robert Jarzmik, Kuninori Morimoto,
linux-i2c, Greg KH, Mauro Carvalho Chehab
On Mon, 20 Apr 2009, Magnus Damm wrote:
> On Mon, Apr 20, 2009 at 5:14 PM, Guennadi Liakhovetski
> <g.liakhovetski@gmx.de> wrote:
> > On Mon, 20 Apr 2009, Magnus Damm wrote:
> >> Can you please test on your Migo-R board? I'd be happy to assist you
> >> in setting up your environment.
> >
> > I did test it and it worked - exactly as you say - with the entire patch
> > stack + v2 of "soc-camera: convert to platform device," the only
> > difference that I can see so far, is that I used modules. So, you can
> > either look in dmesg for driver initialisation whether ov772x and tw9910
> > have found theit i2c chips, or just wait until I test a monolitic build
> > myself. It can be problematic if the i2c-host driver initialises too
> > late... If you want to test a modular build it would be enough to just
> > have sh_mobile_ceu_camera.ko as a module, the rest can stay built in.
>
> I prefer to wait then. Please consider the built-in case broken.
>
> Usually I get some output similar to this during boot:
>
> camera 0-0: SuperH Mobile CEU driver attached to camera 0
> camera 0-0: ov7725 Product ID 77:21 Manufacturer ID 7f:a2
> camera 0-0: SuperH Mobile CEU driver detached from camera 0
>
> But with the "convert to platform device" patch appied I see nothing like that.
>
> The migor_defconfig should give you the static non-module
> configuration that is broken.
Ok, static build is indeed broken. The reason is the wrong initialisation
order. First, internally we have to link camera host drivers after camera
device drivers, that's easy. But unfortunately that alone doesn't help.
The second problem is that i2c is linked after media, or, maybe rather
media is linked before i2c. Currently in drivers/Makefile "media" is on
the same line as "base" and "block", way before IDE, ATA, SCSI, firewire,
mtd, spi, usb, input... Is there a reason for that? Mauro, would anything
break if we move it down right after i2c? Another hackish interim solution
would be to replace module_init with subsys_init in i2c-sh_mobile.c like
some other i2c adapters do (including MXC, PXA). That's certainly easier,
but then we'd also have to modify i2c-imx, later maybe i2c-at91.c...
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: v4l2-subdev Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-20 13:50 ` v4l2-subdev " Guennadi Liakhovetski
@ 2009-04-20 14:04 ` Mark Brown
2009-04-20 14:18 ` Guennadi Liakhovetski
0 siblings, 1 reply; 46+ messages in thread
From: Mark Brown @ 2009-04-20 14:04 UTC (permalink / raw)
To: Guennadi Liakhovetski
Cc: Magnus Damm, Linux Media Mailing List, Robert Jarzmik,
Kuninori Morimoto, linux-i2c, Greg KH, Mauro Carvalho Chehab
On Mon, Apr 20, 2009 at 03:50:44PM +0200, Guennadi Liakhovetski wrote:
> break if we move it down right after i2c? Another hackish interim solution
> would be to replace module_init with subsys_init in i2c-sh_mobile.c like
> some other i2c adapters do (including MXC, PXA). That's certainly easier,
> but then we'd also have to modify i2c-imx, later maybe i2c-at91.c...
That'd be sensible long term anyway - voltage and current regulators are
often I2C devices and they need to be initialised very early in order to
be available for general use.
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: v4l2-subdev Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-20 14:04 ` Mark Brown
@ 2009-04-20 14:18 ` Guennadi Liakhovetski
2009-04-20 14:31 ` Mark Brown
0 siblings, 1 reply; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-20 14:18 UTC (permalink / raw)
To: Mark Brown
Cc: Magnus Damm, Linux Media Mailing List, Robert Jarzmik,
Kuninori Morimoto, linux-i2c, Greg KH, Mauro Carvalho Chehab
On Mon, 20 Apr 2009, Mark Brown wrote:
> On Mon, Apr 20, 2009 at 03:50:44PM +0200, Guennadi Liakhovetski wrote:
>
> > break if we move it down right after i2c? Another hackish interim solution
> > would be to replace module_init with subsys_init in i2c-sh_mobile.c like
> > some other i2c adapters do (including MXC, PXA). That's certainly easier,
> > but then we'd also have to modify i2c-imx, later maybe i2c-at91.c...
>
> That'd be sensible long term anyway - voltage and current regulators are
> often I2C devices and they need to be initialised very early in order to
> be available for general use.
If there are other requirements to have i2c initialise early we can well
move it up the chain. I think it would be preferable to modifying each i2c
host adapter driver to use subsys_init().
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: v4l2-subdev Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-20 14:18 ` Guennadi Liakhovetski
@ 2009-04-20 14:31 ` Mark Brown
0 siblings, 0 replies; 46+ messages in thread
From: Mark Brown @ 2009-04-20 14:31 UTC (permalink / raw)
To: Guennadi Liakhovetski
Cc: Magnus Damm, Linux Media Mailing List, Robert Jarzmik,
Kuninori Morimoto, linux-i2c, Greg KH, Mauro Carvalho Chehab
On Mon, Apr 20, 2009 at 04:18:41PM +0200, Guennadi Liakhovetski wrote:
> If there are other requirements to have i2c initialise early we can well
> move it up the chain. I think it would be preferable to modifying each i2c
> host adapter driver to use subsys_init().
IIRC there are other ordering constraints on I2C in general that cause
problems there in non-embedded cases but I might be misremembering.
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-17 10:31 ` Magnus Damm
2009-04-17 10:43 ` Guennadi Liakhovetski
@ 2009-04-20 0:12 ` Kuninori Morimoto
2009-04-20 7:03 ` Magnus Damm
1 sibling, 1 reply; 46+ messages in thread
From: Kuninori Morimoto @ 2009-04-20 0:12 UTC (permalink / raw)
To: Magnus Damm
Cc: Guennadi Liakhovetski, Linux Media Mailing List, Robert Jarzmik
Hi Magnus
> >> > http://www.open-technology.de/download/20090415/ based on linux-next
> >> > history branch, commit ID in 0000-base file. Don't be surprised, that
> >> > patch-set also contains a few not directly related patches.
> >>
> >> Testing on Migo-R board with 2.6.30-rc2-git-something and the
> >> following cherry-picked patches:
> >>
> >> 0007-driver-core-fix-driver_match_device.patch
> >> 0033-soc-camera-host-driver-cleanup.patch
> >> 0034-soc-camera-remove-an-extra-device-generation-from-s.patch
> >> 0035-soc-camera-simplify-register-access-routines-in-mul.patch
> >> and part of 0036 (avoiding rejects, ap325 seems broken btw)
> >
> > Have I broken it or is it unrelated?
I don't know about current 2.6.30-rc2 git.
But when I used 2.6.30-rc1, It doesn't work either.
The reason was soc_camera_bus_type doesn't has "match" function.
please check 49b420a13ff95b449947181190b08367348e3e1b
And please see
http://marc.info/?t=123245859800006&r=1&w=2
I send patch to this problem.
2009/03/31
[PATCH] soc_camera: Add soc_camera_match function
And please check this patch.
This patch needed on ov772x, but may be rc2 already have it.
06/09: ov772x: wrong pointer for soc_camera_link is modified
http://linuxtv.org/hg/~gliakhovetski/v4l-dvb?cmd=changeset;node=157893ad8d0b
Best regards
--
Kuninori Morimoto
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 0/5] soc-camera: convert to platform device
2009-04-20 0:12 ` Kuninori Morimoto
@ 2009-04-20 7:03 ` Magnus Damm
0 siblings, 0 replies; 46+ messages in thread
From: Magnus Damm @ 2009-04-20 7:03 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Guennadi Liakhovetski, Linux Media Mailing List, Robert Jarzmik
Hi Morimoto-san,
On Mon, Apr 20, 2009 at 9:12 AM, Kuninori Morimoto
<morimoto.kuninori@renesas.com> wrote:
>
> Hi Magnus
>
>> >> > http://www.open-technology.de/download/20090415/ based on linux-next
>> >> > history branch, commit ID in 0000-base file. Don't be surprised, that
>> >> > patch-set also contains a few not directly related patches.
>> >>
>> >> Testing on Migo-R board with 2.6.30-rc2-git-something and the
>> >> following cherry-picked patches:
>> >>
>> >> 0007-driver-core-fix-driver_match_device.patch
>> >> 0033-soc-camera-host-driver-cleanup.patch
>> >> 0034-soc-camera-remove-an-extra-device-generation-from-s.patch
>> >> 0035-soc-camera-simplify-register-access-routines-in-mul.patch
>> >> and part of 0036 (avoiding rejects, ap325 seems broken btw)
>> >
>> > Have I broken it or is it unrelated?
>
> I don't know about current 2.6.30-rc2 git.
> But when I used 2.6.30-rc1, It doesn't work either.
Thanks for your suggestions. I've updated my tree after the weekend
and linux-2.6 git
d91dfbb41bb2e9bdbfbd2cc7078ed7436eab027a is working just fine.
So 2.6.30-rc seems ok on Migo-R at least. A good first step. =)
/ magnus
^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH 5/5 v2] soc-camera: Convert to a platform driver
2009-04-17 7:40 ` Magnus Damm
2009-04-17 7:51 ` Guennadi Liakhovetski
@ 2009-04-17 18:38 ` Guennadi Liakhovetski
2009-04-19 20:01 ` Robert Jarzmik
2009-04-20 9:45 ` Darius Augulis
1 sibling, 2 replies; 46+ messages in thread
From: Guennadi Liakhovetski @ 2009-04-17 18:38 UTC (permalink / raw)
To: Magnus Damm; +Cc: Linux Media Mailing List, Robert Jarzmik, Darius Augulis
Convert soc-camera core to a platform driver. With this approach I2C
devices are no longer statically registered in platform code, instead they
are registered dynamically by the soc-camera core, when a match with a
host driver is found. With this patch all platforms and all soc-camera
device drivers are converted too. This is a preparatory step for the
v4l-subdev conversion.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
Changes since v1: addressed Robert's wishes:-), even compile-tested for
mioa701! Fixed sh_mobile_ceu / migor and tested (still only blindly, I'll
come to the mplayer thing some time...) - it turned out to be a great
test-case - caught a couple of driver and soc-camera core bugs.
Darius, would be nice if you could test this patch series too (see
archives). Unfortunately, I cannot seem to find a suitable i.MX1 platform
code for your camera driver, so, you'd have to convert it yourself. It
isn't very difficult though - just look at other examples, e.g., mx3.
arch/arm/mach-mx3/pcm037.c | 25 ++-
arch/arm/mach-pxa/em-x270.c | 21 ++-
arch/arm/mach-pxa/mioa701.c | 19 +-
arch/arm/mach-pxa/pcm990-baseboard.c | 52 +++-
arch/sh/boards/board-ap325rxa.c | 55 +++--
arch/sh/boards/mach-migor/setup.c | 77 ++++--
drivers/media/video/mt9m001.c | 113 ++++-----
drivers/media/video/mt9m111.c | 152 ++++++------
drivers/media/video/mt9t031.c | 113 ++++-----
drivers/media/video/mt9v022.c | 118 +++++-----
drivers/media/video/mx3_camera.c | 27 ++-
drivers/media/video/ov772x.c | 153 +++++++-----
drivers/media/video/pxa_camera.c | 27 ++-
drivers/media/video/sh_mobile_ceu_camera.c | 13 +-
drivers/media/video/soc_camera.c | 371 +++++++++++++++-------------
drivers/media/video/soc_camera_platform.c | 112 +++++----
drivers/media/video/tw9910.c | 106 +++++----
include/media/soc_camera.h | 30 ++-
include/media/soc_camera_platform.h | 5 +-
19 files changed, 894 insertions(+), 695 deletions(-)
diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c
index 6bfd29a..00ce1eb 100644
--- a/arch/arm/mach-mx3/pcm037.c
+++ b/arch/arm/mach-mx3/pcm037.c
@@ -241,9 +241,17 @@ static int pcm037_camera_power(struct device *dev, int on)
return 0;
}
+static struct i2c_board_info pcm037_i2c_2_devices[] = {
+ {
+ I2C_BOARD_INFO("mt9t031", 0x5d),
+ },
+};
+
static struct soc_camera_link iclink = {
- .bus_id = 0, /* Must match with the camera ID */
- .power = pcm037_camera_power,
+ .bus_id = 0, /* Must match with the camera ID */
+ .power = pcm037_camera_power,
+ .board_info = &pcm037_i2c_2_devices[0],
+ .i2c_adapter_id = 2,
};
static struct i2c_board_info pcm037_i2c_devices[] = {
@@ -256,9 +264,10 @@ static struct i2c_board_info pcm037_i2c_devices[] = {
}
};
-static struct i2c_board_info pcm037_i2c_2_devices[] = {
- {
- I2C_BOARD_INFO("mt9t031", 0x5d),
+static struct platform_device pcm037_camera = {
+ .name = "soc-camera-pdrv",
+ .id = 0,
+ .dev = {
.platform_data = &iclink,
},
};
@@ -338,6 +347,9 @@ static struct platform_device *devices[] __initdata = {
&pcm037_flash,
&pcm037_eth,
&pcm037_sram_device,
+#if defined(CONFIG_I2C_IMX) || defined(CONFIG_I2C_IMX_MODULE)
+ &pcm037_camera,
+#endif
};
static struct ipu_platform_data mx3_ipu_data = {
@@ -395,9 +407,6 @@ static void __init mxc_board_init(void)
i2c_register_board_info(1, pcm037_i2c_devices,
ARRAY_SIZE(pcm037_i2c_devices));
- i2c_register_board_info(2, pcm037_i2c_2_devices,
- ARRAY_SIZE(pcm037_i2c_2_devices));
-
mxc_register_device(&mxc_i2c_device1, &pcm037_i2c_1_data);
mxc_register_device(&mxc_i2c_device2, &pcm037_i2c_2_data);
#endif
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 920dfb8..d4eb0c7 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -847,14 +847,23 @@ static int em_x270_sensor_power(struct device *dev, int on)
return 0;
}
-static struct soc_camera_link iclink = {
- .bus_id = 0,
- .power = em_x270_sensor_power,
-};
-
static struct i2c_board_info em_x270_i2c_cam_info[] = {
{
I2C_BOARD_INFO("mt9m111", 0x48),
+ },
+};
+
+static struct soc_camera_link iclink = {
+ .bus_id = 0,
+ .power = em_x270_sensor_power,
+ .board_info = &em_x270_i2c_cam_info[0],
+ .i2c_adapter_id = 0,
+};
+
+static struct platform_device em_x270_camera = {
+ .name = "soc-camera-pdrv",
+ .id = -1,
+ .dev = {
.platform_data = &iclink,
},
};
@@ -866,8 +875,8 @@ static struct i2c_pxa_platform_data em_x270_i2c_info = {
static void __init em_x270_init_camera(void)
{
pxa_set_i2c_info(&em_x270_i2c_info);
- i2c_register_board_info(0, ARRAY_AND_SIZE(em_x270_i2c_cam_info));
pxa_set_camera_info(&em_x270_camera_platform_data);
+ platform_device_register(&em_x270_camera);
}
#else
static inline void em_x270_init_camera(void) {}
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index 97c93a7..204263d 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -724,19 +724,21 @@ struct pxacamera_platform_data mioa701_pxacamera_platform_data = {
.mclk_10khz = 5000,
};
-static struct soc_camera_link iclink = {
- .bus_id = 0, /* Must match id in pxa27x_device_camera in device.c */
-};
-
-/* Board I2C devices. */
+/*
+ * Board I2C devices
+ */
static struct i2c_board_info __initdata mioa701_i2c_devices[] = {
{
- /* Must initialize before the camera(s) */
I2C_BOARD_INFO("mt9m111", 0x5d),
- .platform_data = &iclink,
},
};
+static struct soc_camera_link iclink = {
+ .bus_id = 0, /* Match id in pxa27x_device_camera in device.c */
+ .board_info = &mioa701_i2c_devices[0],
+ .i2c_adapter_id = 0,
+};
+
struct i2c_pxa_platform_data i2c_pdata = {
.fast_mode = 1,
};
@@ -768,6 +770,7 @@ MIO_PARENT_DEV(mio_wm9713_codec, "wm9713-codec", &pxa2xx_ac97.dev, NULL)
MIO_SIMPLE_DEV(mioa701_sound, "mioa701-wm9713", NULL)
MIO_SIMPLE_DEV(mioa701_board, "mioa701-board", NULL)
MIO_SIMPLE_DEV(gpio_vbus, "gpio-vbus", &gpio_vbus_data);
+MIO_SIMPLE_DEV(mioa701_camera, "soc-camera-pdrv",&iclink)
static struct platform_device *devices[] __initdata = {
&mioa701_gpio_keys,
@@ -780,6 +783,7 @@ static struct platform_device *devices[] __initdata = {
&power_dev,
&strataflash,
&gpio_vbus,
+ &mioa701_camera,
&mioa701_board,
};
@@ -825,7 +829,6 @@ static void __init mioa701_machine_init(void)
pxa_set_i2c_info(&i2c_pdata);
pxa_set_camera_info(&mioa701_pxacamera_platform_data);
- i2c_register_board_info(0, ARRAY_AND_SIZE(mioa701_i2c_devices));
}
static void mioa701_machine_exit(void)
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 9ce1ef2..619b90e 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -427,25 +427,54 @@ static void pcm990_camera_free_bus(struct soc_camera_link *link)
gpio_bus_switch = -EINVAL;
}
-static struct soc_camera_link iclink = {
- .bus_id = 0, /* Must match with the camera ID above */
- .query_bus_param = pcm990_camera_query_bus_param,
- .set_bus_param = pcm990_camera_set_bus_param,
- .free_bus = pcm990_camera_free_bus,
-};
-
/* Board I2C devices. */
static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
{
/* Must initialize before the camera(s) */
I2C_BOARD_INFO("pca9536", 0x41),
.platform_data = &pca9536_data,
- }, {
+ },
+};
+
+static struct i2c_board_info __initdata pcm990_camera_i2c[] = {
+ {
I2C_BOARD_INFO("mt9v022", 0x48),
- .platform_data = &iclink, /* With extender */
}, {
I2C_BOARD_INFO("mt9m001", 0x5d),
- .platform_data = &iclink, /* With extender */
+ },
+};
+
+static struct soc_camera_link iclink[] = {
+ {
+ .bus_id = 0, /* Must match with the camera ID */
+ .board_info = &pcm990_camera_i2c[0],
+ .i2c_adapter_id = 0,
+ .query_bus_param = pcm990_camera_query_bus_param,
+ .set_bus_param = pcm990_camera_set_bus_param,
+ .free_bus = pcm990_camera_free_bus,
+ }, {
+ .bus_id = 0, /* Must match with the camera ID */
+ .board_info = &pcm990_camera_i2c[1],
+ .i2c_adapter_id = 0,
+ .query_bus_param = pcm990_camera_query_bus_param,
+ .set_bus_param = pcm990_camera_set_bus_param,
+ .free_bus = pcm990_camera_free_bus,
+ },
+};
+
+static struct platform_device pcm990_camera[] = {
+ {
+ .name = "soc-camera-pdrv",
+ .id = 0,
+ .dev = {
+ .platform_data = &iclink[0],
+ },
+ }, {
+ .name = "soc-camera-pdrv",
+ .id = 1,
+ .dev = {
+ .platform_data = &iclink[1],
+ },
},
};
#endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */
@@ -501,6 +530,9 @@ void __init pcm990_baseboard_init(void)
pxa_set_camera_info(&pcm990_pxacamera_platform_data);
i2c_register_board_info(0, ARRAY_AND_SIZE(pcm990_i2c_devices));
+
+ platform_device_register(&pcm990_camera[0]);
+ platform_device_register(&pcm990_camera[1]);
#endif
printk(KERN_INFO "PCM-990 Evaluation baseboard initialized\n");
diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c
index e27655b..37c9139 100644
--- a/arch/sh/boards/board-ap325rxa.c
+++ b/arch/sh/boards/board-ap325rxa.c
@@ -228,12 +228,6 @@ static struct platform_device lcdc_device = {
},
};
-static void camera_power(int val)
-{
- gpio_set_value(GPIO_PTZ5, val); /* RST_CAM/RSTB */
- mdelay(10);
-}
-
#ifdef CONFIG_I2C
static unsigned char camera_ncm03j_magic[] =
{
@@ -255,23 +249,28 @@ static unsigned char camera_ncm03j_magic[] =
0x63, 0xD4, 0x64, 0xEA, 0xD6, 0x0F,
};
-static int camera_set_capture(struct soc_camera_platform_info *info,
- int enable)
+static int ap325rxa_camera_power(struct device *dev, int on)
{
- struct i2c_adapter *a = i2c_get_adapter(0);
+ gpio_set_value(GPIO_PTZ5, on); /* RST_CAM/RSTB */
+ mdelay(10);
+ return 0;
+}
+
+static int ap325rxa_camera_set_capture(struct soc_camera_platform_info *info,
+ int enable)
+{
+ struct i2c_adapter *a = i2c_get_adapter(info->link.i2c_adapter_id);
struct i2c_msg msg;
int ret = 0;
int i;
- camera_power(0);
if (!enable)
- return 0; /* no disable for now */
+ return ap325rxa_camera_power(NULL, 0); /* no disable for now */
- camera_power(1);
for (i = 0; i < ARRAY_SIZE(camera_ncm03j_magic); i += 2) {
u_int8_t buf[8];
- msg.addr = 0x6e;
+ msg.addr = info->link.board_info->addr;
msg.buf = buf;
msg.len = 2;
msg.flags = 0;
@@ -285,8 +284,11 @@ static int camera_set_capture(struct soc_camera_platform_info *info,
return ret;
}
+static struct i2c_board_info __initdata ap325rxa_camera_i2c = {
+ I2C_BOARD_INFO("soc_camera_platform", 0x6e),
+};
+
static struct soc_camera_platform_info camera_info = {
- .iface = 0,
.format_name = "UYVY",
.format_depth = 16,
.format = {
@@ -296,22 +298,29 @@ static struct soc_camera_platform_info camera_info = {
.height = 480,
},
.bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
- SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
- .set_capture = camera_set_capture,
+ SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
+ .set_capture = ap325rxa_camera_set_capture,
+ .link = {
+ .bus_id = 0,
+ .board_info = &ap325rxa_camera_i2c,
+ .i2c_adapter_id = 0,
+ .power = ap325rxa_camera_power,
+ },
};
-static struct platform_device camera_device = {
- .name = "soc_camera_platform",
- .dev = {
- .platform_data = &camera_info,
+static struct platform_device ap325rxa_camera = {
+ .name = "soc-camera-pdrv",
+ .id = -1,
+ .dev = {
+ .platform_data = &camera_info.link,
},
};
#endif /* CONFIG_I2C */
static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
.flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
- SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER |
- SOCAM_DATAWIDTH_8,
+ SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH |
+ SOCAM_MASTER | SOCAM_DATAWIDTH_8,
};
static struct resource ceu_resources[] = {
@@ -360,7 +369,7 @@ static struct platform_device *ap325rxa_devices[] __initdata = {
&lcdc_device,
&ceu_device,
#ifdef CONFIG_I2C
- &camera_device,
+ &ap325rxa_camera,
#endif
&nand_flash_device,
&sdcard_cn3_device,
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index 4fd6a72..b8cb246 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -383,21 +383,6 @@ static struct platform_device migor_ceu_device = {
},
};
-static struct ov772x_camera_info ov7725_info = {
- .buswidth = SOCAM_DATAWIDTH_8,
- .link = {
- .power = ov7725_power,
- },
-};
-
-static struct tw9910_video_info tw9910_info = {
- .buswidth = SOCAM_DATAWIDTH_8,
- .mpout = TW9910_MPO_FIELD,
- .link = {
- .power = tw9910_power,
- }
-};
-
struct spi_gpio_platform_data sdcard_cn9_platform_data = {
.sck = GPIO_PTD0,
.mosi = GPIO_PTD1,
@@ -412,16 +397,6 @@ static struct platform_device sdcard_cn9_device = {
},
};
-static struct platform_device *migor_devices[] __initdata = {
- &smc91x_eth_device,
- &sh_keysc_device,
- &migor_lcdc_device,
- &migor_ceu_device,
- &migor_nor_flash_device,
- &migor_nand_flash_device,
- &sdcard_cn9_device,
-};
-
static struct i2c_board_info migor_i2c_devices[] = {
{
I2C_BOARD_INFO("rs5c372b", 0x32),
@@ -430,16 +405,64 @@ static struct i2c_board_info migor_i2c_devices[] = {
I2C_BOARD_INFO("migor_ts", 0x51),
.irq = 38, /* IRQ6 */
},
+};
+
+static struct i2c_board_info migor_camera_i2c[] = {
{
I2C_BOARD_INFO("ov772x", 0x21),
- .platform_data = &ov7725_info,
},
{
I2C_BOARD_INFO("tw9910", 0x45),
- .platform_data = &tw9910_info,
},
};
+static struct ov772x_camera_info ov7725_info = {
+ .buswidth = SOCAM_DATAWIDTH_8,
+ .link = {
+ .power = ov7725_power,
+ .board_info = &migor_camera_i2c[0],
+ .i2c_adapter_id = 0,
+ },
+};
+
+static struct tw9910_video_info tw9910_info = {
+ .buswidth = SOCAM_DATAWIDTH_8,
+ .mpout = TW9910_MPO_FIELD,
+ .link = {
+ .power = tw9910_power,
+ .board_info = &migor_camera_i2c[1],
+ .i2c_adapter_id = 0,
+ }
+};
+
+static struct platform_device migor_camera[] = {
+ {
+ .name = "soc-camera-pdrv",
+ .id = 0,
+ .dev = {
+ .platform_data = &ov7725_info.link,
+ },
+ }, {
+ .name = "soc-camera-pdrv",
+ .id = 1,
+ .dev = {
+ .platform_data = &tw9910_info.link,
+ },
+ },
+};
+
+static struct platform_device *migor_devices[] __initdata = {
+ &smc91x_eth_device,
+ &sh_keysc_device,
+ &migor_lcdc_device,
+ &migor_ceu_device,
+ &migor_nor_flash_device,
+ &migor_nand_flash_device,
+ &sdcard_cn9_device,
+ &migor_camera[0],
+ &migor_camera[1],
+};
+
static struct spi_board_info migor_spi_devices[] = {
{
.modalias = "mmc_spi",
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index 459c04c..b0f4ad5 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -69,8 +69,6 @@ static const struct soc_camera_data_format mt9m001_monochrome_formats[] = {
};
struct mt9m001 {
- struct i2c_client *client;
- struct soc_camera_device icd;
int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
unsigned char autoexposure;
};
@@ -111,11 +109,11 @@ static int reg_clear(struct i2c_client *client, const u8 reg,
static int mt9m001_init(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret;
- dev_dbg(icd->vdev->parent, "%s\n", __func__);
+ dev_dbg(&icd->dev, "%s\n", __func__);
if (icl->power) {
ret = icl->power(&client->dev, 1);
@@ -147,8 +145,8 @@ static int mt9m001_init(struct soc_camera_device *icd)
static int mt9m001_release(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
/* Disable the chip */
reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
@@ -161,7 +159,7 @@ static int mt9m001_release(struct soc_camera_device *icd)
static int mt9m001_start_capture(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
/* Switch to master "normal" mode */
if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0)
@@ -171,7 +169,7 @@ static int mt9m001_start_capture(struct soc_camera_device *icd)
static int mt9m001_stop_capture(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
/* Stop sensor readout */
if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0)
@@ -182,8 +180,7 @@ static int mt9m001_stop_capture(struct soc_camera_device *icd)
static int mt9m001_set_bus_param(struct soc_camera_device *icd,
unsigned long flags)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK;
/* Only one width bit may be set */
@@ -205,8 +202,7 @@ static int mt9m001_set_bus_param(struct soc_camera_device *icd,
static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
/* MT9M001 has all capture_format parameters fixed */
unsigned long flags = SOCAM_PCLK_SAMPLE_FALLING |
SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
@@ -223,8 +219,8 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
static int mt9m001_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
int ret;
const u16 hblank = 9, vblank = 25;
@@ -296,12 +292,13 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd,
static int mt9m001_get_chip_id(struct soc_camera_device *icd,
struct v4l2_dbg_chip_ident *id)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL;
- if (id->match.addr != mt9m001->client->addr)
+ if (id->match.addr != client->addr)
return -ENODEV;
id->ident = mt9m001->model;
@@ -314,7 +311,7 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd,
static int mt9m001_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
@@ -334,7 +331,7 @@ static int mt9m001_get_register(struct soc_camera_device *icd,
static int mt9m001_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
@@ -387,15 +384,11 @@ static const struct v4l2_queryctrl mt9m001_controls[] = {
}
};
-static int mt9m001_video_probe(struct soc_camera_device *);
-static void mt9m001_video_remove(struct soc_camera_device *);
static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *);
static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *);
static struct soc_camera_ops mt9m001_ops = {
.owner = THIS_MODULE,
- .probe = mt9m001_video_probe,
- .remove = mt9m001_video_remove,
.init = mt9m001_init,
.release = mt9m001_release,
.start_capture = mt9m001_start_capture,
@@ -418,8 +411,8 @@ static struct soc_camera_ops mt9m001_ops = {
static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
int data;
switch (ctrl->id) {
@@ -438,8 +431,8 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro
static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
const struct v4l2_queryctrl *qctrl;
int data;
@@ -531,11 +524,11 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
/* Interface active, can use i2c. If it fails, it can indeed mean, that
* this wasn't our capture interface, so, we wait for the right one */
-static int mt9m001_video_probe(struct soc_camera_device *icd)
+static int mt9m001_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
s32 data;
int ret;
unsigned long flags;
@@ -546,6 +539,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
return -ENODEV;
+ /* Switch master clock on */
+ ret = soc_camera_video_start(icd, &client->dev);
+ if (ret)
+ return ret;
+
/* Enable the chip */
data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
dev_dbg(&icd->dev, "write: %d\n", data);
@@ -553,6 +551,8 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
/* Read out the chip version register */
data = reg_read(client, MT9M001_CHIP_VERSION);
+ soc_camera_video_stop(icd);
+
/* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
switch (data) {
case 0x8411:
@@ -565,10 +565,9 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
icd->formats = mt9m001_monochrome_formats;
break;
default:
- ret = -ENODEV;
dev_err(&icd->dev,
"No MT9M001 chip detected, register read %x\n", data);
- goto ei2c;
+ return -ENODEV;
}
icd->num_formats = 0;
@@ -594,26 +593,17 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
data == 0x8431 ? "C12STM" : "C12ST");
- /* Now that we know the model, we can start video */
- ret = soc_camera_video_start(icd);
- if (ret)
- goto eisis;
-
return 0;
-
-eisis:
-ei2c:
- return ret;
}
static void mt9m001_video_remove(struct soc_camera_device *icd)
{
- struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
- struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
- dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr,
+ dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
icd->dev.parent, icd->vdev);
- soc_camera_video_stop(icd);
+ icd->ops = NULL;
if (icl->free_bus)
icl->free_bus(icl);
}
@@ -622,11 +612,17 @@ static int mt9m001_probe(struct i2c_client *client,
const struct i2c_device_id *did)
{
struct mt9m001 *mt9m001;
- struct soc_camera_device *icd;
+ struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct soc_camera_link *icl;
int ret;
+ if (!icd) {
+ dev_err(&client->dev, "MT9M001: missing soc-camera data!\n");
+ return -EINVAL;
+ }
+
+ icl = to_soc_camera_link(icd);
if (!icl) {
dev_err(&client->dev, "MT9M001 driver needs platform data\n");
return -EINVAL;
@@ -642,13 +638,10 @@ static int mt9m001_probe(struct i2c_client *client,
if (!mt9m001)
return -ENOMEM;
- mt9m001->client = client;
i2c_set_clientdata(client, mt9m001);
/* Second stage probe - when a capture adapter is there */
- icd = &mt9m001->icd;
icd->ops = &mt9m001_ops;
- icd->control = &client->dev;
icd->x_min = 20;
icd->y_min = 12;
icd->x_current = 20;
@@ -658,27 +651,27 @@ static int mt9m001_probe(struct i2c_client *client,
icd->height_min = 32;
icd->height_max = 1024;
icd->y_skip_top = 1;
- icd->iface = icl->bus_id;
/* Simulated autoexposure. If enabled, we calculate shutter width
* ourselves in the driver based on vertical blanking and frame width */
mt9m001->autoexposure = 1;
- ret = soc_camera_device_register(icd);
- if (ret)
- goto eisdr;
-
- return 0;
+ ret = mt9m001_video_probe(icd, client);
+ if (ret) {
+ i2c_set_clientdata(client, NULL);
+ kfree(mt9m001);
+ }
-eisdr:
- kfree(mt9m001);
return ret;
}
static int mt9m001_remove(struct i2c_client *client)
{
struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
- soc_camera_device_unregister(&mt9m001->icd);
+ mt9m001_video_remove(icd);
+ i2c_set_clientdata(client, NULL);
+ client->driver = NULL;
kfree(mt9m001);
return 0;
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
index fc5e2de..06f5f97 100644
--- a/drivers/media/video/mt9m111.c
+++ b/drivers/media/video/mt9m111.c
@@ -148,8 +148,6 @@ enum mt9m111_context {
};
struct mt9m111 {
- struct i2c_client *client;
- struct soc_camera_device icd;
int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */
enum mt9m111_context context;
struct v4l2_rect rect;
@@ -203,7 +201,7 @@ static int mt9m111_reg_write(struct i2c_client *client, const u16 reg,
ret = reg_page_map_set(client, reg);
if (!ret)
- ret = i2c_smbus_write_word_data(client, (reg & 0xff),
+ ret = i2c_smbus_write_word_data(client, reg & 0xff,
swab16(data));
dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
return ret;
@@ -232,7 +230,7 @@ static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg,
static int mt9m111_set_context(struct soc_camera_device *icd,
enum mt9m111_context ctxt)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B
| MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B
| MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B
@@ -249,8 +247,8 @@ static int mt9m111_set_context(struct soc_camera_device *icd,
static int mt9m111_setup_rect(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret, is_raw_format;
int width = rect->width;
int height = rect->height;
@@ -294,7 +292,7 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd,
static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int ret;
ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt);
@@ -315,7 +313,8 @@ static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd)
static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int val = 0;
if (mt9m111->swap_rgb_red_blue)
@@ -329,7 +328,8 @@ static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd)
static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int val = 0;
if (mt9m111->swap_rgb_red_blue)
@@ -343,7 +343,8 @@ static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd)
static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int val = 0;
if (mt9m111->swap_yuv_cb_cr)
@@ -356,9 +357,9 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
static int mt9m111_enable(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
if (icl->power) {
@@ -378,9 +379,9 @@ static int mt9m111_enable(struct soc_camera_device *icd)
static int mt9m111_disable(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE);
@@ -395,8 +396,8 @@ static int mt9m111_disable(struct soc_camera_device *icd)
static int mt9m111_reset(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret;
ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
@@ -424,8 +425,7 @@ static int mt9m111_stop_capture(struct soc_camera_device *icd)
static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
- struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |
SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
@@ -441,7 +441,8 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
static int mt9m111_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
@@ -456,7 +457,8 @@ static int mt9m111_set_crop(struct soc_camera_device *icd,
static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
switch (pixfmt) {
@@ -506,7 +508,8 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
static int mt9m111_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
struct v4l2_pix_format *pix = &f->fmt.pix;
struct v4l2_rect rect = {
.left = mt9m111->rect.left,
@@ -544,12 +547,13 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd,
static int mt9m111_get_chip_id(struct soc_camera_device *icd,
struct v4l2_dbg_chip_ident *id)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL;
- if (id->match.addr != mt9m111->client->addr)
+ if (id->match.addr != client->addr)
return -ENODEV;
id->ident = mt9m111->model;
@@ -562,8 +566,8 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd,
static int mt9m111_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int val;
- struct i2c_client *client = to_i2c_client(icd->control);
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
return -EINVAL;
@@ -583,7 +587,7 @@ static int mt9m111_get_register(struct soc_camera_device *icd,
static int mt9m111_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
return -EINVAL;
@@ -635,8 +639,6 @@ static const struct v4l2_queryctrl mt9m111_controls[] = {
}
};
-static int mt9m111_video_probe(struct soc_camera_device *);
-static void mt9m111_video_remove(struct soc_camera_device *);
static int mt9m111_get_control(struct soc_camera_device *,
struct v4l2_control *);
static int mt9m111_set_control(struct soc_camera_device *,
@@ -647,8 +649,6 @@ static int mt9m111_release(struct soc_camera_device *icd);
static struct soc_camera_ops mt9m111_ops = {
.owner = THIS_MODULE,
- .probe = mt9m111_video_probe,
- .remove = mt9m111_video_remove,
.init = mt9m111_init,
.resume = mt9m111_resume,
.release = mt9m111_release,
@@ -672,8 +672,8 @@ static struct soc_camera_ops mt9m111_ops = {
static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
if (mt9m111->context == HIGHPOWER) {
@@ -693,7 +693,7 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
static int mt9m111_get_global_gain(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int data;
data = reg_read(GLOBAL_GAIN);
@@ -705,7 +705,7 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd)
static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
u16 val;
if (gain > 63 * 2 * 2)
@@ -724,8 +724,8 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
if (on)
@@ -741,8 +741,8 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
if (on)
@@ -759,8 +759,8 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
static int mt9m111_get_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int data;
switch (ctrl->id) {
@@ -803,7 +803,8 @@ static int mt9m111_get_control(struct soc_camera_device *icd,
static int mt9m111_set_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
const struct v4l2_queryctrl *qctrl;
int ret;
@@ -841,7 +842,8 @@ static int mt9m111_set_control(struct soc_camera_device *icd,
static int mt9m111_restore_state(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
mt9m111_set_context(icd, mt9m111->context);
mt9m111_set_pixfmt(icd, mt9m111->pixfmt);
@@ -856,7 +858,8 @@ static int mt9m111_restore_state(struct soc_camera_device *icd)
static int mt9m111_resume(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret = 0;
if (mt9m111->powered) {
@@ -871,7 +874,8 @@ static int mt9m111_resume(struct soc_camera_device *icd)
static int mt9m111_init(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
int ret;
mt9m111->context = HIGHPOWER;
@@ -902,10 +906,10 @@ static int mt9m111_release(struct soc_camera_device *icd)
* Interface active, can use i2c. If it fails, it can indeed mean, that
* this wasn't our capture interface, so, we wait for the right one
*/
-static int mt9m111_video_probe(struct soc_camera_device *icd)
+static int mt9m111_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
s32 data;
int ret;
@@ -917,6 +921,11 @@ static int mt9m111_video_probe(struct soc_camera_device *icd)
to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
return -ENODEV;
+ /* Switch master clock on */
+ ret = soc_camera_video_start(icd, &client->dev);
+ if (ret)
+ goto evstart;
+
ret = mt9m111_enable(icd);
if (ret)
goto ei2c;
@@ -945,40 +954,42 @@ static int mt9m111_video_probe(struct soc_camera_device *icd)
dev_info(&icd->dev, "Detected a MT9M11x chip ID %x\n", data);
- ret = soc_camera_video_start(icd);
- if (ret)
- goto eisis;
-
mt9m111->autoexposure = 1;
mt9m111->autowhitebalance = 1;
mt9m111->swap_rgb_even_odd = 1;
mt9m111->swap_rgb_red_blue = 1;
- return 0;
-eisis:
ei2c:
+ soc_camera_video_stop(icd);
+evstart:
return ret;
}
static void mt9m111_video_remove(struct soc_camera_device *icd)
{
- struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
- dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m111->client->addr,
- mt9m111->icd.dev.parent, mt9m111->icd.vdev);
- soc_camera_video_stop(&mt9m111->icd);
+ dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
+ icd->dev.parent, icd->vdev);
+ icd->ops = NULL;
}
static int mt9m111_probe(struct i2c_client *client,
const struct i2c_device_id *did)
{
struct mt9m111 *mt9m111;
- struct soc_camera_device *icd;
+ struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct soc_camera_link *icl;
int ret;
+ if (!icd) {
+ dev_err(&client->dev, "MT9M11x: missing soc-camera data!\n");
+ return -EINVAL;
+ }
+
+ icl = to_soc_camera_link(icd);
if (!icl) {
dev_err(&client->dev, "MT9M11x driver needs platform data\n");
return -EINVAL;
@@ -994,13 +1005,10 @@ static int mt9m111_probe(struct i2c_client *client,
if (!mt9m111)
return -ENOMEM;
- mt9m111->client = client;
i2c_set_clientdata(client, mt9m111);
/* Second stage probe - when a capture adapter is there */
- icd = &mt9m111->icd;
icd->ops = &mt9m111_ops;
- icd->control = &client->dev;
icd->x_min = MT9M111_MIN_DARK_COLS;
icd->y_min = MT9M111_MIN_DARK_ROWS;
icd->x_current = icd->x_min;
@@ -1010,22 +1018,24 @@ static int mt9m111_probe(struct i2c_client *client,
icd->height_min = MT9M111_MIN_DARK_COLS;
icd->height_max = MT9M111_MAX_HEIGHT;
icd->y_skip_top = 0;
- icd->iface = icl->bus_id;
- ret = soc_camera_device_register(icd);
- if (ret)
- goto eisdr;
- return 0;
+ ret = mt9m111_video_probe(icd, client);
+ if (ret) {
+ i2c_set_clientdata(client, NULL);
+ kfree(mt9m111);
+ }
-eisdr:
- kfree(mt9m111);
return ret;
}
static int mt9m111_remove(struct i2c_client *client)
{
struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
- soc_camera_device_unregister(&mt9m111->icd);
+ struct soc_camera_device *icd = client->dev.platform_data;
+
+ mt9m111_video_remove(icd);
+ i2c_set_clientdata(client, NULL);
+ client->driver = NULL;
kfree(mt9m111);
return 0;
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
index f72aeb7..da09906 100644
--- a/drivers/media/video/mt9t031.c
+++ b/drivers/media/video/mt9t031.c
@@ -68,8 +68,6 @@ static const struct soc_camera_data_format mt9t031_colour_formats[] = {
};
struct mt9t031 {
- struct i2c_client *client;
- struct soc_camera_device icd;
int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */
unsigned char autoexposure;
u16 xskip;
@@ -138,8 +136,8 @@ static int get_shutter(struct i2c_client *client, u32 *data)
static int mt9t031_init(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret;
if (icl->power) {
@@ -166,8 +164,8 @@ static int mt9t031_init(struct soc_camera_device *icd)
static int mt9t031_release(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
/* Disable the chip */
reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
@@ -180,7 +178,7 @@ static int mt9t031_release(struct soc_camera_device *icd)
static int mt9t031_start_capture(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
/* Switch to master "normal" mode */
if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
@@ -190,7 +188,7 @@ static int mt9t031_start_capture(struct soc_camera_device *icd)
static int mt9t031_stop_capture(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
/* Stop sensor readout */
if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
@@ -201,7 +199,7 @@ static int mt9t031_stop_capture(struct soc_camera_device *icd)
static int mt9t031_set_bus_param(struct soc_camera_device *icd,
unsigned long flags)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
/* The caller should have queried our parameters, check anyway */
if (flags & ~MT9T031_BUS_PARAM)
@@ -217,8 +215,7 @@ static int mt9t031_set_bus_param(struct soc_camera_device *icd,
static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
- struct soc_camera_link *icl = mt9t031->client->dev.platform_data;
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM);
}
@@ -238,8 +235,8 @@ static void recalculate_limits(struct soc_camera_device *icd,
static int mt9t031_set_params(struct soc_camera_device *icd,
struct v4l2_rect *rect, u16 xskip, u16 yskip)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
int ret;
u16 xbin, ybin, width, height, left, top;
const u16 hblank = MT9T031_HORIZONTAL_BLANK,
@@ -336,7 +333,8 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
static int mt9t031_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
/* CROP - no change in scaling, or in limits */
return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip);
@@ -345,7 +343,8 @@ static int mt9t031_set_crop(struct soc_camera_device *icd,
static int mt9t031_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
int ret;
u16 xskip, yskip;
struct v4l2_rect rect = {
@@ -403,12 +402,13 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd,
static int mt9t031_get_chip_id(struct soc_camera_device *icd,
struct v4l2_dbg_chip_ident *id)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL;
- if (id->match.addr != mt9t031->client->addr)
+ if (id->match.addr != client->addr)
return -ENODEV;
id->ident = mt9t031->model;
@@ -421,7 +421,7 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd,
static int mt9t031_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
@@ -440,7 +440,7 @@ static int mt9t031_get_register(struct soc_camera_device *icd,
static int mt9t031_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
@@ -501,15 +501,11 @@ static const struct v4l2_queryctrl mt9t031_controls[] = {
}
};
-static int mt9t031_video_probe(struct soc_camera_device *);
-static void mt9t031_video_remove(struct soc_camera_device *);
static int mt9t031_get_control(struct soc_camera_device *, struct v4l2_control *);
static int mt9t031_set_control(struct soc_camera_device *, struct v4l2_control *);
static struct soc_camera_ops mt9t031_ops = {
.owner = THIS_MODULE,
- .probe = mt9t031_video_probe,
- .remove = mt9t031_video_remove,
.init = mt9t031_init,
.release = mt9t031_release,
.start_capture = mt9t031_start_capture,
@@ -532,8 +528,8 @@ static struct soc_camera_ops mt9t031_ops = {
static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
int data;
switch (ctrl->id) {
@@ -558,8 +554,8 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro
static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
const struct v4l2_queryctrl *qctrl;
int data;
@@ -665,10 +661,10 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
/* Interface active, can use i2c. If it fails, it can indeed mean, that
* this wasn't our capture interface, so, we wait for the right one */
-static int mt9t031_video_probe(struct soc_camera_device *icd)
+static int mt9t031_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
s32 data;
int ret;
@@ -678,6 +674,11 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
return -ENODEV;
+ /* Switch master clock on */
+ ret = soc_camera_video_start(icd, &client->dev);
+ if (ret)
+ return ret;
+
/* Enable the chip */
data = reg_write(client, MT9T031_CHIP_ENABLE, 1);
dev_dbg(&icd->dev, "write: %d\n", data);
@@ -685,6 +686,8 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
/* Read out the chip version register */
data = reg_read(client, MT9T031_CHIP_VERSION);
+ soc_camera_video_stop(icd);
+
switch (data) {
case 0x1621:
mt9t031->model = V4L2_IDENT_MT9T031;
@@ -692,44 +695,40 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats);
break;
default:
- ret = -ENODEV;
dev_err(&icd->dev,
"No MT9T031 chip detected, register read %x\n", data);
- goto ei2c;
+ return -ENODEV;
}
dev_info(&icd->dev, "Detected a MT9T031 chip ID %x\n", data);
- /* Now that we know the model, we can start video */
- ret = soc_camera_video_start(icd);
- if (ret)
- goto evstart;
-
return 0;
-
-evstart:
-ei2c:
- return ret;
}
static void mt9t031_video_remove(struct soc_camera_device *icd)
{
- struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
- dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9t031->client->addr,
+ dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
icd->dev.parent, icd->vdev);
- soc_camera_video_stop(icd);
+ icd->ops = NULL;
}
static int mt9t031_probe(struct i2c_client *client,
const struct i2c_device_id *did)
{
struct mt9t031 *mt9t031;
- struct soc_camera_device *icd;
+ struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct soc_camera_link *icl;
int ret;
+ if (!icd) {
+ dev_err(&client->dev, "MT9T031: missing soc-camera data!\n");
+ return -EINVAL;
+ }
+
+ icl = to_soc_camera_link(icd);
if (!icl) {
dev_err(&client->dev, "MT9T031 driver needs platform data\n");
return -EINVAL;
@@ -745,13 +744,10 @@ static int mt9t031_probe(struct i2c_client *client,
if (!mt9t031)
return -ENOMEM;
- mt9t031->client = client;
i2c_set_clientdata(client, mt9t031);
/* Second stage probe - when a capture adapter is there */
- icd = &mt9t031->icd;
icd->ops = &mt9t031_ops;
- icd->control = &client->dev;
icd->x_min = MT9T031_COLUMN_SKIP;
icd->y_min = MT9T031_ROW_SKIP;
icd->x_current = icd->x_min;
@@ -761,7 +757,6 @@ static int mt9t031_probe(struct i2c_client *client,
icd->height_min = MT9T031_MIN_HEIGHT;
icd->height_max = MT9T031_MAX_HEIGHT;
icd->y_skip_top = 0;
- icd->iface = icl->bus_id;
/* Simulated autoexposure. If enabled, we calculate shutter width
* ourselves in the driver based on vertical blanking and frame width */
mt9t031->autoexposure = 1;
@@ -769,24 +764,24 @@ static int mt9t031_probe(struct i2c_client *client,
mt9t031->xskip = 1;
mt9t031->yskip = 1;
- ret = soc_camera_device_register(icd);
- if (ret)
- goto eisdr;
-
- return 0;
+ ret = mt9t031_video_probe(icd, client);
+ if (ret) {
+ icd->ops = NULL;
+ i2c_set_clientdata(client, NULL);
+ kfree(mt9t031);
+ }
-eisdr:
- i2c_set_clientdata(client, NULL);
- kfree(mt9t031);
return ret;
}
static int mt9t031_remove(struct i2c_client *client)
{
struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
- soc_camera_device_unregister(&mt9t031->icd);
+ mt9t031_video_remove(icd);
i2c_set_clientdata(client, NULL);
+ client->driver = NULL;
kfree(mt9t031);
return 0;
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index be20d31..1683af1 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -85,8 +85,6 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = {
};
struct mt9v022 {
- struct i2c_client *client;
- struct soc_camera_device icd;
int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
u16 chip_control;
};
@@ -127,9 +125,9 @@ static int reg_clear(struct i2c_client *client, const u8 reg,
static int mt9v022_init(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
+ struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
int ret;
if (icl->power) {
@@ -173,19 +171,19 @@ static int mt9v022_init(struct soc_camera_device *icd)
static int mt9v022_release(struct soc_camera_device *icd)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
if (icl->power)
- icl->power(&mt9v022->client->dev, 0);
+ icl->power(&client->dev, 0);
return 0;
}
static int mt9v022_start_capture(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
/* Switch to master "normal" mode */
mt9v022->chip_control &= ~0x10;
if (reg_write(client, MT9V022_CHIP_CONTROL,
@@ -196,8 +194,8 @@ static int mt9v022_start_capture(struct soc_camera_device *icd)
static int mt9v022_stop_capture(struct soc_camera_device *icd)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
/* Switch to snapshot mode */
mt9v022->chip_control |= 0x10;
if (reg_write(client, MT9V022_CHIP_CONTROL,
@@ -209,9 +207,9 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd)
static int mt9v022_set_bus_param(struct soc_camera_device *icd,
unsigned long flags)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
int ret;
u16 pixclk = 0;
@@ -263,8 +261,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd,
static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
unsigned int width_flag;
if (icl->query_bus_param)
@@ -283,7 +280,7 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
static int mt9v022_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int ret;
/* Like in example app. Contradicts the datasheet though */
@@ -326,7 +323,8 @@ static int mt9v022_set_crop(struct soc_camera_device *icd,
static int mt9v022_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
struct v4l2_pix_format *pix = &f->fmt.pix;
struct v4l2_rect rect = {
.left = icd->x_current,
@@ -380,12 +378,13 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd,
static int mt9v022_get_chip_id(struct soc_camera_device *icd,
struct v4l2_dbg_chip_ident *id)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
return -EINVAL;
- if (id->match.addr != mt9v022->client->addr)
+ if (id->match.addr != client->addr)
return -ENODEV;
id->ident = mt9v022->model;
@@ -398,7 +397,7 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd,
static int mt9v022_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
@@ -418,7 +417,7 @@ static int mt9v022_get_register(struct soc_camera_device *icd,
static int mt9v022_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
return -EINVAL;
@@ -487,15 +486,11 @@ static const struct v4l2_queryctrl mt9v022_controls[] = {
}
};
-static int mt9v022_video_probe(struct soc_camera_device *);
-static void mt9v022_video_remove(struct soc_camera_device *);
static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *);
static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *);
static struct soc_camera_ops mt9v022_ops = {
.owner = THIS_MODULE,
- .probe = mt9v022_video_probe,
- .remove = mt9v022_video_remove,
.init = mt9v022_init,
.release = mt9v022_release,
.start_capture = mt9v022_start_capture,
@@ -519,7 +514,7 @@ static struct soc_camera_ops mt9v022_ops = {
static int mt9v022_get_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int data;
switch (ctrl->id) {
@@ -555,7 +550,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
int data;
- struct i2c_client *client = to_i2c_client(icd->control);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
const struct v4l2_queryctrl *qctrl;
qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
@@ -652,11 +647,11 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
/* Interface active, can use i2c. If it fails, it can indeed mean, that
* this wasn't our capture interface, so, we wait for the right one */
-static int mt9v022_video_probe(struct soc_camera_device *icd)
+static int mt9v022_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
{
- struct i2c_client *client = to_i2c_client(icd->control);
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
s32 data;
int ret;
unsigned long flags;
@@ -665,6 +660,11 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
return -ENODEV;
+ /* Switch master clock on */
+ ret = soc_camera_video_start(icd, &client->dev);
+ if (ret)
+ return ret;
+
/* Read out the chip version register */
data = reg_read(client, MT9V022_CHIP_VERSION);
@@ -684,6 +684,8 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
udelay(200);
if (reg_read(client, MT9V022_RESET)) {
dev_err(&icd->dev, "Resetting MT9V022 failed!\n");
+ if (ret > 0)
+ ret = -EIO;
goto ei2c;
}
@@ -700,7 +702,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
}
if (ret < 0)
- goto eisis;
+ goto ei2c;
icd->num_formats = 0;
@@ -722,29 +724,24 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
if (flags & SOCAM_DATAWIDTH_8)
icd->num_formats++;
- ret = soc_camera_video_start(icd);
- if (ret < 0)
- goto eisis;
-
dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n",
data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ?
"monochrome" : "colour");
- return 0;
-
-eisis:
ei2c:
+ soc_camera_video_stop(icd);
+
return ret;
}
static void mt9v022_video_remove(struct soc_camera_device *icd)
{
- struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
- struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
- dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr,
+ dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
icd->dev.parent, icd->vdev);
- soc_camera_video_stop(icd);
+ icd->ops = NULL;
if (icl->free_bus)
icl->free_bus(icl);
}
@@ -753,11 +750,17 @@ static int mt9v022_probe(struct i2c_client *client,
const struct i2c_device_id *did)
{
struct mt9v022 *mt9v022;
- struct soc_camera_device *icd;
+ struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
- struct soc_camera_link *icl = client->dev.platform_data;
+ struct soc_camera_link *icl;
int ret;
+ if (!icd) {
+ dev_err(&client->dev, "MT9V022: missing soc-camera data!\n");
+ return -EINVAL;
+ }
+
+ icl = to_soc_camera_link(icd);
if (!icl) {
dev_err(&client->dev, "MT9V022 driver needs platform data\n");
return -EINVAL;
@@ -774,12 +777,9 @@ static int mt9v022_probe(struct i2c_client *client,
return -ENOMEM;
mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
- mt9v022->client = client;
i2c_set_clientdata(client, mt9v022);
- icd = &mt9v022->icd;
icd->ops = &mt9v022_ops;
- icd->control = &client->dev;
icd->x_min = 1;
icd->y_min = 4;
icd->x_current = 1;
@@ -789,24 +789,24 @@ static int mt9v022_probe(struct i2c_client *client,
icd->height_min = 32;
icd->height_max = 480;
icd->y_skip_top = 1;
- icd->iface = icl->bus_id;
-
- ret = soc_camera_device_register(icd);
- if (ret)
- goto eisdr;
- return 0;
+ ret = mt9v022_video_probe(icd, client);
+ if (ret) {
+ i2c_set_clientdata(client, NULL);
+ kfree(mt9v022);
+ }
-eisdr:
- kfree(mt9v022);
return ret;
}
static int mt9v022_remove(struct i2c_client *client)
{
struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
- soc_camera_device_unregister(&mt9v022->icd);
+ mt9v022_video_remove(icd);
+ i2c_set_clientdata(client, NULL);
+ client->driver = NULL;
kfree(mt9v022);
return 0;
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
index cb13faa..ed752c5 100644
--- a/drivers/media/video/mx3_camera.c
+++ b/drivers/media/video/mx3_camera.c
@@ -502,18 +502,19 @@ static int mx3_camera_add_device(struct soc_camera_device *icd)
mx3_camera_activate(mx3_cam, icd);
ret = icd->ops->init(icd);
- if (ret < 0) {
- clk_disable(mx3_cam->clk);
+ if (ret < 0)
goto einit;
- }
mx3_cam->icd = icd;
+ dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n",
+ icd->devnum);
+
+ return 0;
+
einit:
+ clk_disable(mx3_cam->clk);
ebusy:
- if (!ret)
- dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n",
- icd->devnum);
return ret;
}
@@ -946,9 +947,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
camera_flags = icd->ops->query_bus_param(icd);
common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
+ dev_dbg(ici->dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n",
+ camera_flags, bus_flags, common_flags);
if (!common_flags) {
- dev_dbg(ici->dev, "no common flags: camera %lx, host %lx\n",
- camera_flags, bus_flags);
+ dev_dbg(ici->dev, "no common flags");
return -EINVAL;
}
@@ -1001,8 +1003,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
SOCAM_DATAWIDTH_4;
ret = icd->ops->set_bus_param(icd, common_flags);
- if (ret < 0)
+ if (ret < 0) {
+ dev_dbg(ici->dev, "camera set_bus_param(%lx) returned %d\n",
+ common_flags, ret);
return ret;
+ }
/*
* So far only gated clock mode is supported. Add a line
@@ -1130,8 +1135,9 @@ static int mx3_camera_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&mx3_cam->capture);
spin_lock_init(&mx3_cam->lock);
- base = ioremap(res->start, res->end - res->start + 1);
+ base = ioremap(res->start, resource_size(res));
if (!base) {
+ pr_err("Couldn't map %x@%x\n", resource_size(res), res->start);
err = -ENOMEM;
goto eioremap;
}
@@ -1218,3 +1224,4 @@ module_exit(mx3_camera_exit);
MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver");
MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" MX3_CAM_DRV_NAME);
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
index c0d9112..c90a918 100644
--- a/drivers/media/video/ov772x.c
+++ b/drivers/media/video/ov772x.c
@@ -399,8 +399,6 @@ struct ov772x_win_size {
struct ov772x_priv {
struct ov772x_camera_info *info;
- struct i2c_client *client;
- struct soc_camera_device icd;
const struct ov772x_color_format *fmt;
const struct ov772x_win_size *win;
int model;
@@ -619,53 +617,56 @@ static int ov772x_reset(struct i2c_client *client)
static int ov772x_init(struct soc_camera_device *icd)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret = 0;
- if (priv->info->link.power) {
- ret = priv->info->link.power(&priv->client->dev, 1);
+ if (icl->power) {
+ ret = icl->power(&client->dev, 1);
if (ret < 0)
return ret;
}
- if (priv->info->link.reset)
- ret = priv->info->link.reset(&priv->client->dev);
+ if (icl->reset)
+ ret = icl->reset(&client->dev);
return ret;
}
static int ov772x_release(struct soc_camera_device *icd)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret = 0;
- if (priv->info->link.power)
- ret = priv->info->link.power(&priv->client->dev, 0);
+ if (icl->power)
+ ret = icl->power(&client->dev, 0);
return ret;
}
static int ov772x_start_capture(struct soc_camera_device *icd)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
if (!priv->win || !priv->fmt) {
dev_err(&icd->dev, "norm or win select error\n");
return -EPERM;
}
- ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0);
+ ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0);
dev_dbg(&icd->dev,
- "format %s, win %s\n", priv->fmt->name, priv->win->name);
+ "format %s, win %s\n", priv->fmt->name, priv->win->name);
return 0;
}
static int ov772x_stop_capture(struct soc_camera_device *icd)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
- ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
return 0;
}
@@ -677,8 +678,9 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd,
static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
- struct soc_camera_link *icl = &priv->info->link;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
@@ -689,7 +691,8 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
static int ov772x_get_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
switch (ctrl->id) {
case V4L2_CID_VFLIP:
@@ -705,7 +708,8 @@ static int ov772x_get_control(struct soc_camera_device *icd,
static int ov772x_set_control(struct soc_camera_device *icd,
struct v4l2_control *ctrl)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
int ret = 0;
u8 val;
@@ -715,14 +719,14 @@ static int ov772x_set_control(struct soc_camera_device *icd,
priv->flag_vflip = ctrl->value;
if (priv->info->flags & OV772X_FLAG_VFLIP)
val ^= VFLIP_IMG;
- ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val);
+ ret = ov772x_mask_set(client, COM3, VFLIP_IMG, val);
break;
case V4L2_CID_HFLIP:
val = ctrl->value ? HFLIP_IMG : 0x00;
priv->flag_hflip = ctrl->value;
if (priv->info->flags & OV772X_FLAG_HFLIP)
val ^= HFLIP_IMG;
- ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val);
+ ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val);
break;
}
@@ -730,9 +734,10 @@ static int ov772x_set_control(struct soc_camera_device *icd,
}
static int ov772x_get_chip_id(struct soc_camera_device *icd,
- struct v4l2_dbg_chip_ident *id)
+ struct v4l2_dbg_chip_ident *id)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
id->ident = priv->model;
id->revision = 0;
@@ -744,14 +749,14 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd,
static int ov772x_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
- int ret;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ int ret;
reg->size = 1;
if (reg->reg > 0xff)
return -EINVAL;
- ret = i2c_smbus_read_byte_data(priv->client, reg->reg);
+ ret = i2c_smbus_read_byte_data(client, reg->reg);
if (ret < 0)
return ret;
@@ -763,13 +768,13 @@ static int ov772x_get_register(struct soc_camera_device *icd,
static int ov772x_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->reg > 0xff ||
reg->val > 0xff)
return -EINVAL;
- return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val);
+ return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
}
#endif
@@ -793,9 +798,11 @@ ov772x_select_win(u32 width, u32 height)
return win;
}
-static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
- u32 pixfmt)
+static int ov772x_set_params(struct soc_camera_device *icd,
+ u32 width, u32 height, u32 pixfmt)
{
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
int ret = -EINVAL;
u8 val;
int i;
@@ -810,6 +817,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
break;
}
}
+ dev_dbg(&icd->dev, "Using fmt %x #%d\n", pixfmt, i);
if (!priv->fmt)
goto ov772x_set_fmt_error;
@@ -821,7 +829,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
/*
* reset hardware
*/
- ov772x_reset(priv->client);
+ ov772x_reset(client);
/*
* Edge Ctrl
@@ -835,17 +843,17 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
* Remove it when manual mode.
*/
- ret = ov772x_mask_set(priv->client, DSPAUTO, EDGE_ACTRL, 0x00);
+ ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00);
if (ret < 0)
goto ov772x_set_fmt_error;
- ret = ov772x_mask_set(priv->client,
+ ret = ov772x_mask_set(client,
EDGE_TRSHLD, EDGE_THRESHOLD_MASK,
priv->info->edgectrl.threshold);
if (ret < 0)
goto ov772x_set_fmt_error;
- ret = ov772x_mask_set(priv->client,
+ ret = ov772x_mask_set(client,
EDGE_STRNGT, EDGE_STRENGTH_MASK,
priv->info->edgectrl.strength);
if (ret < 0)
@@ -857,13 +865,13 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
*
* set upper and lower limit
*/
- ret = ov772x_mask_set(priv->client,
+ ret = ov772x_mask_set(client,
EDGE_UPPER, EDGE_UPPER_MASK,
priv->info->edgectrl.upper);
if (ret < 0)
goto ov772x_set_fmt_error;
- ret = ov772x_mask_set(priv->client,
+ ret = ov772x_mask_set(client,
EDGE_LOWER, EDGE_LOWER_MASK,
priv->info->edgectrl.lower);
if (ret < 0)
@@ -873,7 +881,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
/*
* set size format
*/
- ret = ov772x_write_array(priv->client, priv->win->regs);
+ ret = ov772x_write_array(client, priv->win->regs);
if (ret < 0)
goto ov772x_set_fmt_error;
@@ -882,7 +890,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
*/
val = priv->fmt->dsp3;
if (val) {
- ret = ov772x_mask_set(priv->client,
+ ret = ov772x_mask_set(client,
DSP_CTRL3, UV_MASK, val);
if (ret < 0)
goto ov772x_set_fmt_error;
@@ -901,7 +909,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
if (priv->flag_hflip)
val ^= HFLIP_IMG;
- ret = ov772x_mask_set(priv->client,
+ ret = ov772x_mask_set(client,
COM3, SWAP_MASK | IMG_MASK, val);
if (ret < 0)
goto ov772x_set_fmt_error;
@@ -910,7 +918,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
* set COM7
*/
val = priv->win->com7_bit | priv->fmt->com7;
- ret = ov772x_mask_set(priv->client,
+ ret = ov772x_mask_set(client,
COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK),
val);
if (ret < 0)
@@ -920,7 +928,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
ov772x_set_fmt_error:
- ov772x_reset(priv->client);
+ ov772x_reset(client);
priv->win = NULL;
priv->fmt = NULL;
@@ -930,22 +938,22 @@ ov772x_set_fmt_error:
static int ov772x_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
if (!priv->fmt)
return -EINVAL;
- return ov772x_set_params(priv, rect->width, rect->height,
+ return ov772x_set_params(icd, rect->width, rect->height,
priv->fmt->fourcc);
}
static int ov772x_set_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
struct v4l2_pix_format *pix = &f->fmt.pix;
- return ov772x_set_params(priv, pix->width, pix->height,
+ return ov772x_set_params(icd, pix->width, pix->height,
pix->pixelformat);
}
@@ -967,11 +975,13 @@ static int ov772x_try_fmt(struct soc_camera_device *icd,
return 0;
}
-static int ov772x_video_probe(struct soc_camera_device *icd)
+static int ov772x_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
{
- struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
+ struct ov772x_priv *priv = i2c_get_clientdata(client);
u8 pid, ver;
const char *devname;
+ int ret;
/*
* We must have a parent by now. And it cannot be a wrong one.
@@ -993,11 +1003,16 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
icd->formats = ov772x_fmt_lists;
icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists);
+ /* Switch master clock on */
+ ret = soc_camera_video_start(icd, &client->dev);
+ if (ret)
+ return ret;
+
/*
* check and show product ID and manufacturer ID
*/
- pid = i2c_smbus_read_byte_data(priv->client, PID);
- ver = i2c_smbus_read_byte_data(priv->client, VER);
+ pid = i2c_smbus_read_byte_data(client, PID);
+ ver = i2c_smbus_read_byte_data(client, VER);
switch (VERSION(pid, ver)) {
case OV7720:
@@ -1011,7 +1026,8 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
default:
dev_err(&icd->dev,
"Product ID error %x:%x\n", pid, ver);
- return -ENODEV;
+ ret = -ENODEV;
+ goto ever;
}
dev_info(&icd->dev,
@@ -1019,21 +1035,22 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
devname,
pid,
ver,
- i2c_smbus_read_byte_data(priv->client, MIDH),
- i2c_smbus_read_byte_data(priv->client, MIDL));
+ i2c_smbus_read_byte_data(client, MIDH),
+ i2c_smbus_read_byte_data(client, MIDL));
+
+ soc_camera_video_stop(icd);
- return soc_camera_video_start(icd);
+ever:
+ return ret;
}
static void ov772x_video_remove(struct soc_camera_device *icd)
{
- soc_camera_video_stop(icd);
+ icd->ops = NULL;
}
static struct soc_camera_ops ov772x_ops = {
.owner = THIS_MODULE,
- .probe = ov772x_video_probe,
- .remove = ov772x_video_remove,
.init = ov772x_init,
.release = ov772x_release,
.start_capture = ov772x_start_capture,
@@ -1063,14 +1080,22 @@ static int ov772x_probe(struct i2c_client *client,
{
struct ov772x_priv *priv;
struct ov772x_camera_info *info;
- struct soc_camera_device *icd;
+ struct soc_camera_device *icd = client->dev.platform_data;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ struct soc_camera_link *icl;
int ret;
- info = client->dev.platform_data;
- if (!info)
+ if (!icd) {
+ dev_err(&client->dev, "MT9M001: missing soc-camera data!\n");
+ return -EINVAL;
+ }
+
+ icl = to_soc_camera_link(icd);
+ if (!icl)
return -EINVAL;
+ info = container_of(icl, struct ov772x_camera_info, link);
+
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_err(&adapter->dev,
"I2C-Adapter doesn't support "
@@ -1083,18 +1108,13 @@ static int ov772x_probe(struct i2c_client *client,
return -ENOMEM;
priv->info = info;
- priv->client = client;
i2c_set_clientdata(client, priv);
- icd = &priv->icd;
icd->ops = &ov772x_ops;
- icd->control = &client->dev;
icd->width_max = MAX_WIDTH;
icd->height_max = MAX_HEIGHT;
- icd->iface = priv->info->link.bus_id;
-
- ret = soc_camera_device_register(icd);
+ ret = ov772x_video_probe(icd, client);
if (ret) {
i2c_set_clientdata(client, NULL);
kfree(priv);
@@ -1106,8 +1126,9 @@ static int ov772x_probe(struct i2c_client *client,
static int ov772x_remove(struct i2c_client *client)
{
struct ov772x_priv *priv = i2c_get_clientdata(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
- soc_camera_device_unregister(&priv->icd);
+ ov772x_video_remove(icd);
i2c_set_clientdata(client, NULL);
kfree(priv);
return 0;
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
index 2da5eef..63964d0 100644
--- a/drivers/media/video/pxa_camera.c
+++ b/drivers/media/video/pxa_camera.c
@@ -841,7 +841,8 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q,
sizeof(struct pxa_buffer), icd);
}
-static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
+static u32 mclk_get_divisor(struct platform_device *pdev,
+ struct pxa_camera_dev *pcdev)
{
unsigned long mclk = pcdev->mclk;
u32 div;
@@ -853,7 +854,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
/* mclk <= ciclk / 4 (27.4.2) */
if (mclk > lcdclk / 4) {
mclk = lcdclk / 4;
- dev_warn(pcdev->soc_host.dev, "Limiting master clock to %lu\n", mclk);
+ dev_warn(&pdev->dev, "Limiting master clock to %lu\n", mclk);
}
/* We verify mclk != 0, so if anyone breaks it, here comes their Oops */
@@ -863,8 +864,8 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
pcdev->mclk = lcdclk / (2 * (div + 1));
- dev_dbg(pcdev->soc_host.dev, "LCD clock %luHz, target freq %luHz, "
- "divisor %u\n", lcdclk, mclk, div);
+ dev_dbg(&pdev->dev, "LCD clock %luHz, target freq %luHz, divisor %u\n",
+ lcdclk, mclk, div);
return div;
}
@@ -969,15 +970,20 @@ static int pxa_camera_add_device(struct soc_camera_device *icd)
goto ebusy;
}
- dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
- icd->devnum);
-
pxa_camera_activate(pcdev);
ret = icd->ops->init(icd);
+ if (ret < 0)
+ goto einit;
+
+ pcdev->icd = icd;
- if (!ret)
- pcdev->icd = icd;
+ dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
+ icd->devnum);
+ return 0;
+
+einit:
+ pxa_camera_deactivate(pcdev);
ebusy:
return ret;
}
@@ -1599,7 +1605,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
pcdev->mclk = 20000000;
}
- pcdev->mclk_divisor = mclk_get_divisor(pcdev);
+ pcdev->mclk_divisor = mclk_get_divisor(pdev, pcdev);
INIT_LIST_HEAD(&pcdev->capture);
spin_lock_init(&pcdev->lock);
@@ -1746,3 +1752,4 @@ module_exit(pxa_camera_exit);
MODULE_DESCRIPTION("PXA27x SoC Camera Host driver");
MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" PXA_CAM_DRV_NAME);
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
index d369e84..ac9b467 100644
--- a/drivers/media/video/sh_mobile_ceu_camera.c
+++ b/drivers/media/video/sh_mobile_ceu_camera.c
@@ -360,11 +360,13 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
"SuperH Mobile CEU driver attached to camera %d\n",
icd->devnum);
+ clk_enable(pcdev->clk);
+
ret = icd->ops->init(icd);
- if (ret)
+ if (ret) {
+ clk_disable(pcdev->clk);
goto err;
-
- clk_enable(pcdev->clk);
+ }
ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
while (ceu_read(pcdev, CSTSR) & 1)
@@ -398,10 +400,10 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
}
spin_unlock_irqrestore(&pcdev->lock, flags);
- clk_disable(pcdev->clk);
-
icd->ops->release(icd);
+ clk_disable(pcdev->clk);
+
dev_info(&icd->dev,
"SuperH Mobile CEU driver detached from camera %d\n",
icd->devnum);
@@ -948,3 +950,4 @@ module_exit(sh_mobile_ceu_exit);
MODULE_DESCRIPTION("SuperH Mobile CEU driver");
MODULE_AUTHOR("Magnus Damm");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sh_mobile_ceu");
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 03a6c29..22f544c 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -16,19 +16,21 @@
* published by the Free Software Foundation.
*/
-#include <linux/module.h>
-#include <linux/init.h>
#include <linux/device.h>
-#include <linux/list.h>
#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/list.h>
#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/vmalloc.h>
+#include <media/soc_camera.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-dev.h>
#include <media/videobuf-core.h>
-#include <media/soc_camera.h>
/* Default to VGA resolution */
#define DEFAULT_WIDTH 640
@@ -36,7 +38,7 @@
static LIST_HEAD(hosts);
static LIST_HEAD(devices);
-static DEFINE_MUTEX(list_lock);
+static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */
const struct soc_camera_data_format *soc_camera_format_by_fourcc(
struct soc_camera_device *icd, unsigned int fourcc)
@@ -207,6 +209,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv,
return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK);
}
+/* Always entered with .video_lock held */
static int soc_camera_init_user_formats(struct soc_camera_device *icd)
{
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
@@ -255,9 +258,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd)
return 0;
}
+/* Always entered with .video_lock held */
static void soc_camera_free_user_formats(struct soc_camera_device *icd)
{
+ icd->current_fmt = NULL;
vfree(icd->user_formats);
+ icd->user_formats = NULL;
}
/* Called with .vb_lock held */
@@ -308,10 +314,6 @@ static int soc_camera_open(struct file *file)
struct soc_camera_file *icf;
int ret;
- icf = vmalloc(sizeof(*icf));
- if (!icf)
- return -ENOMEM;
-
/*
* It is safe to dereference these pointers now as long as a user has
* the video device open - we are protected by the held cdev reference.
@@ -319,8 +321,17 @@ static int soc_camera_open(struct file *file)
vdev = video_devdata(file);
icd = container_of(vdev->parent, struct soc_camera_device, dev);
+
+ if (!icd->ops)
+ /* No device driver attached */
+ return -ENODEV;
+
ici = to_soc_camera_host(icd->dev.parent);
+ icf = vmalloc(sizeof(*icf));
+ if (!icf)
+ return -ENOMEM;
+
if (!try_module_get(icd->ops->owner)) {
dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
ret = -EINVAL;
@@ -333,7 +344,7 @@ static int soc_camera_open(struct file *file)
goto emgi;
}
- /* Protect against icd->remove() until we module_get() both drivers. */
+ /* Protect against icd->ops->remove() until we module_get() both drivers. */
mutex_lock(&icd->video_lock);
icf->icd = icd;
@@ -348,11 +359,18 @@ static int soc_camera_open(struct file *file)
.width = icd->width,
.height = icd->height,
.field = icd->field,
- .pixelformat = icd->current_fmt->fourcc,
- .colorspace = icd->current_fmt->colorspace,
},
};
+ ret = soc_camera_init_user_formats(icd);
+ if (ret < 0)
+ goto eiufmt;
+
+ dev_dbg(&icd->dev, "Using fmt %x\n", icd->current_fmt->fourcc);
+
+ f.fmt.pix.pixelformat = icd->current_fmt->fourcc;
+ f.fmt.pix.colorspace = icd->current_fmt->colorspace;
+
ret = ici->ops->add(icd);
if (ret < 0) {
dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
@@ -381,6 +399,8 @@ static int soc_camera_open(struct file *file)
esfmt:
ici->ops->remove(icd);
eiciadd:
+ soc_camera_free_user_formats(icd);
+eiufmt:
icd->use_count--;
mutex_unlock(&icd->video_lock);
module_put(ici->ops->owner);
@@ -400,8 +420,10 @@ static int soc_camera_close(struct file *file)
mutex_lock(&icd->video_lock);
icd->use_count--;
- if (!icd->use_count)
+ if (!icd->use_count) {
ici->ops->remove(icd);
+ soc_camera_free_user_formats(icd);
+ }
mutex_unlock(&icd->video_lock);
@@ -762,29 +784,6 @@ static int soc_camera_s_register(struct file *file, void *fh,
}
#endif
-static int device_register_link(struct soc_camera_device *icd)
-{
- int ret = dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum);
-
- if (!ret)
- ret = device_register(&icd->dev);
-
- if (ret < 0) {
- /* Prevent calling device_unregister() */
- icd->dev.parent = NULL;
- dev_err(&icd->dev, "Cannot register device: %d\n", ret);
- /* Even if probe() was unsuccessful for all registered drivers,
- * device_register() returns 0, and we add the link, just to
- * document this camera's control device */
- } else if (icd->control)
- /* Have to sysfs_remove_link() before device_unregister()? */
- if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj,
- "control"))
- dev_warn(&icd->dev,
- "Failed creating the control symlink\n");
- return ret;
-}
-
/* So far this function cannot fail */
static void scan_add_host(struct soc_camera_host *ici)
{
@@ -794,103 +793,78 @@ static void scan_add_host(struct soc_camera_host *ici)
list_for_each_entry(icd, &devices, list) {
if (icd->iface == ici->nr) {
+ int ret;
icd->dev.parent = ici->dev;
- device_register_link(icd);
- }
- }
-
- mutex_unlock(&list_lock);
-}
-
-/* return: 0 if no match found or a match found and
- * device_register() successful, error code otherwise */
-static int scan_add_device(struct soc_camera_device *icd)
-{
- struct soc_camera_host *ici;
- int ret = 0;
-
- mutex_lock(&list_lock);
-
- list_add_tail(&icd->list, &devices);
-
- /* Watch out for class_for_each_device / class_find_device API by
- * Dave Young <hidave.darkstar@gmail.com> */
- list_for_each_entry(ici, &hosts, list) {
- if (icd->iface == ici->nr) {
- ret = 1;
- icd->dev.parent = ici->dev;
- break;
+ dev_set_name(&icd->dev, "%u-%u", icd->iface,
+ icd->devnum);
+ ret = device_register(&icd->dev);
+ if (ret < 0) {
+ icd->dev.parent = NULL;
+ dev_err(&icd->dev,
+ "Cannot register device: %d\n", ret);
+ }
}
}
mutex_unlock(&list_lock);
-
- if (ret)
- ret = device_register_link(icd);
-
- return ret;
}
+static int video_dev_create(struct soc_camera_device *icd);
+/* Called during host-driver probe */
static int soc_camera_probe(struct device *dev)
{
struct soc_camera_device *icd = to_soc_camera_dev(dev);
- struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret;
+ struct i2c_client *client;
+ struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id);
- /*
- * Possible race scenario:
- * modprobe <camera-host-driver> triggers __func__
- * at this moment respective <camera-sensor-driver> gets rmmod'ed
- * to protect take module references.
- */
-
- if (!try_module_get(icd->ops->owner)) {
- dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
- ret = -EINVAL;
- goto emgd;
- }
-
- if (!try_module_get(ici->ops->owner)) {
- dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
- ret = -EINVAL;
- goto emgi;
+ if (!adap) {
+ ret = -ENODEV;
+ dev_err(dev, "Cannot get I2C adapter %d\n", icl->i2c_adapter_id);
+ goto ei2cga;
}
- mutex_lock(&icd->video_lock);
+ dev_info(dev, "Probing %s\n", dev_name(dev));
- /* We only call ->add() here to activate and probe the camera.
- * We shall ->remove() and deactivate it immediately afterwards. */
- ret = ici->ops->add(icd);
+ ret = video_dev_create(icd);
if (ret < 0)
- goto eiadd;
+ goto evdc;
- ret = icd->ops->probe(icd);
- if (ret >= 0) {
- const struct v4l2_queryctrl *qctrl;
+ client = i2c_new_device(adap, icl->board_info);
+ if (!client) {
+ ret = -ENOMEM;
+ goto ei2cnd;
+ }
- qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
- icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
- qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
- icd->exposure = qctrl ? qctrl->default_value :
- (unsigned short)~0;
+ /*
+ * We set icd drvdata at two locations - here and in
+ * soc_camera_video_start(). Depending on the module loading /
+ * initialisation order one of these locations will be entered first
+ */
+ /* Use to_i2c_client(dev) to recover the i2c client */
+ dev_set_drvdata(&icd->dev, &client->dev);
- ret = soc_camera_init_user_formats(icd);
- if (ret < 0)
- goto eiufmt;
+ /* Do we have to sysfs_remove_link() before device_unregister()? */
+ if (sysfs_create_link(&dev->kobj, &to_soc_camera_control(icd)->kobj,
+ "control"))
+ dev_warn(dev, "Failed creating the control symlink\n");
- icd->height = DEFAULT_HEIGHT;
- icd->width = DEFAULT_WIDTH;
- icd->field = V4L2_FIELD_ANY;
+ ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, icd->vdev->minor);
+ if (ret < 0) {
+ dev_err(&icd->dev, "video_register_device failed: %d\n", ret);
+ goto evidregd;
}
-eiufmt:
- ici->ops->remove(icd);
-eiadd:
- mutex_unlock(&icd->video_lock);
- module_put(ici->ops->owner);
-emgi:
- module_put(icd->ops->owner);
-emgd:
+ return 0;
+
+evidregd:
+ i2c_unregister_device(client);
+ei2cnd:
+ video_device_release(icd->vdev);
+evdc:
+ i2c_put_adapter(adap);
+ei2cga:
return ret;
}
@@ -899,11 +873,24 @@ emgd:
static int soc_camera_remove(struct device *dev)
{
struct soc_camera_device *icd = to_soc_camera_dev(dev);
+ struct video_device *vdev = icd->vdev;
- if (icd->ops->remove)
- icd->ops->remove(icd);
+ BUG_ON(!dev->parent);
- soc_camera_free_user_formats(icd);
+ if (vdev) {
+ mutex_lock(&icd->video_lock);
+ video_unregister_device(vdev);
+ icd->vdev = NULL;
+ mutex_unlock(&icd->video_lock);
+ }
+
+ if (to_soc_camera_control(icd)) {
+ struct i2c_client *client =
+ to_i2c_client(to_soc_camera_control(icd));
+ dev_set_drvdata(&icd->dev, NULL);
+ i2c_unregister_device(client);
+ i2c_put_adapter(client->adapter);
+ }
return 0;
}
@@ -998,10 +985,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
list_for_each_entry(icd, &devices, list) {
if (icd->dev.parent == ici->dev) {
+ /* The bus->remove will be called */
device_unregister(&icd->dev);
/* Not before device_unregister(), .remove
* needs parent to call ici->ops->remove() */
icd->dev.parent = NULL;
+
+ /* If the host module is loaded again, device_register()
+ * would complain "already initialised" */
memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj));
}
}
@@ -1013,26 +1004,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
EXPORT_SYMBOL(soc_camera_host_unregister);
/* Image capture device */
-int soc_camera_device_register(struct soc_camera_device *icd)
+static int soc_camera_device_register(struct soc_camera_device *icd)
{
struct soc_camera_device *ix;
int num = -1, i;
- if (!icd || !icd->ops ||
- !icd->ops->probe ||
- !icd->ops->init ||
- !icd->ops->release ||
- !icd->ops->start_capture ||
- !icd->ops->stop_capture ||
- !icd->ops->set_crop ||
- !icd->ops->set_fmt ||
- !icd->ops->try_fmt ||
- !icd->ops->query_bus_param ||
- !icd->ops->set_bus_param)
- return -EINVAL;
-
for (i = 0; i < 256 && num < 0; i++) {
num = i;
+ /* Check if this index is available on this interface */
list_for_each_entry(ix, &devices, list) {
if (ix->iface == icd->iface && ix->devnum == i) {
num = -1;
@@ -1054,21 +1033,15 @@ int soc_camera_device_register(struct soc_camera_device *icd)
icd->host_priv = NULL;
mutex_init(&icd->video_lock);
- return scan_add_device(icd);
+ list_add_tail(&icd->list, &devices);
+
+ return 0;
}
-EXPORT_SYMBOL(soc_camera_device_register);
-void soc_camera_device_unregister(struct soc_camera_device *icd)
+static void soc_camera_device_unregister(struct soc_camera_device *icd)
{
- mutex_lock(&list_lock);
list_del(&icd->list);
-
- /* The bus->remove will be eventually called */
- if (icd->dev.parent)
- device_unregister(&icd->dev);
- mutex_unlock(&list_lock);
}
-EXPORT_SYMBOL(soc_camera_device_unregister);
static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
.vidioc_querycap = soc_camera_querycap,
@@ -1099,22 +1072,13 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
#endif
};
-/*
- * Usually called from the struct soc_camera_ops .probe() method, i.e., from
- * soc_camera_probe() above with .video_lock held
- */
-int soc_camera_video_start(struct soc_camera_device *icd)
+static int video_dev_create(struct soc_camera_device *icd)
{
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
- int err = -ENOMEM;
- struct video_device *vdev;
+ struct video_device *vdev = video_device_alloc();
- if (!icd->dev.parent)
- return -ENODEV;
-
- vdev = video_device_alloc();
if (!vdev)
- goto evidallocd;
+ return -ENOMEM;
dev_dbg(ici->dev, "Allocated video_device %p\n", vdev);
strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
@@ -1125,40 +1089,103 @@ int soc_camera_video_start(struct soc_camera_device *icd)
vdev->ioctl_ops = &soc_camera_ioctl_ops;
vdev->release = video_device_release;
vdev->minor = -1;
- vdev->tvnorms = V4L2_STD_UNKNOWN,
+ vdev->tvnorms = V4L2_STD_UNKNOWN;
- err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
- if (err < 0) {
- dev_err(vdev->parent, "video_register_device failed\n");
- goto evidregd;
- }
icd->vdev = vdev;
return 0;
+}
-evidregd:
- video_device_release(vdev);
-evidallocd:
- return err;
+/*
+ * Usually called from the struct soc_camera_ops .probe() method, i.e., from
+ * soc_camera_probe() above with .video_lock held
+ */
+int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev)
+{
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+ const struct v4l2_queryctrl *qctrl;
+
+ if (!icd->dev.parent)
+ return -ENODEV;
+
+ if (!icd->ops ||
+ !icd->ops->init ||
+ !icd->ops->release ||
+ !icd->ops->start_capture ||
+ !icd->ops->stop_capture ||
+ !icd->ops->set_fmt ||
+ !icd->ops->try_fmt ||
+ !icd->ops->query_bus_param ||
+ !icd->ops->set_bus_param)
+ return -EINVAL;
+
+ /* See comment in soc_camera_probe() */
+ dev_set_drvdata(&icd->dev, dev);
+
+ qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
+ icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
+ qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
+ icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0;
+
+ return ici->ops->add(icd);
}
EXPORT_SYMBOL(soc_camera_video_start);
void soc_camera_video_stop(struct soc_camera_device *icd)
{
- struct video_device *vdev = icd->vdev;
+ struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
dev_dbg(&icd->dev, "%s\n", __func__);
- if (!icd->dev.parent || !vdev)
- return;
-
- mutex_lock(&icd->video_lock);
- video_unregister_device(vdev);
- icd->vdev = NULL;
- mutex_unlock(&icd->video_lock);
+ ici->ops->remove(icd);
}
EXPORT_SYMBOL(soc_camera_video_stop);
+static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
+{
+ struct soc_camera_link *icl = pdev->dev.platform_data;
+ struct soc_camera_device *icd;
+
+ if (!icl)
+ return -EINVAL;
+
+ icd = kzalloc(sizeof(*icd), GFP_KERNEL);
+ if (!icd)
+ return -ENOMEM;
+
+ icd->iface = icl->bus_id;
+ icl->board_info->platform_data = icd;
+ platform_set_drvdata(pdev, icd);
+ icd->dev.platform_data = icl;
+
+ return soc_camera_device_register(icd);
+}
+
+/* Only called on rmmod for each platform device, since they are not
+ * hot-pluggable. Now we know, that all our users - hosts and devices have
+ * been unloaded already */
+static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev)
+{
+ struct soc_camera_device *icd = platform_get_drvdata(pdev);
+
+ if (!icd)
+ return -EINVAL;
+
+ soc_camera_device_unregister(icd);
+
+ kfree(icd);
+
+ return 0;
+}
+
+static struct platform_driver soc_camera_pdrv = {
+ .remove = __exit_p(soc_camera_pdrv_remove),
+ .driver = {
+ .name = "soc-camera-pdrv",
+ .owner = THIS_MODULE,
+ },
+};
+
static int __init soc_camera_init(void)
{
int ret = bus_register(&soc_camera_bus_type);
@@ -1168,8 +1195,14 @@ static int __init soc_camera_init(void)
if (ret)
goto edrvr;
+ ret = platform_driver_probe(&soc_camera_pdrv, soc_camera_pdrv_probe);
+ if (ret)
+ goto epdr;
+
return 0;
+epdr:
+ driver_unregister(&ic_drv);
edrvr:
bus_unregister(&soc_camera_bus_type);
return ret;
@@ -1177,6 +1210,7 @@ edrvr:
static void __exit soc_camera_exit(void)
{
+ platform_driver_unregister(&soc_camera_pdrv);
driver_unregister(&ic_drv);
bus_unregister(&soc_camera_bus_type);
}
@@ -1187,3 +1221,4 @@ module_exit(soc_camera_exit);
MODULE_DESCRIPTION("Image capture bus driver");
MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:soc-camera-pdrv");
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c
index c486763..021f9f1 100644
--- a/drivers/media/video/soc_camera_platform.c
+++ b/drivers/media/video/soc_camera_platform.c
@@ -20,49 +20,52 @@
#include <media/soc_camera.h>
#include <media/soc_camera_platform.h>
+static const char drv_name[] = "soc_camera_platform";
+
struct soc_camera_platform_priv {
struct soc_camera_platform_info *info;
- struct soc_camera_device icd;
struct soc_camera_data_format format;
};
-static struct soc_camera_platform_info *
-soc_camera_platform_get_info(struct soc_camera_device *icd)
+static struct soc_camera_platform_info *i2c_to_info(struct i2c_client *client)
{
- struct soc_camera_platform_priv *priv;
- priv = container_of(icd, struct soc_camera_platform_priv, icd);
+ struct soc_camera_platform_priv *priv = i2c_get_clientdata(client);
return priv->info;
}
static int soc_camera_platform_init(struct soc_camera_device *icd)
{
- struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_platform_info *p = i2c_to_info(client);
- if (p->power)
- p->power(1);
+ if (p->link.power)
+ p->link.power(&client->dev, 1);
return 0;
}
static int soc_camera_platform_release(struct soc_camera_device *icd)
{
- struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_platform_info *p = i2c_to_info(client);
- if (p->power)
- p->power(0);
+ if (p->link.power)
+ p->link.power(&client->dev, 0);
return 0;
}
static int soc_camera_platform_start_capture(struct soc_camera_device *icd)
{
- struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_platform_info *p = i2c_to_info(client);
return p->set_capture(p, 1);
}
static int soc_camera_platform_stop_capture(struct soc_camera_device *icd)
{
- struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_platform_info *p = i2c_to_info(client);
return p->set_capture(p, 0);
}
@@ -75,7 +78,8 @@ static int soc_camera_platform_set_bus_param(struct soc_camera_device *icd,
static unsigned long
soc_camera_platform_query_bus_param(struct soc_camera_device *icd)
{
- struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_platform_info *p = i2c_to_info(client);
return p->bus_param;
}
@@ -94,7 +98,8 @@ static int soc_camera_platform_set_fmt(struct soc_camera_device *icd,
static int soc_camera_platform_try_fmt(struct soc_camera_device *icd,
struct v4l2_format *f)
{
- struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_platform_info *p = i2c_to_info(client);
struct v4l2_pix_format *pix = &f->fmt.pix;
pix->width = p->format.width;
@@ -102,31 +107,30 @@ static int soc_camera_platform_try_fmt(struct soc_camera_device *icd,
return 0;
}
-static int soc_camera_platform_video_probe(struct soc_camera_device *icd)
+static int soc_camera_platform_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
{
- struct soc_camera_platform_priv *priv;
- priv = container_of(icd, struct soc_camera_platform_priv, icd);
+ struct soc_camera_platform_priv *priv = i2c_get_clientdata(client);
+ struct soc_camera_platform_info *p = priv->info;
- priv->format.name = priv->info->format_name;
- priv->format.depth = priv->info->format_depth;
- priv->format.fourcc = priv->info->format.pixelformat;
- priv->format.colorspace = priv->info->format.colorspace;
+ priv->format.name = p->format_name;
+ priv->format.depth = p->format_depth;
+ priv->format.fourcc = p->format.pixelformat;
+ priv->format.colorspace = p->format.colorspace;
icd->formats = &priv->format;
icd->num_formats = 1;
- return soc_camera_video_start(icd);
+ return 0;
}
static void soc_camera_platform_video_remove(struct soc_camera_device *icd)
{
- soc_camera_video_stop(icd);
+ icd->ops = NULL;
}
static struct soc_camera_ops soc_camera_platform_ops = {
.owner = THIS_MODULE,
- .probe = soc_camera_platform_video_probe,
- .remove = soc_camera_platform_video_remove,
.init = soc_camera_platform_init,
.release = soc_camera_platform_release,
.start_capture = soc_camera_platform_start_capture,
@@ -138,66 +142,85 @@ static struct soc_camera_ops soc_camera_platform_ops = {
.query_bus_param = soc_camera_platform_query_bus_param,
};
-static int soc_camera_platform_probe(struct platform_device *pdev)
+static int soc_camera_platform_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
{
struct soc_camera_platform_priv *priv;
struct soc_camera_platform_info *p;
- struct soc_camera_device *icd;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct soc_camera_link *icl;
int ret;
- p = pdev->dev.platform_data;
- if (!p)
+ if (!icd) {
+ dev_err(&client->dev, "%s: missing soc-camera data!\n", drv_name);
return -EINVAL;
+ }
+
+ icl = dev_get_drvdata(&icd->dev);
+ if (!icl) {
+ dev_err(&client->dev, "%s driver needs platform data\n", drv_name);
+ return -EINVAL;
+ }
+
+ p = container_of(icl, struct soc_camera_platform_info, link);
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->info = p;
- platform_set_drvdata(pdev, priv);
+ i2c_set_clientdata(client, priv);
- icd = &priv->icd;
icd->ops = &soc_camera_platform_ops;
- icd->control = &pdev->dev;
icd->width_min = 0;
- icd->width_max = priv->info->format.width;
+ icd->width_max = p->format.width;
icd->height_min = 0;
- icd->height_max = priv->info->format.height;
+ icd->height_max = p->format.height;
icd->y_skip_top = 0;
- icd->iface = priv->info->iface;
- ret = soc_camera_device_register(icd);
- if (ret)
+ ret = soc_camera_platform_video_probe(icd, client);
+ if (ret) {
+ i2c_set_clientdata(client, NULL);
kfree(priv);
+ }
return ret;
}
-static int soc_camera_platform_remove(struct platform_device *pdev)
+static int soc_camera_platform_remove(struct i2c_client *client)
{
- struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev);
+ struct soc_camera_platform_priv *priv = i2c_get_clientdata(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
- soc_camera_device_unregister(&priv->icd);
+ soc_camera_platform_video_remove(icd);
+ i2c_set_clientdata(client, NULL);
kfree(priv);
return 0;
}
-static struct platform_driver soc_camera_platform_driver = {
+static const struct i2c_device_id soc_camera_platform_id[] = {
+ { "soc_camera_platform", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, soc_camera_platform_id);
+
+static struct i2c_driver soc_camera_platform_driver = {
.driver = {
.name = "soc_camera_platform",
},
.probe = soc_camera_platform_probe,
.remove = soc_camera_platform_remove,
+ .id_table = soc_camera_platform_id,
};
static int __init soc_camera_platform_module_init(void)
{
- return platform_driver_register(&soc_camera_platform_driver);
+ return i2c_add_driver(&soc_camera_platform_driver);
}
static void __exit soc_camera_platform_module_exit(void)
{
- platform_driver_unregister(&soc_camera_platform_driver);
+ i2c_del_driver(&soc_camera_platform_driver);
}
module_init(soc_camera_platform_module_init);
@@ -206,3 +229,4 @@ module_exit(soc_camera_platform_module_exit);
MODULE_DESCRIPTION("SoC Camera Platform driver");
MODULE_AUTHOR("Magnus Damm");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:soc_camera_platform");
diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c
index a399476..419e596 100644
--- a/drivers/media/video/tw9910.c
+++ b/drivers/media/video/tw9910.c
@@ -224,8 +224,6 @@ struct tw9910_hsync_ctrl {
struct tw9910_priv {
struct tw9910_video_info *info;
- struct i2c_client *client;
- struct soc_camera_device icd;
const struct tw9910_scale_ctrl *scale;
};
@@ -511,35 +509,38 @@ tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height)
*/
static int tw9910_init(struct soc_camera_device *icd)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret = 0;
- if (priv->info->link.power) {
- ret = priv->info->link.power(&priv->client->dev, 1);
+ if (icl->power) {
+ ret = icl->power(&client->dev, 1);
if (ret < 0)
return ret;
}
- if (priv->info->link.reset)
- ret = priv->info->link.reset(&priv->client->dev);
+ if (icl->reset)
+ ret = icl->reset(&client->dev);
return ret;
}
static int tw9910_release(struct soc_camera_device *icd)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
int ret = 0;
- if (priv->info->link.power)
- ret = priv->info->link.power(&priv->client->dev, 0);
+ if (icl->power)
+ ret = icl->power(&client->dev, 0);
return ret;
}
static int tw9910_start_capture(struct soc_camera_device *icd)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct tw9910_priv *priv = i2c_get_clientdata(client);
if (!priv->scale) {
dev_err(&icd->dev, "norm select error\n");
@@ -567,8 +568,9 @@ static int tw9910_set_bus_param(struct soc_camera_device *icd,
static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
- struct soc_camera_link *icl = priv->client->dev.platform_data;
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct tw9910_priv *priv = i2c_get_clientdata(client);
+ struct soc_camera_link *icl = to_soc_camera_link(icd);
unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
@@ -610,13 +612,13 @@ static int tw9910_enum_input(struct soc_camera_device *icd,
static int tw9910_get_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
int ret;
if (reg->reg > 0xff)
return -EINVAL;
- ret = i2c_smbus_read_byte_data(priv->client, reg->reg);
+ ret = i2c_smbus_read_byte_data(client, reg->reg);
if (ret < 0)
return ret;
@@ -631,20 +633,21 @@ static int tw9910_get_register(struct soc_camera_device *icd,
static int tw9910_set_register(struct soc_camera_device *icd,
struct v4l2_dbg_register *reg)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
if (reg->reg > 0xff ||
reg->val > 0xff)
return -EINVAL;
- return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val);
+ return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
}
#endif
static int tw9910_set_crop(struct soc_camera_device *icd,
struct v4l2_rect *rect)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
+ struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+ struct tw9910_priv *priv = i2c_get_clientdata(client);
int ret = -EINVAL;
u8 val;
@@ -658,8 +661,8 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
/*
* reset hardware
*/
- tw9910_reset(priv->client);
- ret = tw9910_write_array(priv->client, tw9910_default_regs);
+ tw9910_reset(client);
+ ret = tw9910_write_array(client, tw9910_default_regs);
if (ret < 0)
goto tw9910_set_fmt_error;
@@ -670,7 +673,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
if (SOCAM_DATAWIDTH_16 == priv->info->buswidth)
val = LEN;
- ret = tw9910_mask_set(priv->client, OPFORM, LEN, val);
+ ret = tw9910_mask_set(client, OPFORM, LEN, val);
if (ret < 0)
goto tw9910_set_fmt_error;
@@ -698,28 +701,28 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
val = 0;
}
- ret = tw9910_mask_set(priv->client, VBICNTL, RTSEL_MASK, val);
+ ret = tw9910_mask_set(client, VBICNTL, RTSEL_MASK, val);
if (ret < 0)
goto tw9910_set_fmt_error;
/*
* set scale
*/
- ret = tw9910_set_scale(priv->client, priv->scale);
+ ret = tw9910_set_scale(client, priv->scale);
if (ret < 0)
goto tw9910_set_fmt_error;
/*
* set cropping
*/
- ret = tw9910_set_cropping(priv->client, &tw9910_cropping_ctrl);
+ ret = tw9910_set_cropping(client, &tw9910_cropping_ctrl);
if (ret < 0)
goto tw9910_set_fmt_error;
/*
* set hsync
*/
- ret = tw9910_set_hsync(priv->client, &tw9910_hsync_ctrl);
+ ret = tw9910_set_hsync(client, &tw9910_hsync_ctrl);
if (ret < 0)
goto tw9910_set_fmt_error;
@@ -727,7 +730,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
tw9910_set_fmt_error:
- tw9910_reset(priv->client);
+ tw9910_reset(client);
priv->scale = NULL;
return ret;
@@ -784,9 +787,10 @@ static int tw9910_try_fmt(struct soc_camera_device *icd,
return 0;
}
-static int tw9910_video_probe(struct soc_camera_device *icd)
+static int tw9910_video_probe(struct soc_camera_device *icd,
+ struct i2c_client *client)
{
- struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
+ struct tw9910_priv *priv = i2c_get_clientdata(client);
s32 val;
int ret;
@@ -810,10 +814,18 @@ static int tw9910_video_probe(struct soc_camera_device *icd)
icd->formats = tw9910_color_fmt;
icd->num_formats = ARRAY_SIZE(tw9910_color_fmt);
+ /* Switch master clock on */
+ ret = soc_camera_video_start(icd, &client->dev);
+ if (ret)
+ return ret;
+
/*
* check and show Product ID
*/
- val = i2c_smbus_read_byte_data(priv->client, ID);
+ val = i2c_smbus_read_byte_data(client, ID);
+
+ soc_camera_video_stop(icd);
+
if (0x0B != GET_ID(val) ||
0x00 != GET_ReV(val)) {
dev_err(&icd->dev,
@@ -824,10 +836,6 @@ static int tw9910_video_probe(struct soc_camera_device *icd)
dev_info(&icd->dev,
"tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val));
- ret = soc_camera_video_start(icd);
- if (ret < 0)
- return ret;
-
icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL;
icd->vdev->current_norm = V4L2_STD_NTSC;
@@ -836,13 +844,11 @@ static int tw9910_video_probe(struct soc_camera_device *icd)
static void tw9910_video_remove(struct soc_camera_device *icd)
{
- soc_camera_video_stop(icd);
+ icd->ops = NULL;
}
static struct soc_camera_ops tw9910_ops = {
.owner = THIS_MODULE,
- .probe = tw9910_video_probe,
- .remove = tw9910_video_remove,
.init = tw9910_init,
.release = tw9910_release,
.start_capture = tw9910_start_capture,
@@ -871,16 +877,25 @@ static int tw9910_probe(struct i2c_client *client,
{
struct tw9910_priv *priv;
struct tw9910_video_info *info;
- struct soc_camera_device *icd;
+ struct soc_camera_device *icd = client->dev.platform_data;
+ struct i2c_adapter *adapter =
+ to_i2c_adapter(client->dev.parent);
+ struct soc_camera_link *icl;
const struct tw9910_scale_ctrl *scale;
int i, ret;
- info = client->dev.platform_data;
- if (!info)
+ if (!icd) {
+ dev_err(&client->dev, "TW9910: missing soc-camera data!\n");
return -EINVAL;
+ }
- if (!i2c_check_functionality(to_i2c_adapter(client->dev.parent),
- I2C_FUNC_SMBUS_BYTE_DATA)) {
+ icl = to_soc_camera_link(icd);
+ if (!icl)
+ return -EINVAL;
+
+ info = container_of(icl, struct tw9910_video_info, link);
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_err(&client->dev,
"I2C-Adapter doesn't support "
"I2C_FUNC_SMBUS_BYTE_DATA\n");
@@ -892,12 +907,9 @@ static int tw9910_probe(struct i2c_client *client,
return -ENOMEM;
priv->info = info;
- priv->client = client;
i2c_set_clientdata(client, priv);
- icd = &priv->icd;
icd->ops = &tw9910_ops;
- icd->control = &client->dev;
icd->iface = info->link.bus_id;
/*
@@ -923,8 +935,7 @@ static int tw9910_probe(struct i2c_client *client,
icd->height_min = min(scale[i].height, icd->height_min);
}
- ret = soc_camera_device_register(icd);
-
+ ret = tw9910_video_probe(icd, client);
if (ret) {
i2c_set_clientdata(client, NULL);
kfree(priv);
@@ -936,8 +947,9 @@ static int tw9910_probe(struct i2c_client *client,
static int tw9910_remove(struct i2c_client *client)
{
struct tw9910_priv *priv = i2c_get_clientdata(client);
+ struct soc_camera_device *icd = client->dev.platform_data;
- soc_camera_device_unregister(&priv->icd);
+ tw9910_video_remove(icd);
i2c_set_clientdata(client, NULL);
kfree(priv);
return 0;
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index bef5e81..977326e 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -12,6 +12,7 @@
#ifndef SOC_CAMERA_H
#define SOC_CAMERA_H
+#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/pm.h>
#include <linux/videodev2.h>
@@ -20,7 +21,6 @@
struct soc_camera_device {
struct list_head list;
struct device dev;
- struct device *control;
unsigned short width; /* Current window */
unsigned short height; /* sizes */
unsigned short x_min; /* Camera capabilities */
@@ -97,6 +97,8 @@ struct soc_camera_link {
int bus_id;
/* Per camera SOCAM_SENSOR_* bus flags */
unsigned long flags;
+ int i2c_adapter_id;
+ struct i2c_board_info *board_info;
/* Optional callbacks to power on or off and reset the sensor */
int (*power)(struct device *, int);
int (*reset)(struct device *);
@@ -120,17 +122,25 @@ static inline struct soc_camera_host *to_soc_camera_host(struct device *dev)
return dev_get_drvdata(dev);
}
-extern int soc_camera_host_register(struct soc_camera_host *ici);
-extern void soc_camera_host_unregister(struct soc_camera_host *ici);
-extern int soc_camera_device_register(struct soc_camera_device *icd);
-extern void soc_camera_device_unregister(struct soc_camera_device *icd);
+static inline struct soc_camera_link *to_soc_camera_link(struct soc_camera_device *icd)
+{
+ return icd->dev.platform_data;
+}
-extern int soc_camera_video_start(struct soc_camera_device *icd);
-extern void soc_camera_video_stop(struct soc_camera_device *icd);
+static inline struct device *to_soc_camera_control(struct soc_camera_device *icd)
+{
+ return dev_get_drvdata(&icd->dev);
+}
-extern const struct soc_camera_data_format *soc_camera_format_by_fourcc(
+int soc_camera_host_register(struct soc_camera_host *ici);
+void soc_camera_host_unregister(struct soc_camera_host *ici);
+
+int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev);
+void soc_camera_video_stop(struct soc_camera_device *icd);
+
+const struct soc_camera_data_format *soc_camera_format_by_fourcc(
struct soc_camera_device *icd, unsigned int fourcc);
-extern const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
+const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
struct soc_camera_device *icd, unsigned int fourcc);
struct soc_camera_data_format {
@@ -159,8 +169,6 @@ struct soc_camera_format_xlate {
struct soc_camera_ops {
struct module *owner;
- int (*probe)(struct soc_camera_device *);
- void (*remove)(struct soc_camera_device *);
int (*suspend)(struct soc_camera_device *, pm_message_t state);
int (*resume)(struct soc_camera_device *);
int (*init)(struct soc_camera_device *);
diff --git a/include/media/soc_camera_platform.h b/include/media/soc_camera_platform.h
index 1d092b4..db7ff89 100644
--- a/include/media/soc_camera_platform.h
+++ b/include/media/soc_camera_platform.h
@@ -14,13 +14,12 @@
#include <linux/videodev2.h>
struct soc_camera_platform_info {
- int iface;
- char *format_name;
+ const char *format_name;
unsigned long format_depth;
struct v4l2_pix_format format;
unsigned long bus_param;
- void (*power)(int);
int (*set_capture)(struct soc_camera_platform_info *info, int enable);
+ struct soc_camera_link link;
};
#endif /* __SOC_CAMERA_H__ */
--
1.5.4
^ permalink raw reply related [flat|nested] 46+ messages in thread* Re: [PATCH 5/5 v2] soc-camera: Convert to a platform driver
2009-04-17 18:38 ` [PATCH 5/5 v2] soc-camera: Convert to a platform driver Guennadi Liakhovetski
@ 2009-04-19 20:01 ` Robert Jarzmik
2009-04-20 9:45 ` Darius Augulis
1 sibling, 0 replies; 46+ messages in thread
From: Robert Jarzmik @ 2009-04-19 20:01 UTC (permalink / raw)
To: Guennadi Liakhovetski
Cc: Magnus Damm, Linux Media Mailing List, Darius Augulis
Guennadi Liakhovetski <g.liakhovetski@gmx.de> writes:
> Convert soc-camera core to a platform driver. With this approach I2C
> devices are no longer statically registered in platform code, instead they
> are registered dynamically by the soc-camera core, when a match with a
> host driver is found. With this patch all platforms and all soc-camera
> device drivers are converted too. This is a preparatory step for the
> v4l-subdev conversion.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>
Cheers.
--
Robert
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH 5/5 v2] soc-camera: Convert to a platform driver
2009-04-17 18:38 ` [PATCH 5/5 v2] soc-camera: Convert to a platform driver Guennadi Liakhovetski
2009-04-19 20:01 ` Robert Jarzmik
@ 2009-04-20 9:45 ` Darius Augulis
1 sibling, 0 replies; 46+ messages in thread
From: Darius Augulis @ 2009-04-20 9:45 UTC (permalink / raw)
To: Guennadi Liakhovetski; +Cc: Linux Media Mailing List, Robert Jarzmik
Guennadi Liakhovetski wrote:
> Convert soc-camera core to a platform driver. With this approach I2C
> devices are no longer statically registered in platform code, instead they
> are registered dynamically by the soc-camera core, when a match with a
> host driver is found. With this patch all platforms and all soc-camera
> device drivers are converted too. This is a preparatory step for the
> v4l-subdev conversion.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> ---
>
> Changes since v1: addressed Robert's wishes:-), even compile-tested for
> mioa701! Fixed sh_mobile_ceu / migor and tested (still only blindly, I'll
> come to the mplayer thing some time...) - it turned out to be a great
> test-case - caught a couple of driver and soc-camera core bugs.
>
> Darius, would be nice if you could test this patch series too (see
> archives). Unfortunately, I cannot seem to find a suitable i.MX1 platform
> code for your camera driver, so, you'd have to convert it yourself. It
> isn't very difficult though - just look at other examples, e.g., mx3.
>
unfortunately I don't have time for this yet.
I have lot of new stuff to do at least for 1 month.
I guess I should have opportunity to return to IMX.
> arch/arm/mach-mx3/pcm037.c | 25 ++-
> arch/arm/mach-pxa/em-x270.c | 21 ++-
> arch/arm/mach-pxa/mioa701.c | 19 +-
> arch/arm/mach-pxa/pcm990-baseboard.c | 52 +++-
> arch/sh/boards/board-ap325rxa.c | 55 +++--
> arch/sh/boards/mach-migor/setup.c | 77 ++++--
> drivers/media/video/mt9m001.c | 113 ++++-----
> drivers/media/video/mt9m111.c | 152 ++++++------
> drivers/media/video/mt9t031.c | 113 ++++-----
> drivers/media/video/mt9v022.c | 118 +++++-----
> drivers/media/video/mx3_camera.c | 27 ++-
> drivers/media/video/ov772x.c | 153 +++++++-----
> drivers/media/video/pxa_camera.c | 27 ++-
> drivers/media/video/sh_mobile_ceu_camera.c | 13 +-
> drivers/media/video/soc_camera.c | 371 +++++++++++++++-------------
> drivers/media/video/soc_camera_platform.c | 112 +++++----
> drivers/media/video/tw9910.c | 106 +++++----
> include/media/soc_camera.h | 30 ++-
> include/media/soc_camera_platform.h | 5 +-
> 19 files changed, 894 insertions(+), 695 deletions(-)
>
> diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c
> index 6bfd29a..00ce1eb 100644
> --- a/arch/arm/mach-mx3/pcm037.c
> +++ b/arch/arm/mach-mx3/pcm037.c
> @@ -241,9 +241,17 @@ static int pcm037_camera_power(struct device *dev, int on)
> return 0;
> }
>
> +static struct i2c_board_info pcm037_i2c_2_devices[] = {
> + {
> + I2C_BOARD_INFO("mt9t031", 0x5d),
> + },
> +};
> +
> static struct soc_camera_link iclink = {
> - .bus_id = 0, /* Must match with the camera ID */
> - .power = pcm037_camera_power,
> + .bus_id = 0, /* Must match with the camera ID */
> + .power = pcm037_camera_power,
> + .board_info = &pcm037_i2c_2_devices[0],
> + .i2c_adapter_id = 2,
> };
>
> static struct i2c_board_info pcm037_i2c_devices[] = {
> @@ -256,9 +264,10 @@ static struct i2c_board_info pcm037_i2c_devices[] = {
> }
> };
>
> -static struct i2c_board_info pcm037_i2c_2_devices[] = {
> - {
> - I2C_BOARD_INFO("mt9t031", 0x5d),
> +static struct platform_device pcm037_camera = {
> + .name = "soc-camera-pdrv",
> + .id = 0,
> + .dev = {
> .platform_data = &iclink,
> },
> };
> @@ -338,6 +347,9 @@ static struct platform_device *devices[] __initdata = {
> &pcm037_flash,
> &pcm037_eth,
> &pcm037_sram_device,
> +#if defined(CONFIG_I2C_IMX) || defined(CONFIG_I2C_IMX_MODULE)
> + &pcm037_camera,
> +#endif
> };
>
> static struct ipu_platform_data mx3_ipu_data = {
> @@ -395,9 +407,6 @@ static void __init mxc_board_init(void)
> i2c_register_board_info(1, pcm037_i2c_devices,
> ARRAY_SIZE(pcm037_i2c_devices));
>
> - i2c_register_board_info(2, pcm037_i2c_2_devices,
> - ARRAY_SIZE(pcm037_i2c_2_devices));
> -
> mxc_register_device(&mxc_i2c_device1, &pcm037_i2c_1_data);
> mxc_register_device(&mxc_i2c_device2, &pcm037_i2c_2_data);
> #endif
> diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
> index 920dfb8..d4eb0c7 100644
> --- a/arch/arm/mach-pxa/em-x270.c
> +++ b/arch/arm/mach-pxa/em-x270.c
> @@ -847,14 +847,23 @@ static int em_x270_sensor_power(struct device *dev, int on)
> return 0;
> }
>
> -static struct soc_camera_link iclink = {
> - .bus_id = 0,
> - .power = em_x270_sensor_power,
> -};
> -
> static struct i2c_board_info em_x270_i2c_cam_info[] = {
> {
> I2C_BOARD_INFO("mt9m111", 0x48),
> + },
> +};
> +
> +static struct soc_camera_link iclink = {
> + .bus_id = 0,
> + .power = em_x270_sensor_power,
> + .board_info = &em_x270_i2c_cam_info[0],
> + .i2c_adapter_id = 0,
> +};
> +
> +static struct platform_device em_x270_camera = {
> + .name = "soc-camera-pdrv",
> + .id = -1,
> + .dev = {
> .platform_data = &iclink,
> },
> };
> @@ -866,8 +875,8 @@ static struct i2c_pxa_platform_data em_x270_i2c_info = {
> static void __init em_x270_init_camera(void)
> {
> pxa_set_i2c_info(&em_x270_i2c_info);
> - i2c_register_board_info(0, ARRAY_AND_SIZE(em_x270_i2c_cam_info));
> pxa_set_camera_info(&em_x270_camera_platform_data);
> + platform_device_register(&em_x270_camera);
> }
> #else
> static inline void em_x270_init_camera(void) {}
> diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
> index 97c93a7..204263d 100644
> --- a/arch/arm/mach-pxa/mioa701.c
> +++ b/arch/arm/mach-pxa/mioa701.c
> @@ -724,19 +724,21 @@ struct pxacamera_platform_data mioa701_pxacamera_platform_data = {
> .mclk_10khz = 5000,
> };
>
> -static struct soc_camera_link iclink = {
> - .bus_id = 0, /* Must match id in pxa27x_device_camera in device.c */
> -};
> -
> -/* Board I2C devices. */
> +/*
> + * Board I2C devices
> + */
> static struct i2c_board_info __initdata mioa701_i2c_devices[] = {
> {
> - /* Must initialize before the camera(s) */
> I2C_BOARD_INFO("mt9m111", 0x5d),
> - .platform_data = &iclink,
> },
> };
>
> +static struct soc_camera_link iclink = {
> + .bus_id = 0, /* Match id in pxa27x_device_camera in device.c */
> + .board_info = &mioa701_i2c_devices[0],
> + .i2c_adapter_id = 0,
> +};
> +
> struct i2c_pxa_platform_data i2c_pdata = {
> .fast_mode = 1,
> };
> @@ -768,6 +770,7 @@ MIO_PARENT_DEV(mio_wm9713_codec, "wm9713-codec", &pxa2xx_ac97.dev, NULL)
> MIO_SIMPLE_DEV(mioa701_sound, "mioa701-wm9713", NULL)
> MIO_SIMPLE_DEV(mioa701_board, "mioa701-board", NULL)
> MIO_SIMPLE_DEV(gpio_vbus, "gpio-vbus", &gpio_vbus_data);
> +MIO_SIMPLE_DEV(mioa701_camera, "soc-camera-pdrv",&iclink)
>
> static struct platform_device *devices[] __initdata = {
> &mioa701_gpio_keys,
> @@ -780,6 +783,7 @@ static struct platform_device *devices[] __initdata = {
> &power_dev,
> &strataflash,
> &gpio_vbus,
> + &mioa701_camera,
> &mioa701_board,
> };
>
> @@ -825,7 +829,6 @@ static void __init mioa701_machine_init(void)
>
> pxa_set_i2c_info(&i2c_pdata);
> pxa_set_camera_info(&mioa701_pxacamera_platform_data);
> - i2c_register_board_info(0, ARRAY_AND_SIZE(mioa701_i2c_devices));
> }
>
> static void mioa701_machine_exit(void)
> diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
> index 9ce1ef2..619b90e 100644
> --- a/arch/arm/mach-pxa/pcm990-baseboard.c
> +++ b/arch/arm/mach-pxa/pcm990-baseboard.c
> @@ -427,25 +427,54 @@ static void pcm990_camera_free_bus(struct soc_camera_link *link)
> gpio_bus_switch = -EINVAL;
> }
>
> -static struct soc_camera_link iclink = {
> - .bus_id = 0, /* Must match with the camera ID above */
> - .query_bus_param = pcm990_camera_query_bus_param,
> - .set_bus_param = pcm990_camera_set_bus_param,
> - .free_bus = pcm990_camera_free_bus,
> -};
> -
> /* Board I2C devices. */
> static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
> {
> /* Must initialize before the camera(s) */
> I2C_BOARD_INFO("pca9536", 0x41),
> .platform_data = &pca9536_data,
> - }, {
> + },
> +};
> +
> +static struct i2c_board_info __initdata pcm990_camera_i2c[] = {
> + {
> I2C_BOARD_INFO("mt9v022", 0x48),
> - .platform_data = &iclink, /* With extender */
> }, {
> I2C_BOARD_INFO("mt9m001", 0x5d),
> - .platform_data = &iclink, /* With extender */
> + },
> +};
> +
> +static struct soc_camera_link iclink[] = {
> + {
> + .bus_id = 0, /* Must match with the camera ID */
> + .board_info = &pcm990_camera_i2c[0],
> + .i2c_adapter_id = 0,
> + .query_bus_param = pcm990_camera_query_bus_param,
> + .set_bus_param = pcm990_camera_set_bus_param,
> + .free_bus = pcm990_camera_free_bus,
> + }, {
> + .bus_id = 0, /* Must match with the camera ID */
> + .board_info = &pcm990_camera_i2c[1],
> + .i2c_adapter_id = 0,
> + .query_bus_param = pcm990_camera_query_bus_param,
> + .set_bus_param = pcm990_camera_set_bus_param,
> + .free_bus = pcm990_camera_free_bus,
> + },
> +};
> +
> +static struct platform_device pcm990_camera[] = {
> + {
> + .name = "soc-camera-pdrv",
> + .id = 0,
> + .dev = {
> + .platform_data = &iclink[0],
> + },
> + }, {
> + .name = "soc-camera-pdrv",
> + .id = 1,
> + .dev = {
> + .platform_data = &iclink[1],
> + },
> },
> };
> #endif /* CONFIG_VIDEO_PXA27x ||CONFIG_VIDEO_PXA27x_MODULE */
> @@ -501,6 +530,9 @@ void __init pcm990_baseboard_init(void)
> pxa_set_camera_info(&pcm990_pxacamera_platform_data);
>
> i2c_register_board_info(0, ARRAY_AND_SIZE(pcm990_i2c_devices));
> +
> + platform_device_register(&pcm990_camera[0]);
> + platform_device_register(&pcm990_camera[1]);
> #endif
>
> printk(KERN_INFO "PCM-990 Evaluation baseboard initialized\n");
> diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c
> index e27655b..37c9139 100644
> --- a/arch/sh/boards/board-ap325rxa.c
> +++ b/arch/sh/boards/board-ap325rxa.c
> @@ -228,12 +228,6 @@ static struct platform_device lcdc_device = {
> },
> };
>
> -static void camera_power(int val)
> -{
> - gpio_set_value(GPIO_PTZ5, val); /* RST_CAM/RSTB */
> - mdelay(10);
> -}
> -
> #ifdef CONFIG_I2C
> static unsigned char camera_ncm03j_magic[] =
> {
> @@ -255,23 +249,28 @@ static unsigned char camera_ncm03j_magic[] =
> 0x63, 0xD4, 0x64, 0xEA, 0xD6, 0x0F,
> };
>
> -static int camera_set_capture(struct soc_camera_platform_info *info,
> - int enable)
> +static int ap325rxa_camera_power(struct device *dev, int on)
> {
> - struct i2c_adapter *a = i2c_get_adapter(0);
> + gpio_set_value(GPIO_PTZ5, on); /* RST_CAM/RSTB */
> + mdelay(10);
> + return 0;
> +}
> +
> +static int ap325rxa_camera_set_capture(struct soc_camera_platform_info *info,
> + int enable)
> +{
> + struct i2c_adapter *a = i2c_get_adapter(info->link.i2c_adapter_id);
> struct i2c_msg msg;
> int ret = 0;
> int i;
>
> - camera_power(0);
> if (!enable)
> - return 0; /* no disable for now */
> + return ap325rxa_camera_power(NULL, 0); /* no disable for now */
>
> - camera_power(1);
> for (i = 0; i < ARRAY_SIZE(camera_ncm03j_magic); i += 2) {
> u_int8_t buf[8];
>
> - msg.addr = 0x6e;
> + msg.addr = info->link.board_info->addr;
> msg.buf = buf;
> msg.len = 2;
> msg.flags = 0;
> @@ -285,8 +284,11 @@ static int camera_set_capture(struct soc_camera_platform_info *info,
> return ret;
> }
>
> +static struct i2c_board_info __initdata ap325rxa_camera_i2c = {
> + I2C_BOARD_INFO("soc_camera_platform", 0x6e),
> +};
> +
> static struct soc_camera_platform_info camera_info = {
> - .iface = 0,
> .format_name = "UYVY",
> .format_depth = 16,
> .format = {
> @@ -296,22 +298,29 @@ static struct soc_camera_platform_info camera_info = {
> .height = 480,
> },
> .bus_param = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
> - SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
> - .set_capture = camera_set_capture,
> + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_MASTER | SOCAM_DATAWIDTH_8,
> + .set_capture = ap325rxa_camera_set_capture,
> + .link = {
> + .bus_id = 0,
> + .board_info = &ap325rxa_camera_i2c,
> + .i2c_adapter_id = 0,
> + .power = ap325rxa_camera_power,
> + },
> };
>
> -static struct platform_device camera_device = {
> - .name = "soc_camera_platform",
> - .dev = {
> - .platform_data = &camera_info,
> +static struct platform_device ap325rxa_camera = {
> + .name = "soc-camera-pdrv",
> + .id = -1,
> + .dev = {
> + .platform_data = &camera_info.link,
> },
> };
> #endif /* CONFIG_I2C */
>
> static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
> .flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_HSYNC_ACTIVE_HIGH |
> - SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH | SOCAM_MASTER |
> - SOCAM_DATAWIDTH_8,
> + SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH |
> + SOCAM_MASTER | SOCAM_DATAWIDTH_8,
> };
>
> static struct resource ceu_resources[] = {
> @@ -360,7 +369,7 @@ static struct platform_device *ap325rxa_devices[] __initdata = {
> &lcdc_device,
> &ceu_device,
> #ifdef CONFIG_I2C
> - &camera_device,
> + &ap325rxa_camera,
> #endif
> &nand_flash_device,
> &sdcard_cn3_device,
> diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
> index 4fd6a72..b8cb246 100644
> --- a/arch/sh/boards/mach-migor/setup.c
> +++ b/arch/sh/boards/mach-migor/setup.c
> @@ -383,21 +383,6 @@ static struct platform_device migor_ceu_device = {
> },
> };
>
> -static struct ov772x_camera_info ov7725_info = {
> - .buswidth = SOCAM_DATAWIDTH_8,
> - .link = {
> - .power = ov7725_power,
> - },
> -};
> -
> -static struct tw9910_video_info tw9910_info = {
> - .buswidth = SOCAM_DATAWIDTH_8,
> - .mpout = TW9910_MPO_FIELD,
> - .link = {
> - .power = tw9910_power,
> - }
> -};
> -
> struct spi_gpio_platform_data sdcard_cn9_platform_data = {
> .sck = GPIO_PTD0,
> .mosi = GPIO_PTD1,
> @@ -412,16 +397,6 @@ static struct platform_device sdcard_cn9_device = {
> },
> };
>
> -static struct platform_device *migor_devices[] __initdata = {
> - &smc91x_eth_device,
> - &sh_keysc_device,
> - &migor_lcdc_device,
> - &migor_ceu_device,
> - &migor_nor_flash_device,
> - &migor_nand_flash_device,
> - &sdcard_cn9_device,
> -};
> -
> static struct i2c_board_info migor_i2c_devices[] = {
> {
> I2C_BOARD_INFO("rs5c372b", 0x32),
> @@ -430,16 +405,64 @@ static struct i2c_board_info migor_i2c_devices[] = {
> I2C_BOARD_INFO("migor_ts", 0x51),
> .irq = 38, /* IRQ6 */
> },
> +};
> +
> +static struct i2c_board_info migor_camera_i2c[] = {
> {
> I2C_BOARD_INFO("ov772x", 0x21),
> - .platform_data = &ov7725_info,
> },
> {
> I2C_BOARD_INFO("tw9910", 0x45),
> - .platform_data = &tw9910_info,
> },
> };
>
> +static struct ov772x_camera_info ov7725_info = {
> + .buswidth = SOCAM_DATAWIDTH_8,
> + .link = {
> + .power = ov7725_power,
> + .board_info = &migor_camera_i2c[0],
> + .i2c_adapter_id = 0,
> + },
> +};
> +
> +static struct tw9910_video_info tw9910_info = {
> + .buswidth = SOCAM_DATAWIDTH_8,
> + .mpout = TW9910_MPO_FIELD,
> + .link = {
> + .power = tw9910_power,
> + .board_info = &migor_camera_i2c[1],
> + .i2c_adapter_id = 0,
> + }
> +};
> +
> +static struct platform_device migor_camera[] = {
> + {
> + .name = "soc-camera-pdrv",
> + .id = 0,
> + .dev = {
> + .platform_data = &ov7725_info.link,
> + },
> + }, {
> + .name = "soc-camera-pdrv",
> + .id = 1,
> + .dev = {
> + .platform_data = &tw9910_info.link,
> + },
> + },
> +};
> +
> +static struct platform_device *migor_devices[] __initdata = {
> + &smc91x_eth_device,
> + &sh_keysc_device,
> + &migor_lcdc_device,
> + &migor_ceu_device,
> + &migor_nor_flash_device,
> + &migor_nand_flash_device,
> + &sdcard_cn9_device,
> + &migor_camera[0],
> + &migor_camera[1],
> +};
> +
> static struct spi_board_info migor_spi_devices[] = {
> {
> .modalias = "mmc_spi",
> diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
> index 459c04c..b0f4ad5 100644
> --- a/drivers/media/video/mt9m001.c
> +++ b/drivers/media/video/mt9m001.c
> @@ -69,8 +69,6 @@ static const struct soc_camera_data_format mt9m001_monochrome_formats[] = {
> };
>
> struct mt9m001 {
> - struct i2c_client *client;
> - struct soc_camera_device icd;
> int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
> unsigned char autoexposure;
> };
> @@ -111,11 +109,11 @@ static int reg_clear(struct i2c_client *client, const u8 reg,
>
> static int mt9m001_init(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> int ret;
>
> - dev_dbg(icd->vdev->parent, "%s\n", __func__);
> + dev_dbg(&icd->dev, "%s\n", __func__);
>
> if (icl->power) {
> ret = icl->power(&client->dev, 1);
> @@ -147,8 +145,8 @@ static int mt9m001_init(struct soc_camera_device *icd)
>
> static int mt9m001_release(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
>
> /* Disable the chip */
> reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
> @@ -161,7 +159,7 @@ static int mt9m001_release(struct soc_camera_device *icd)
>
> static int mt9m001_start_capture(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> /* Switch to master "normal" mode */
> if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0)
> @@ -171,7 +169,7 @@ static int mt9m001_start_capture(struct soc_camera_device *icd)
>
> static int mt9m001_stop_capture(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> /* Stop sensor readout */
> if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0)
> @@ -182,8 +180,7 @@ static int mt9m001_stop_capture(struct soc_camera_device *icd)
> static int mt9m001_set_bus_param(struct soc_camera_device *icd,
> unsigned long flags)
> {
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> - struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> unsigned long width_flag = flags & SOCAM_DATAWIDTH_MASK;
>
> /* Only one width bit may be set */
> @@ -205,8 +202,7 @@ static int mt9m001_set_bus_param(struct soc_camera_device *icd,
>
> static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
> {
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> - struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> /* MT9M001 has all capture_format parameters fixed */
> unsigned long flags = SOCAM_PCLK_SAMPLE_FALLING |
> SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
> @@ -223,8 +219,8 @@ static unsigned long mt9m001_query_bus_param(struct soc_camera_device *icd)
> static int mt9m001_set_crop(struct soc_camera_device *icd,
> struct v4l2_rect *rect)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
> int ret;
> const u16 hblank = 9, vblank = 25;
>
> @@ -296,12 +292,13 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd,
> static int mt9m001_get_chip_id(struct soc_camera_device *icd,
> struct v4l2_dbg_chip_ident *id)
> {
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
>
> if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
> return -EINVAL;
>
> - if (id->match.addr != mt9m001->client->addr)
> + if (id->match.addr != client->addr)
> return -ENODEV;
>
> id->ident = mt9m001->model;
> @@ -314,7 +311,7 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd,
> static int mt9m001_get_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
> return -EINVAL;
> @@ -334,7 +331,7 @@ static int mt9m001_get_register(struct soc_camera_device *icd,
> static int mt9m001_set_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
> return -EINVAL;
> @@ -387,15 +384,11 @@ static const struct v4l2_queryctrl mt9m001_controls[] = {
> }
> };
>
> -static int mt9m001_video_probe(struct soc_camera_device *);
> -static void mt9m001_video_remove(struct soc_camera_device *);
> static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *);
> static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *);
>
> static struct soc_camera_ops mt9m001_ops = {
> .owner = THIS_MODULE,
> - .probe = mt9m001_video_probe,
> - .remove = mt9m001_video_remove,
> .init = mt9m001_init,
> .release = mt9m001_release,
> .start_capture = mt9m001_start_capture,
> @@ -418,8 +411,8 @@ static struct soc_camera_ops mt9m001_ops = {
>
> static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
> int data;
>
> switch (ctrl->id) {
> @@ -438,8 +431,8 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro
>
> static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
> const struct v4l2_queryctrl *qctrl;
> int data;
>
> @@ -531,11 +524,11 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
>
> /* Interface active, can use i2c. If it fails, it can indeed mean, that
> * this wasn't our capture interface, so, we wait for the right one */
> -static int mt9m001_video_probe(struct soc_camera_device *icd)
> +static int mt9m001_video_probe(struct soc_camera_device *icd,
> + struct i2c_client *client)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> s32 data;
> int ret;
> unsigned long flags;
> @@ -546,6 +539,11 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
> to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
> return -ENODEV;
>
> + /* Switch master clock on */
> + ret = soc_camera_video_start(icd, &client->dev);
> + if (ret)
> + return ret;
> +
> /* Enable the chip */
> data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
> dev_dbg(&icd->dev, "write: %d\n", data);
> @@ -553,6 +551,8 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
> /* Read out the chip version register */
> data = reg_read(client, MT9M001_CHIP_VERSION);
>
> + soc_camera_video_stop(icd);
> +
> /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
> switch (data) {
> case 0x8411:
> @@ -565,10 +565,9 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
> icd->formats = mt9m001_monochrome_formats;
> break;
> default:
> - ret = -ENODEV;
> dev_err(&icd->dev,
> "No MT9M001 chip detected, register read %x\n", data);
> - goto ei2c;
> + return -ENODEV;
> }
>
> icd->num_formats = 0;
> @@ -594,26 +593,17 @@ static int mt9m001_video_probe(struct soc_camera_device *icd)
> dev_info(&icd->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
> data == 0x8431 ? "C12STM" : "C12ST");
>
> - /* Now that we know the model, we can start video */
> - ret = soc_camera_video_start(icd);
> - if (ret)
> - goto eisis;
> -
> return 0;
> -
> -eisis:
> -ei2c:
> - return ret;
> }
>
> static void mt9m001_video_remove(struct soc_camera_device *icd)
> {
> - struct mt9m001 *mt9m001 = container_of(icd, struct mt9m001, icd);
> - struct soc_camera_link *icl = mt9m001->client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
>
> - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m001->client->addr,
> + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
> icd->dev.parent, icd->vdev);
> - soc_camera_video_stop(icd);
> + icd->ops = NULL;
> if (icl->free_bus)
> icl->free_bus(icl);
> }
> @@ -622,11 +612,17 @@ static int mt9m001_probe(struct i2c_client *client,
> const struct i2c_device_id *did)
> {
> struct mt9m001 *mt9m001;
> - struct soc_camera_device *icd;
> + struct soc_camera_device *icd = client->dev.platform_data;
> struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct soc_camera_link *icl;
> int ret;
>
> + if (!icd) {
> + dev_err(&client->dev, "MT9M001: missing soc-camera data!\n");
> + return -EINVAL;
> + }
> +
> + icl = to_soc_camera_link(icd);
> if (!icl) {
> dev_err(&client->dev, "MT9M001 driver needs platform data\n");
> return -EINVAL;
> @@ -642,13 +638,10 @@ static int mt9m001_probe(struct i2c_client *client,
> if (!mt9m001)
> return -ENOMEM;
>
> - mt9m001->client = client;
> i2c_set_clientdata(client, mt9m001);
>
> /* Second stage probe - when a capture adapter is there */
> - icd = &mt9m001->icd;
> icd->ops = &mt9m001_ops;
> - icd->control = &client->dev;
> icd->x_min = 20;
> icd->y_min = 12;
> icd->x_current = 20;
> @@ -658,27 +651,27 @@ static int mt9m001_probe(struct i2c_client *client,
> icd->height_min = 32;
> icd->height_max = 1024;
> icd->y_skip_top = 1;
> - icd->iface = icl->bus_id;
> /* Simulated autoexposure. If enabled, we calculate shutter width
> * ourselves in the driver based on vertical blanking and frame width */
> mt9m001->autoexposure = 1;
>
> - ret = soc_camera_device_register(icd);
> - if (ret)
> - goto eisdr;
> -
> - return 0;
> + ret = mt9m001_video_probe(icd, client);
> + if (ret) {
> + i2c_set_clientdata(client, NULL);
> + kfree(mt9m001);
> + }
>
> -eisdr:
> - kfree(mt9m001);
> return ret;
> }
>
> static int mt9m001_remove(struct i2c_client *client)
> {
> struct mt9m001 *mt9m001 = i2c_get_clientdata(client);
> + struct soc_camera_device *icd = client->dev.platform_data;
>
> - soc_camera_device_unregister(&mt9m001->icd);
> + mt9m001_video_remove(icd);
> + i2c_set_clientdata(client, NULL);
> + client->driver = NULL;
> kfree(mt9m001);
>
> return 0;
> diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c
> index fc5e2de..06f5f97 100644
> --- a/drivers/media/video/mt9m111.c
> +++ b/drivers/media/video/mt9m111.c
> @@ -148,8 +148,6 @@ enum mt9m111_context {
> };
>
> struct mt9m111 {
> - struct i2c_client *client;
> - struct soc_camera_device icd;
> int model; /* V4L2_IDENT_MT9M11x* codes from v4l2-chip-ident.h */
> enum mt9m111_context context;
> struct v4l2_rect rect;
> @@ -203,7 +201,7 @@ static int mt9m111_reg_write(struct i2c_client *client, const u16 reg,
>
> ret = reg_page_map_set(client, reg);
> if (!ret)
> - ret = i2c_smbus_write_word_data(client, (reg & 0xff),
> + ret = i2c_smbus_write_word_data(client, reg & 0xff,
> swab16(data));
> dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
> return ret;
> @@ -232,7 +230,7 @@ static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg,
> static int mt9m111_set_context(struct soc_camera_device *icd,
> enum mt9m111_context ctxt)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B
> | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B
> | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B
> @@ -249,8 +247,8 @@ static int mt9m111_set_context(struct soc_camera_device *icd,
> static int mt9m111_setup_rect(struct soc_camera_device *icd,
> struct v4l2_rect *rect)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret, is_raw_format;
> int width = rect->width;
> int height = rect->height;
> @@ -294,7 +292,7 @@ static int mt9m111_setup_rect(struct soc_camera_device *icd,
>
> static int mt9m111_setup_pixfmt(struct soc_camera_device *icd, u16 outfmt)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> int ret;
>
> ret = reg_write(OUTPUT_FORMAT_CTRL2_A, outfmt);
> @@ -315,7 +313,8 @@ static int mt9m111_setfmt_bayer10(struct soc_camera_device *icd)
>
> static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int val = 0;
>
> if (mt9m111->swap_rgb_red_blue)
> @@ -329,7 +328,8 @@ static int mt9m111_setfmt_rgb565(struct soc_camera_device *icd)
>
> static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int val = 0;
>
> if (mt9m111->swap_rgb_red_blue)
> @@ -343,7 +343,8 @@ static int mt9m111_setfmt_rgb555(struct soc_camera_device *icd)
>
> static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int val = 0;
>
> if (mt9m111->swap_yuv_cb_cr)
> @@ -356,9 +357,9 @@ static int mt9m111_setfmt_yuv(struct soc_camera_device *icd)
>
> static int mt9m111_enable(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> if (icl->power) {
> @@ -378,9 +379,9 @@ static int mt9m111_enable(struct soc_camera_device *icd)
>
> static int mt9m111_disable(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE);
> @@ -395,8 +396,8 @@ static int mt9m111_disable(struct soc_camera_device *icd)
>
> static int mt9m111_reset(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> int ret;
>
> ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
> @@ -424,8 +425,7 @@ static int mt9m111_stop_capture(struct soc_camera_device *icd)
>
> static unsigned long mt9m111_query_bus_param(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> - struct soc_camera_link *icl = mt9m111->client->dev.platform_data;
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> unsigned long flags = SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |
> SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_HIGH |
> SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
> @@ -441,7 +441,8 @@ static int mt9m111_set_bus_param(struct soc_camera_device *icd, unsigned long f)
> static int mt9m111_set_crop(struct soc_camera_device *icd,
> struct v4l2_rect *rect)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> dev_dbg(&icd->dev, "%s left=%d, top=%d, width=%d, height=%d\n",
> @@ -456,7 +457,8 @@ static int mt9m111_set_crop(struct soc_camera_device *icd,
>
> static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> switch (pixfmt) {
> @@ -506,7 +508,8 @@ static int mt9m111_set_pixfmt(struct soc_camera_device *icd, u32 pixfmt)
> static int mt9m111_set_fmt(struct soc_camera_device *icd,
> struct v4l2_format *f)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> struct v4l2_pix_format *pix = &f->fmt.pix;
> struct v4l2_rect rect = {
> .left = mt9m111->rect.left,
> @@ -544,12 +547,13 @@ static int mt9m111_try_fmt(struct soc_camera_device *icd,
> static int mt9m111_get_chip_id(struct soc_camera_device *icd,
> struct v4l2_dbg_chip_ident *id)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>
> if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
> return -EINVAL;
>
> - if (id->match.addr != mt9m111->client->addr)
> + if (id->match.addr != client->addr)
> return -ENODEV;
>
> id->ident = mt9m111->model;
> @@ -562,8 +566,8 @@ static int mt9m111_get_chip_id(struct soc_camera_device *icd,
> static int mt9m111_get_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> int val;
> - struct i2c_client *client = to_i2c_client(icd->control);
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
> return -EINVAL;
> @@ -583,7 +587,7 @@ static int mt9m111_get_register(struct soc_camera_device *icd,
> static int mt9m111_set_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
> return -EINVAL;
> @@ -635,8 +639,6 @@ static const struct v4l2_queryctrl mt9m111_controls[] = {
> }
> };
>
> -static int mt9m111_video_probe(struct soc_camera_device *);
> -static void mt9m111_video_remove(struct soc_camera_device *);
> static int mt9m111_get_control(struct soc_camera_device *,
> struct v4l2_control *);
> static int mt9m111_set_control(struct soc_camera_device *,
> @@ -647,8 +649,6 @@ static int mt9m111_release(struct soc_camera_device *icd);
>
> static struct soc_camera_ops mt9m111_ops = {
> .owner = THIS_MODULE,
> - .probe = mt9m111_video_probe,
> - .remove = mt9m111_video_remove,
> .init = mt9m111_init,
> .resume = mt9m111_resume,
> .release = mt9m111_release,
> @@ -672,8 +672,8 @@ static struct soc_camera_ops mt9m111_ops = {
>
> static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> if (mt9m111->context == HIGHPOWER) {
> @@ -693,7 +693,7 @@ static int mt9m111_set_flip(struct soc_camera_device *icd, int flip, int mask)
>
> static int mt9m111_get_global_gain(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> int data;
>
> data = reg_read(GLOBAL_GAIN);
> @@ -705,7 +705,7 @@ static int mt9m111_get_global_gain(struct soc_camera_device *icd)
>
> static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> u16 val;
>
> if (gain > 63 * 2 * 2)
> @@ -724,8 +724,8 @@ static int mt9m111_set_global_gain(struct soc_camera_device *icd, int gain)
>
> static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> if (on)
> @@ -741,8 +741,8 @@ static int mt9m111_set_autoexposure(struct soc_camera_device *icd, int on)
>
> static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> if (on)
> @@ -759,8 +759,8 @@ static int mt9m111_set_autowhitebalance(struct soc_camera_device *icd, int on)
> static int mt9m111_get_control(struct soc_camera_device *icd,
> struct v4l2_control *ctrl)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int data;
>
> switch (ctrl->id) {
> @@ -803,7 +803,8 @@ static int mt9m111_get_control(struct soc_camera_device *icd,
> static int mt9m111_set_control(struct soc_camera_device *icd,
> struct v4l2_control *ctrl)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> const struct v4l2_queryctrl *qctrl;
> int ret;
>
> @@ -841,7 +842,8 @@ static int mt9m111_set_control(struct soc_camera_device *icd,
>
> static int mt9m111_restore_state(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
>
> mt9m111_set_context(icd, mt9m111->context);
> mt9m111_set_pixfmt(icd, mt9m111->pixfmt);
> @@ -856,7 +858,8 @@ static int mt9m111_restore_state(struct soc_camera_device *icd)
>
> static int mt9m111_resume(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret = 0;
>
> if (mt9m111->powered) {
> @@ -871,7 +874,8 @@ static int mt9m111_resume(struct soc_camera_device *icd)
>
> static int mt9m111_init(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> int ret;
>
> mt9m111->context = HIGHPOWER;
> @@ -902,10 +906,10 @@ static int mt9m111_release(struct soc_camera_device *icd)
> * Interface active, can use i2c. If it fails, it can indeed mean, that
> * this wasn't our capture interface, so, we wait for the right one
> */
> -static int mt9m111_video_probe(struct soc_camera_device *icd)
> +static int mt9m111_video_probe(struct soc_camera_device *icd,
> + struct i2c_client *client)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> s32 data;
> int ret;
>
> @@ -917,6 +921,11 @@ static int mt9m111_video_probe(struct soc_camera_device *icd)
> to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
> return -ENODEV;
>
> + /* Switch master clock on */
> + ret = soc_camera_video_start(icd, &client->dev);
> + if (ret)
> + goto evstart;
> +
> ret = mt9m111_enable(icd);
> if (ret)
> goto ei2c;
> @@ -945,40 +954,42 @@ static int mt9m111_video_probe(struct soc_camera_device *icd)
>
> dev_info(&icd->dev, "Detected a MT9M11x chip ID %x\n", data);
>
> - ret = soc_camera_video_start(icd);
> - if (ret)
> - goto eisis;
> -
> mt9m111->autoexposure = 1;
> mt9m111->autowhitebalance = 1;
>
> mt9m111->swap_rgb_even_odd = 1;
> mt9m111->swap_rgb_red_blue = 1;
>
> - return 0;
> -eisis:
> ei2c:
> + soc_camera_video_stop(icd);
> +evstart:
> return ret;
> }
>
> static void mt9m111_video_remove(struct soc_camera_device *icd)
> {
> - struct mt9m111 *mt9m111 = container_of(icd, struct mt9m111, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9m111->client->addr,
> - mt9m111->icd.dev.parent, mt9m111->icd.vdev);
> - soc_camera_video_stop(&mt9m111->icd);
> + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
> + icd->dev.parent, icd->vdev);
> + icd->ops = NULL;
> }
>
> static int mt9m111_probe(struct i2c_client *client,
> const struct i2c_device_id *did)
> {
> struct mt9m111 *mt9m111;
> - struct soc_camera_device *icd;
> + struct soc_camera_device *icd = client->dev.platform_data;
> struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct soc_camera_link *icl;
> int ret;
>
> + if (!icd) {
> + dev_err(&client->dev, "MT9M11x: missing soc-camera data!\n");
> + return -EINVAL;
> + }
> +
> + icl = to_soc_camera_link(icd);
> if (!icl) {
> dev_err(&client->dev, "MT9M11x driver needs platform data\n");
> return -EINVAL;
> @@ -994,13 +1005,10 @@ static int mt9m111_probe(struct i2c_client *client,
> if (!mt9m111)
> return -ENOMEM;
>
> - mt9m111->client = client;
> i2c_set_clientdata(client, mt9m111);
>
> /* Second stage probe - when a capture adapter is there */
> - icd = &mt9m111->icd;
> icd->ops = &mt9m111_ops;
> - icd->control = &client->dev;
> icd->x_min = MT9M111_MIN_DARK_COLS;
> icd->y_min = MT9M111_MIN_DARK_ROWS;
> icd->x_current = icd->x_min;
> @@ -1010,22 +1018,24 @@ static int mt9m111_probe(struct i2c_client *client,
> icd->height_min = MT9M111_MIN_DARK_COLS;
> icd->height_max = MT9M111_MAX_HEIGHT;
> icd->y_skip_top = 0;
> - icd->iface = icl->bus_id;
>
> - ret = soc_camera_device_register(icd);
> - if (ret)
> - goto eisdr;
> - return 0;
> + ret = mt9m111_video_probe(icd, client);
> + if (ret) {
> + i2c_set_clientdata(client, NULL);
> + kfree(mt9m111);
> + }
>
> -eisdr:
> - kfree(mt9m111);
> return ret;
> }
>
> static int mt9m111_remove(struct i2c_client *client)
> {
> struct mt9m111 *mt9m111 = i2c_get_clientdata(client);
> - soc_camera_device_unregister(&mt9m111->icd);
> + struct soc_camera_device *icd = client->dev.platform_data;
> +
> + mt9m111_video_remove(icd);
> + i2c_set_clientdata(client, NULL);
> + client->driver = NULL;
> kfree(mt9m111);
>
> return 0;
> diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
> index f72aeb7..da09906 100644
> --- a/drivers/media/video/mt9t031.c
> +++ b/drivers/media/video/mt9t031.c
> @@ -68,8 +68,6 @@ static const struct soc_camera_data_format mt9t031_colour_formats[] = {
> };
>
> struct mt9t031 {
> - struct i2c_client *client;
> - struct soc_camera_device icd;
> int model; /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */
> unsigned char autoexposure;
> u16 xskip;
> @@ -138,8 +136,8 @@ static int get_shutter(struct i2c_client *client, u32 *data)
>
> static int mt9t031_init(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> int ret;
>
> if (icl->power) {
> @@ -166,8 +164,8 @@ static int mt9t031_init(struct soc_camera_device *icd)
>
> static int mt9t031_release(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
>
> /* Disable the chip */
> reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
> @@ -180,7 +178,7 @@ static int mt9t031_release(struct soc_camera_device *icd)
>
> static int mt9t031_start_capture(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> /* Switch to master "normal" mode */
> if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
> @@ -190,7 +188,7 @@ static int mt9t031_start_capture(struct soc_camera_device *icd)
>
> static int mt9t031_stop_capture(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> /* Stop sensor readout */
> if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
> @@ -201,7 +199,7 @@ static int mt9t031_stop_capture(struct soc_camera_device *icd)
> static int mt9t031_set_bus_param(struct soc_camera_device *icd,
> unsigned long flags)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> /* The caller should have queried our parameters, check anyway */
> if (flags & ~MT9T031_BUS_PARAM)
> @@ -217,8 +215,7 @@ static int mt9t031_set_bus_param(struct soc_camera_device *icd,
>
> static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd)
> {
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> - struct soc_camera_link *icl = mt9t031->client->dev.platform_data;
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
>
> return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM);
> }
> @@ -238,8 +235,8 @@ static void recalculate_limits(struct soc_camera_device *icd,
> static int mt9t031_set_params(struct soc_camera_device *icd,
> struct v4l2_rect *rect, u16 xskip, u16 yskip)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
> int ret;
> u16 xbin, ybin, width, height, left, top;
> const u16 hblank = MT9T031_HORIZONTAL_BLANK,
> @@ -336,7 +333,8 @@ static int mt9t031_set_params(struct soc_camera_device *icd,
> static int mt9t031_set_crop(struct soc_camera_device *icd,
> struct v4l2_rect *rect)
> {
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
>
> /* CROP - no change in scaling, or in limits */
> return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip);
> @@ -345,7 +343,8 @@ static int mt9t031_set_crop(struct soc_camera_device *icd,
> static int mt9t031_set_fmt(struct soc_camera_device *icd,
> struct v4l2_format *f)
> {
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
> int ret;
> u16 xskip, yskip;
> struct v4l2_rect rect = {
> @@ -403,12 +402,13 @@ static int mt9t031_try_fmt(struct soc_camera_device *icd,
> static int mt9t031_get_chip_id(struct soc_camera_device *icd,
> struct v4l2_dbg_chip_ident *id)
> {
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
>
> if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
> return -EINVAL;
>
> - if (id->match.addr != mt9t031->client->addr)
> + if (id->match.addr != client->addr)
> return -ENODEV;
>
> id->ident = mt9t031->model;
> @@ -421,7 +421,7 @@ static int mt9t031_get_chip_id(struct soc_camera_device *icd,
> static int mt9t031_get_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
> return -EINVAL;
> @@ -440,7 +440,7 @@ static int mt9t031_get_register(struct soc_camera_device *icd,
> static int mt9t031_set_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
> return -EINVAL;
> @@ -501,15 +501,11 @@ static const struct v4l2_queryctrl mt9t031_controls[] = {
> }
> };
>
> -static int mt9t031_video_probe(struct soc_camera_device *);
> -static void mt9t031_video_remove(struct soc_camera_device *);
> static int mt9t031_get_control(struct soc_camera_device *, struct v4l2_control *);
> static int mt9t031_set_control(struct soc_camera_device *, struct v4l2_control *);
>
> static struct soc_camera_ops mt9t031_ops = {
> .owner = THIS_MODULE,
> - .probe = mt9t031_video_probe,
> - .remove = mt9t031_video_remove,
> .init = mt9t031_init,
> .release = mt9t031_release,
> .start_capture = mt9t031_start_capture,
> @@ -532,8 +528,8 @@ static struct soc_camera_ops mt9t031_ops = {
>
> static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
> int data;
>
> switch (ctrl->id) {
> @@ -558,8 +554,8 @@ static int mt9t031_get_control(struct soc_camera_device *icd, struct v4l2_contro
>
> static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
> const struct v4l2_queryctrl *qctrl;
> int data;
>
> @@ -665,10 +661,10 @@ static int mt9t031_set_control(struct soc_camera_device *icd, struct v4l2_contro
>
> /* Interface active, can use i2c. If it fails, it can indeed mean, that
> * this wasn't our capture interface, so, we wait for the right one */
> -static int mt9t031_video_probe(struct soc_camera_device *icd)
> +static int mt9t031_video_probe(struct soc_camera_device *icd,
> + struct i2c_client *client)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
> s32 data;
> int ret;
>
> @@ -678,6 +674,11 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
> to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
> return -ENODEV;
>
> + /* Switch master clock on */
> + ret = soc_camera_video_start(icd, &client->dev);
> + if (ret)
> + return ret;
> +
> /* Enable the chip */
> data = reg_write(client, MT9T031_CHIP_ENABLE, 1);
> dev_dbg(&icd->dev, "write: %d\n", data);
> @@ -685,6 +686,8 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
> /* Read out the chip version register */
> data = reg_read(client, MT9T031_CHIP_VERSION);
>
> + soc_camera_video_stop(icd);
> +
> switch (data) {
> case 0x1621:
> mt9t031->model = V4L2_IDENT_MT9T031;
> @@ -692,44 +695,40 @@ static int mt9t031_video_probe(struct soc_camera_device *icd)
> icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats);
> break;
> default:
> - ret = -ENODEV;
> dev_err(&icd->dev,
> "No MT9T031 chip detected, register read %x\n", data);
> - goto ei2c;
> + return -ENODEV;
> }
>
> dev_info(&icd->dev, "Detected a MT9T031 chip ID %x\n", data);
>
> - /* Now that we know the model, we can start video */
> - ret = soc_camera_video_start(icd);
> - if (ret)
> - goto evstart;
> -
> return 0;
> -
> -evstart:
> -ei2c:
> - return ret;
> }
>
> static void mt9t031_video_remove(struct soc_camera_device *icd)
> {
> - struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9t031->client->addr,
> + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
> icd->dev.parent, icd->vdev);
> - soc_camera_video_stop(icd);
> + icd->ops = NULL;
> }
>
> static int mt9t031_probe(struct i2c_client *client,
> const struct i2c_device_id *did)
> {
> struct mt9t031 *mt9t031;
> - struct soc_camera_device *icd;
> + struct soc_camera_device *icd = client->dev.platform_data;
> struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct soc_camera_link *icl;
> int ret;
>
> + if (!icd) {
> + dev_err(&client->dev, "MT9T031: missing soc-camera data!\n");
> + return -EINVAL;
> + }
> +
> + icl = to_soc_camera_link(icd);
> if (!icl) {
> dev_err(&client->dev, "MT9T031 driver needs platform data\n");
> return -EINVAL;
> @@ -745,13 +744,10 @@ static int mt9t031_probe(struct i2c_client *client,
> if (!mt9t031)
> return -ENOMEM;
>
> - mt9t031->client = client;
> i2c_set_clientdata(client, mt9t031);
>
> /* Second stage probe - when a capture adapter is there */
> - icd = &mt9t031->icd;
> icd->ops = &mt9t031_ops;
> - icd->control = &client->dev;
> icd->x_min = MT9T031_COLUMN_SKIP;
> icd->y_min = MT9T031_ROW_SKIP;
> icd->x_current = icd->x_min;
> @@ -761,7 +757,6 @@ static int mt9t031_probe(struct i2c_client *client,
> icd->height_min = MT9T031_MIN_HEIGHT;
> icd->height_max = MT9T031_MAX_HEIGHT;
> icd->y_skip_top = 0;
> - icd->iface = icl->bus_id;
> /* Simulated autoexposure. If enabled, we calculate shutter width
> * ourselves in the driver based on vertical blanking and frame width */
> mt9t031->autoexposure = 1;
> @@ -769,24 +764,24 @@ static int mt9t031_probe(struct i2c_client *client,
> mt9t031->xskip = 1;
> mt9t031->yskip = 1;
>
> - ret = soc_camera_device_register(icd);
> - if (ret)
> - goto eisdr;
> -
> - return 0;
> + ret = mt9t031_video_probe(icd, client);
> + if (ret) {
> + icd->ops = NULL;
> + i2c_set_clientdata(client, NULL);
> + kfree(mt9t031);
> + }
>
> -eisdr:
> - i2c_set_clientdata(client, NULL);
> - kfree(mt9t031);
> return ret;
> }
>
> static int mt9t031_remove(struct i2c_client *client)
> {
> struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
> + struct soc_camera_device *icd = client->dev.platform_data;
>
> - soc_camera_device_unregister(&mt9t031->icd);
> + mt9t031_video_remove(icd);
> i2c_set_clientdata(client, NULL);
> + client->driver = NULL;
> kfree(mt9t031);
>
> return 0;
> diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
> index be20d31..1683af1 100644
> --- a/drivers/media/video/mt9v022.c
> +++ b/drivers/media/video/mt9v022.c
> @@ -85,8 +85,6 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = {
> };
>
> struct mt9v022 {
> - struct i2c_client *client;
> - struct soc_camera_device icd;
> int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
> u16 chip_control;
> };
> @@ -127,9 +125,9 @@ static int reg_clear(struct i2c_client *client, const u8 reg,
>
> static int mt9v022_init(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> + struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> int ret;
>
> if (icl->power) {
> @@ -173,19 +171,19 @@ static int mt9v022_init(struct soc_camera_device *icd)
>
> static int mt9v022_release(struct soc_camera_device *icd)
> {
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> - struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
>
> if (icl->power)
> - icl->power(&mt9v022->client->dev, 0);
> + icl->power(&client->dev, 0);
>
> return 0;
> }
>
> static int mt9v022_start_capture(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> /* Switch to master "normal" mode */
> mt9v022->chip_control &= ~0x10;
> if (reg_write(client, MT9V022_CHIP_CONTROL,
> @@ -196,8 +194,8 @@ static int mt9v022_start_capture(struct soc_camera_device *icd)
>
> static int mt9v022_stop_capture(struct soc_camera_device *icd)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> /* Switch to snapshot mode */
> mt9v022->chip_control |= 0x10;
> if (reg_write(client, MT9V022_CHIP_CONTROL,
> @@ -209,9 +207,9 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd)
> static int mt9v022_set_bus_param(struct soc_camera_device *icd,
> unsigned long flags)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
> int ret;
> u16 pixclk = 0;
> @@ -263,8 +261,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd,
>
> static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
> {
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> - struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> unsigned int width_flag;
>
> if (icl->query_bus_param)
> @@ -283,7 +280,7 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
> static int mt9v022_set_crop(struct soc_camera_device *icd,
> struct v4l2_rect *rect)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> int ret;
>
> /* Like in example app. Contradicts the datasheet though */
> @@ -326,7 +323,8 @@ static int mt9v022_set_crop(struct soc_camera_device *icd,
> static int mt9v022_set_fmt(struct soc_camera_device *icd,
> struct v4l2_format *f)
> {
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> struct v4l2_pix_format *pix = &f->fmt.pix;
> struct v4l2_rect rect = {
> .left = icd->x_current,
> @@ -380,12 +378,13 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd,
> static int mt9v022_get_chip_id(struct soc_camera_device *icd,
> struct v4l2_dbg_chip_ident *id)
> {
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
>
> if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
> return -EINVAL;
>
> - if (id->match.addr != mt9v022->client->addr)
> + if (id->match.addr != client->addr)
> return -ENODEV;
>
> id->ident = mt9v022->model;
> @@ -398,7 +397,7 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd,
> static int mt9v022_get_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
> return -EINVAL;
> @@ -418,7 +417,7 @@ static int mt9v022_get_register(struct soc_camera_device *icd,
> static int mt9v022_set_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
> return -EINVAL;
> @@ -487,15 +486,11 @@ static const struct v4l2_queryctrl mt9v022_controls[] = {
> }
> };
>
> -static int mt9v022_video_probe(struct soc_camera_device *);
> -static void mt9v022_video_remove(struct soc_camera_device *);
> static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *);
> static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *);
>
> static struct soc_camera_ops mt9v022_ops = {
> .owner = THIS_MODULE,
> - .probe = mt9v022_video_probe,
> - .remove = mt9v022_video_remove,
> .init = mt9v022_init,
> .release = mt9v022_release,
> .start_capture = mt9v022_start_capture,
> @@ -519,7 +514,7 @@ static struct soc_camera_ops mt9v022_ops = {
> static int mt9v022_get_control(struct soc_camera_device *icd,
> struct v4l2_control *ctrl)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> int data;
>
> switch (ctrl->id) {
> @@ -555,7 +550,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
> struct v4l2_control *ctrl)
> {
> int data;
> - struct i2c_client *client = to_i2c_client(icd->control);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> const struct v4l2_queryctrl *qctrl;
>
> qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
> @@ -652,11 +647,11 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
>
> /* Interface active, can use i2c. If it fails, it can indeed mean, that
> * this wasn't our capture interface, so, we wait for the right one */
> -static int mt9v022_video_probe(struct soc_camera_device *icd)
> +static int mt9v022_video_probe(struct soc_camera_device *icd,
> + struct i2c_client *client)
> {
> - struct i2c_client *client = to_i2c_client(icd->control);
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> s32 data;
> int ret;
> unsigned long flags;
> @@ -665,6 +660,11 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
> to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
> return -ENODEV;
>
> + /* Switch master clock on */
> + ret = soc_camera_video_start(icd, &client->dev);
> + if (ret)
> + return ret;
> +
> /* Read out the chip version register */
> data = reg_read(client, MT9V022_CHIP_VERSION);
>
> @@ -684,6 +684,8 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
> udelay(200);
> if (reg_read(client, MT9V022_RESET)) {
> dev_err(&icd->dev, "Resetting MT9V022 failed!\n");
> + if (ret > 0)
> + ret = -EIO;
> goto ei2c;
> }
>
> @@ -700,7 +702,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
> }
>
> if (ret < 0)
> - goto eisis;
> + goto ei2c;
>
> icd->num_formats = 0;
>
> @@ -722,29 +724,24 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
> if (flags & SOCAM_DATAWIDTH_8)
> icd->num_formats++;
>
> - ret = soc_camera_video_start(icd);
> - if (ret < 0)
> - goto eisis;
> -
> dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n",
> data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ?
> "monochrome" : "colour");
>
> - return 0;
> -
> -eisis:
> ei2c:
> + soc_camera_video_stop(icd);
> +
> return ret;
> }
>
> static void mt9v022_video_remove(struct soc_camera_device *icd)
> {
> - struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd);
> - struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
>
> - dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr,
> + dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
> icd->dev.parent, icd->vdev);
> - soc_camera_video_stop(icd);
> + icd->ops = NULL;
> if (icl->free_bus)
> icl->free_bus(icl);
> }
> @@ -753,11 +750,17 @@ static int mt9v022_probe(struct i2c_client *client,
> const struct i2c_device_id *did)
> {
> struct mt9v022 *mt9v022;
> - struct soc_camera_device *icd;
> + struct soc_camera_device *icd = client->dev.platform_data;
> struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> - struct soc_camera_link *icl = client->dev.platform_data;
> + struct soc_camera_link *icl;
> int ret;
>
> + if (!icd) {
> + dev_err(&client->dev, "MT9V022: missing soc-camera data!\n");
> + return -EINVAL;
> + }
> +
> + icl = to_soc_camera_link(icd);
> if (!icl) {
> dev_err(&client->dev, "MT9V022 driver needs platform data\n");
> return -EINVAL;
> @@ -774,12 +777,9 @@ static int mt9v022_probe(struct i2c_client *client,
> return -ENOMEM;
>
> mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
> - mt9v022->client = client;
> i2c_set_clientdata(client, mt9v022);
>
> - icd = &mt9v022->icd;
> icd->ops = &mt9v022_ops;
> - icd->control = &client->dev;
> icd->x_min = 1;
> icd->y_min = 4;
> icd->x_current = 1;
> @@ -789,24 +789,24 @@ static int mt9v022_probe(struct i2c_client *client,
> icd->height_min = 32;
> icd->height_max = 480;
> icd->y_skip_top = 1;
> - icd->iface = icl->bus_id;
> -
> - ret = soc_camera_device_register(icd);
> - if (ret)
> - goto eisdr;
>
> - return 0;
> + ret = mt9v022_video_probe(icd, client);
> + if (ret) {
> + i2c_set_clientdata(client, NULL);
> + kfree(mt9v022);
> + }
>
> -eisdr:
> - kfree(mt9v022);
> return ret;
> }
>
> static int mt9v022_remove(struct i2c_client *client)
> {
> struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
> + struct soc_camera_device *icd = client->dev.platform_data;
>
> - soc_camera_device_unregister(&mt9v022->icd);
> + mt9v022_video_remove(icd);
> + i2c_set_clientdata(client, NULL);
> + client->driver = NULL;
> kfree(mt9v022);
>
> return 0;
> diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c
> index cb13faa..ed752c5 100644
> --- a/drivers/media/video/mx3_camera.c
> +++ b/drivers/media/video/mx3_camera.c
> @@ -502,18 +502,19 @@ static int mx3_camera_add_device(struct soc_camera_device *icd)
>
> mx3_camera_activate(mx3_cam, icd);
> ret = icd->ops->init(icd);
> - if (ret < 0) {
> - clk_disable(mx3_cam->clk);
> + if (ret < 0)
> goto einit;
> - }
>
> mx3_cam->icd = icd;
>
> + dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n",
> + icd->devnum);
> +
> + return 0;
> +
> einit:
> + clk_disable(mx3_cam->clk);
> ebusy:
> - if (!ret)
> - dev_info(&icd->dev, "MX3 Camera driver attached to camera %d\n",
> - icd->devnum);
>
> return ret;
> }
> @@ -946,9 +947,10 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
> camera_flags = icd->ops->query_bus_param(icd);
>
> common_flags = soc_camera_bus_param_compatible(camera_flags, bus_flags);
> + dev_dbg(ici->dev, "Flags cam: 0x%lx host: 0x%lx common: 0x%lx\n",
> + camera_flags, bus_flags, common_flags);
> if (!common_flags) {
> - dev_dbg(ici->dev, "no common flags: camera %lx, host %lx\n",
> - camera_flags, bus_flags);
> + dev_dbg(ici->dev, "no common flags");
> return -EINVAL;
> }
>
> @@ -1001,8 +1003,11 @@ static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt)
> SOCAM_DATAWIDTH_4;
>
> ret = icd->ops->set_bus_param(icd, common_flags);
> - if (ret < 0)
> + if (ret < 0) {
> + dev_dbg(ici->dev, "camera set_bus_param(%lx) returned %d\n",
> + common_flags, ret);
> return ret;
> + }
>
> /*
> * So far only gated clock mode is supported. Add a line
> @@ -1130,8 +1135,9 @@ static int mx3_camera_probe(struct platform_device *pdev)
> INIT_LIST_HEAD(&mx3_cam->capture);
> spin_lock_init(&mx3_cam->lock);
>
> - base = ioremap(res->start, res->end - res->start + 1);
> + base = ioremap(res->start, resource_size(res));
> if (!base) {
> + pr_err("Couldn't map %x@%x\n", resource_size(res), res->start);
> err = -ENOMEM;
> goto eioremap;
> }
> @@ -1218,3 +1224,4 @@ module_exit(mx3_camera_exit);
> MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver");
> MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
> MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:" MX3_CAM_DRV_NAME);
> diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
> index c0d9112..c90a918 100644
> --- a/drivers/media/video/ov772x.c
> +++ b/drivers/media/video/ov772x.c
> @@ -399,8 +399,6 @@ struct ov772x_win_size {
>
> struct ov772x_priv {
> struct ov772x_camera_info *info;
> - struct i2c_client *client;
> - struct soc_camera_device icd;
> const struct ov772x_color_format *fmt;
> const struct ov772x_win_size *win;
> int model;
> @@ -619,53 +617,56 @@ static int ov772x_reset(struct i2c_client *client)
>
> static int ov772x_init(struct soc_camera_device *icd)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> int ret = 0;
>
> - if (priv->info->link.power) {
> - ret = priv->info->link.power(&priv->client->dev, 1);
> + if (icl->power) {
> + ret = icl->power(&client->dev, 1);
> if (ret < 0)
> return ret;
> }
>
> - if (priv->info->link.reset)
> - ret = priv->info->link.reset(&priv->client->dev);
> + if (icl->reset)
> + ret = icl->reset(&client->dev);
>
> return ret;
> }
>
> static int ov772x_release(struct soc_camera_device *icd)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> int ret = 0;
>
> - if (priv->info->link.power)
> - ret = priv->info->link.power(&priv->client->dev, 0);
> + if (icl->power)
> + ret = icl->power(&client->dev, 0);
>
> return ret;
> }
>
> static int ov772x_start_capture(struct soc_camera_device *icd)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
>
> if (!priv->win || !priv->fmt) {
> dev_err(&icd->dev, "norm or win select error\n");
> return -EPERM;
> }
>
> - ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0);
> + ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0);
>
> dev_dbg(&icd->dev,
> - "format %s, win %s\n", priv->fmt->name, priv->win->name);
> + "format %s, win %s\n", priv->fmt->name, priv->win->name);
>
> return 0;
> }
>
> static int ov772x_stop_capture(struct soc_camera_device *icd)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> - ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
> return 0;
> }
>
> @@ -677,8 +678,9 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd,
>
> static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> - struct soc_camera_link *icl = &priv->info->link;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
> SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
> SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
> @@ -689,7 +691,8 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
> static int ov772x_get_control(struct soc_camera_device *icd,
> struct v4l2_control *ctrl)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
>
> switch (ctrl->id) {
> case V4L2_CID_VFLIP:
> @@ -705,7 +708,8 @@ static int ov772x_get_control(struct soc_camera_device *icd,
> static int ov772x_set_control(struct soc_camera_device *icd,
> struct v4l2_control *ctrl)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
> int ret = 0;
> u8 val;
>
> @@ -715,14 +719,14 @@ static int ov772x_set_control(struct soc_camera_device *icd,
> priv->flag_vflip = ctrl->value;
> if (priv->info->flags & OV772X_FLAG_VFLIP)
> val ^= VFLIP_IMG;
> - ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val);
> + ret = ov772x_mask_set(client, COM3, VFLIP_IMG, val);
> break;
> case V4L2_CID_HFLIP:
> val = ctrl->value ? HFLIP_IMG : 0x00;
> priv->flag_hflip = ctrl->value;
> if (priv->info->flags & OV772X_FLAG_HFLIP)
> val ^= HFLIP_IMG;
> - ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val);
> + ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val);
> break;
> }
>
> @@ -730,9 +734,10 @@ static int ov772x_set_control(struct soc_camera_device *icd,
> }
>
> static int ov772x_get_chip_id(struct soc_camera_device *icd,
> - struct v4l2_dbg_chip_ident *id)
> + struct v4l2_dbg_chip_ident *id)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
>
> id->ident = priv->model;
> id->revision = 0;
> @@ -744,14 +749,14 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd,
> static int ov772x_get_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> - int ret;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + int ret;
>
> reg->size = 1;
> if (reg->reg > 0xff)
> return -EINVAL;
>
> - ret = i2c_smbus_read_byte_data(priv->client, reg->reg);
> + ret = i2c_smbus_read_byte_data(client, reg->reg);
> if (ret < 0)
> return ret;
>
> @@ -763,13 +768,13 @@ static int ov772x_get_register(struct soc_camera_device *icd,
> static int ov772x_set_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->reg > 0xff ||
> reg->val > 0xff)
> return -EINVAL;
>
> - return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val);
> + return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
> }
> #endif
>
> @@ -793,9 +798,11 @@ ov772x_select_win(u32 width, u32 height)
> return win;
> }
>
> -static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> - u32 pixfmt)
> +static int ov772x_set_params(struct soc_camera_device *icd,
> + u32 width, u32 height, u32 pixfmt)
> {
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
> int ret = -EINVAL;
> u8 val;
> int i;
> @@ -810,6 +817,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> break;
> }
> }
> + dev_dbg(&icd->dev, "Using fmt %x #%d\n", pixfmt, i);
> if (!priv->fmt)
> goto ov772x_set_fmt_error;
>
> @@ -821,7 +829,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> /*
> * reset hardware
> */
> - ov772x_reset(priv->client);
> + ov772x_reset(client);
>
> /*
> * Edge Ctrl
> @@ -835,17 +843,17 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> * Remove it when manual mode.
> */
>
> - ret = ov772x_mask_set(priv->client, DSPAUTO, EDGE_ACTRL, 0x00);
> + ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00);
> if (ret < 0)
> goto ov772x_set_fmt_error;
>
> - ret = ov772x_mask_set(priv->client,
> + ret = ov772x_mask_set(client,
> EDGE_TRSHLD, EDGE_THRESHOLD_MASK,
> priv->info->edgectrl.threshold);
> if (ret < 0)
> goto ov772x_set_fmt_error;
>
> - ret = ov772x_mask_set(priv->client,
> + ret = ov772x_mask_set(client,
> EDGE_STRNGT, EDGE_STRENGTH_MASK,
> priv->info->edgectrl.strength);
> if (ret < 0)
> @@ -857,13 +865,13 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> *
> * set upper and lower limit
> */
> - ret = ov772x_mask_set(priv->client,
> + ret = ov772x_mask_set(client,
> EDGE_UPPER, EDGE_UPPER_MASK,
> priv->info->edgectrl.upper);
> if (ret < 0)
> goto ov772x_set_fmt_error;
>
> - ret = ov772x_mask_set(priv->client,
> + ret = ov772x_mask_set(client,
> EDGE_LOWER, EDGE_LOWER_MASK,
> priv->info->edgectrl.lower);
> if (ret < 0)
> @@ -873,7 +881,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> /*
> * set size format
> */
> - ret = ov772x_write_array(priv->client, priv->win->regs);
> + ret = ov772x_write_array(client, priv->win->regs);
> if (ret < 0)
> goto ov772x_set_fmt_error;
>
> @@ -882,7 +890,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> */
> val = priv->fmt->dsp3;
> if (val) {
> - ret = ov772x_mask_set(priv->client,
> + ret = ov772x_mask_set(client,
> DSP_CTRL3, UV_MASK, val);
> if (ret < 0)
> goto ov772x_set_fmt_error;
> @@ -901,7 +909,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> if (priv->flag_hflip)
> val ^= HFLIP_IMG;
>
> - ret = ov772x_mask_set(priv->client,
> + ret = ov772x_mask_set(client,
> COM3, SWAP_MASK | IMG_MASK, val);
> if (ret < 0)
> goto ov772x_set_fmt_error;
> @@ -910,7 +918,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
> * set COM7
> */
> val = priv->win->com7_bit | priv->fmt->com7;
> - ret = ov772x_mask_set(priv->client,
> + ret = ov772x_mask_set(client,
> COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK),
> val);
> if (ret < 0)
> @@ -920,7 +928,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
>
> ov772x_set_fmt_error:
>
> - ov772x_reset(priv->client);
> + ov772x_reset(client);
> priv->win = NULL;
> priv->fmt = NULL;
>
> @@ -930,22 +938,22 @@ ov772x_set_fmt_error:
> static int ov772x_set_crop(struct soc_camera_device *icd,
> struct v4l2_rect *rect)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
>
> if (!priv->fmt)
> return -EINVAL;
>
> - return ov772x_set_params(priv, rect->width, rect->height,
> + return ov772x_set_params(icd, rect->width, rect->height,
> priv->fmt->fourcc);
> }
>
> static int ov772x_set_fmt(struct soc_camera_device *icd,
> struct v4l2_format *f)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> struct v4l2_pix_format *pix = &f->fmt.pix;
>
> - return ov772x_set_params(priv, pix->width, pix->height,
> + return ov772x_set_params(icd, pix->width, pix->height,
> pix->pixelformat);
> }
>
> @@ -967,11 +975,13 @@ static int ov772x_try_fmt(struct soc_camera_device *icd,
> return 0;
> }
>
> -static int ov772x_video_probe(struct soc_camera_device *icd)
> +static int ov772x_video_probe(struct soc_camera_device *icd,
> + struct i2c_client *client)
> {
> - struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
> + struct ov772x_priv *priv = i2c_get_clientdata(client);
> u8 pid, ver;
> const char *devname;
> + int ret;
>
> /*
> * We must have a parent by now. And it cannot be a wrong one.
> @@ -993,11 +1003,16 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
> icd->formats = ov772x_fmt_lists;
> icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists);
>
> + /* Switch master clock on */
> + ret = soc_camera_video_start(icd, &client->dev);
> + if (ret)
> + return ret;
> +
> /*
> * check and show product ID and manufacturer ID
> */
> - pid = i2c_smbus_read_byte_data(priv->client, PID);
> - ver = i2c_smbus_read_byte_data(priv->client, VER);
> + pid = i2c_smbus_read_byte_data(client, PID);
> + ver = i2c_smbus_read_byte_data(client, VER);
>
> switch (VERSION(pid, ver)) {
> case OV7720:
> @@ -1011,7 +1026,8 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
> default:
> dev_err(&icd->dev,
> "Product ID error %x:%x\n", pid, ver);
> - return -ENODEV;
> + ret = -ENODEV;
> + goto ever;
> }
>
> dev_info(&icd->dev,
> @@ -1019,21 +1035,22 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
> devname,
> pid,
> ver,
> - i2c_smbus_read_byte_data(priv->client, MIDH),
> - i2c_smbus_read_byte_data(priv->client, MIDL));
> + i2c_smbus_read_byte_data(client, MIDH),
> + i2c_smbus_read_byte_data(client, MIDL));
> +
> + soc_camera_video_stop(icd);
>
> - return soc_camera_video_start(icd);
> +ever:
> + return ret;
> }
>
> static void ov772x_video_remove(struct soc_camera_device *icd)
> {
> - soc_camera_video_stop(icd);
> + icd->ops = NULL;
> }
>
> static struct soc_camera_ops ov772x_ops = {
> .owner = THIS_MODULE,
> - .probe = ov772x_video_probe,
> - .remove = ov772x_video_remove,
> .init = ov772x_init,
> .release = ov772x_release,
> .start_capture = ov772x_start_capture,
> @@ -1063,14 +1080,22 @@ static int ov772x_probe(struct i2c_client *client,
> {
> struct ov772x_priv *priv;
> struct ov772x_camera_info *info;
> - struct soc_camera_device *icd;
> + struct soc_camera_device *icd = client->dev.platform_data;
> struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> + struct soc_camera_link *icl;
> int ret;
>
> - info = client->dev.platform_data;
> - if (!info)
> + if (!icd) {
> + dev_err(&client->dev, "MT9M001: missing soc-camera data!\n");
> + return -EINVAL;
> + }
> +
> + icl = to_soc_camera_link(icd);
> + if (!icl)
> return -EINVAL;
>
> + info = container_of(icl, struct ov772x_camera_info, link);
> +
> if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
> dev_err(&adapter->dev,
> "I2C-Adapter doesn't support "
> @@ -1083,18 +1108,13 @@ static int ov772x_probe(struct i2c_client *client,
> return -ENOMEM;
>
> priv->info = info;
> - priv->client = client;
> i2c_set_clientdata(client, priv);
>
> - icd = &priv->icd;
> icd->ops = &ov772x_ops;
> - icd->control = &client->dev;
> icd->width_max = MAX_WIDTH;
> icd->height_max = MAX_HEIGHT;
> - icd->iface = priv->info->link.bus_id;
> -
> - ret = soc_camera_device_register(icd);
>
> + ret = ov772x_video_probe(icd, client);
> if (ret) {
> i2c_set_clientdata(client, NULL);
> kfree(priv);
> @@ -1106,8 +1126,9 @@ static int ov772x_probe(struct i2c_client *client,
> static int ov772x_remove(struct i2c_client *client)
> {
> struct ov772x_priv *priv = i2c_get_clientdata(client);
> + struct soc_camera_device *icd = client->dev.platform_data;
>
> - soc_camera_device_unregister(&priv->icd);
> + ov772x_video_remove(icd);
> i2c_set_clientdata(client, NULL);
> kfree(priv);
> return 0;
> diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c
> index 2da5eef..63964d0 100644
> --- a/drivers/media/video/pxa_camera.c
> +++ b/drivers/media/video/pxa_camera.c
> @@ -841,7 +841,8 @@ static void pxa_camera_init_videobuf(struct videobuf_queue *q,
> sizeof(struct pxa_buffer), icd);
> }
>
> -static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
> +static u32 mclk_get_divisor(struct platform_device *pdev,
> + struct pxa_camera_dev *pcdev)
> {
> unsigned long mclk = pcdev->mclk;
> u32 div;
> @@ -853,7 +854,7 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
> /* mclk <= ciclk / 4 (27.4.2) */
> if (mclk > lcdclk / 4) {
> mclk = lcdclk / 4;
> - dev_warn(pcdev->soc_host.dev, "Limiting master clock to %lu\n", mclk);
> + dev_warn(&pdev->dev, "Limiting master clock to %lu\n", mclk);
> }
>
> /* We verify mclk != 0, so if anyone breaks it, here comes their Oops */
> @@ -863,8 +864,8 @@ static u32 mclk_get_divisor(struct pxa_camera_dev *pcdev)
> if (pcdev->platform_flags & PXA_CAMERA_MCLK_EN)
> pcdev->mclk = lcdclk / (2 * (div + 1));
>
> - dev_dbg(pcdev->soc_host.dev, "LCD clock %luHz, target freq %luHz, "
> - "divisor %u\n", lcdclk, mclk, div);
> + dev_dbg(&pdev->dev, "LCD clock %luHz, target freq %luHz, divisor %u\n",
> + lcdclk, mclk, div);
>
> return div;
> }
> @@ -969,15 +970,20 @@ static int pxa_camera_add_device(struct soc_camera_device *icd)
> goto ebusy;
> }
>
> - dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
> - icd->devnum);
> -
> pxa_camera_activate(pcdev);
> ret = icd->ops->init(icd);
> + if (ret < 0)
> + goto einit;
> +
> + pcdev->icd = icd;
>
> - if (!ret)
> - pcdev->icd = icd;
> + dev_info(&icd->dev, "PXA Camera driver attached to camera %d\n",
> + icd->devnum);
>
> + return 0;
> +
> +einit:
> + pxa_camera_deactivate(pcdev);
> ebusy:
> return ret;
> }
> @@ -1599,7 +1605,7 @@ static int pxa_camera_probe(struct platform_device *pdev)
> pcdev->mclk = 20000000;
> }
>
> - pcdev->mclk_divisor = mclk_get_divisor(pcdev);
> + pcdev->mclk_divisor = mclk_get_divisor(pdev, pcdev);
>
> INIT_LIST_HEAD(&pcdev->capture);
> spin_lock_init(&pcdev->lock);
> @@ -1746,3 +1752,4 @@ module_exit(pxa_camera_exit);
> MODULE_DESCRIPTION("PXA27x SoC Camera Host driver");
> MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
> MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:" PXA_CAM_DRV_NAME);
> diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c
> index d369e84..ac9b467 100644
> --- a/drivers/media/video/sh_mobile_ceu_camera.c
> +++ b/drivers/media/video/sh_mobile_ceu_camera.c
> @@ -360,11 +360,13 @@ static int sh_mobile_ceu_add_device(struct soc_camera_device *icd)
> "SuperH Mobile CEU driver attached to camera %d\n",
> icd->devnum);
>
> + clk_enable(pcdev->clk);
> +
> ret = icd->ops->init(icd);
> - if (ret)
> + if (ret) {
> + clk_disable(pcdev->clk);
> goto err;
> -
> - clk_enable(pcdev->clk);
> + }
>
> ceu_write(pcdev, CAPSR, 1 << 16); /* reset */
> while (ceu_read(pcdev, CSTSR) & 1)
> @@ -398,10 +400,10 @@ static void sh_mobile_ceu_remove_device(struct soc_camera_device *icd)
> }
> spin_unlock_irqrestore(&pcdev->lock, flags);
>
> - clk_disable(pcdev->clk);
> -
> icd->ops->release(icd);
>
> + clk_disable(pcdev->clk);
> +
> dev_info(&icd->dev,
> "SuperH Mobile CEU driver detached from camera %d\n",
> icd->devnum);
> @@ -948,3 +950,4 @@ module_exit(sh_mobile_ceu_exit);
> MODULE_DESCRIPTION("SuperH Mobile CEU driver");
> MODULE_AUTHOR("Magnus Damm");
> MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:sh_mobile_ceu");
> diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
> index 03a6c29..22f544c 100644
> --- a/drivers/media/video/soc_camera.c
> +++ b/drivers/media/video/soc_camera.c
> @@ -16,19 +16,21 @@
> * published by the Free Software Foundation.
> */
>
> -#include <linux/module.h>
> -#include <linux/init.h>
> #include <linux/device.h>
> -#include <linux/list.h>
> #include <linux/err.h>
> +#include <linux/i2c.h>
> +#include <linux/init.h>
> +#include <linux/list.h>
> #include <linux/mutex.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> #include <linux/vmalloc.h>
>
> +#include <media/soc_camera.h>
> #include <media/v4l2-common.h>
> #include <media/v4l2-ioctl.h>
> #include <media/v4l2-dev.h>
> #include <media/videobuf-core.h>
> -#include <media/soc_camera.h>
>
> /* Default to VGA resolution */
> #define DEFAULT_WIDTH 640
> @@ -36,7 +38,7 @@
>
> static LIST_HEAD(hosts);
> static LIST_HEAD(devices);
> -static DEFINE_MUTEX(list_lock);
> +static DEFINE_MUTEX(list_lock); /* Protects the list of hosts */
>
> const struct soc_camera_data_format *soc_camera_format_by_fourcc(
> struct soc_camera_device *icd, unsigned int fourcc)
> @@ -207,6 +209,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv,
> return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK);
> }
>
> +/* Always entered with .video_lock held */
> static int soc_camera_init_user_formats(struct soc_camera_device *icd)
> {
> struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
> @@ -255,9 +258,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd)
> return 0;
> }
>
> +/* Always entered with .video_lock held */
> static void soc_camera_free_user_formats(struct soc_camera_device *icd)
> {
> + icd->current_fmt = NULL;
> vfree(icd->user_formats);
> + icd->user_formats = NULL;
> }
>
> /* Called with .vb_lock held */
> @@ -308,10 +314,6 @@ static int soc_camera_open(struct file *file)
> struct soc_camera_file *icf;
> int ret;
>
> - icf = vmalloc(sizeof(*icf));
> - if (!icf)
> - return -ENOMEM;
> -
> /*
> * It is safe to dereference these pointers now as long as a user has
> * the video device open - we are protected by the held cdev reference.
> @@ -319,8 +321,17 @@ static int soc_camera_open(struct file *file)
>
> vdev = video_devdata(file);
> icd = container_of(vdev->parent, struct soc_camera_device, dev);
> +
> + if (!icd->ops)
> + /* No device driver attached */
> + return -ENODEV;
> +
> ici = to_soc_camera_host(icd->dev.parent);
>
> + icf = vmalloc(sizeof(*icf));
> + if (!icf)
> + return -ENOMEM;
> +
> if (!try_module_get(icd->ops->owner)) {
> dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
> ret = -EINVAL;
> @@ -333,7 +344,7 @@ static int soc_camera_open(struct file *file)
> goto emgi;
> }
>
> - /* Protect against icd->remove() until we module_get() both drivers. */
> + /* Protect against icd->ops->remove() until we module_get() both drivers. */
> mutex_lock(&icd->video_lock);
>
> icf->icd = icd;
> @@ -348,11 +359,18 @@ static int soc_camera_open(struct file *file)
> .width = icd->width,
> .height = icd->height,
> .field = icd->field,
> - .pixelformat = icd->current_fmt->fourcc,
> - .colorspace = icd->current_fmt->colorspace,
> },
> };
>
> + ret = soc_camera_init_user_formats(icd);
> + if (ret < 0)
> + goto eiufmt;
> +
> + dev_dbg(&icd->dev, "Using fmt %x\n", icd->current_fmt->fourcc);
> +
> + f.fmt.pix.pixelformat = icd->current_fmt->fourcc;
> + f.fmt.pix.colorspace = icd->current_fmt->colorspace;
> +
> ret = ici->ops->add(icd);
> if (ret < 0) {
> dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
> @@ -381,6 +399,8 @@ static int soc_camera_open(struct file *file)
> esfmt:
> ici->ops->remove(icd);
> eiciadd:
> + soc_camera_free_user_formats(icd);
> +eiufmt:
> icd->use_count--;
> mutex_unlock(&icd->video_lock);
> module_put(ici->ops->owner);
> @@ -400,8 +420,10 @@ static int soc_camera_close(struct file *file)
>
> mutex_lock(&icd->video_lock);
> icd->use_count--;
> - if (!icd->use_count)
> + if (!icd->use_count) {
> ici->ops->remove(icd);
> + soc_camera_free_user_formats(icd);
> + }
>
> mutex_unlock(&icd->video_lock);
>
> @@ -762,29 +784,6 @@ static int soc_camera_s_register(struct file *file, void *fh,
> }
> #endif
>
> -static int device_register_link(struct soc_camera_device *icd)
> -{
> - int ret = dev_set_name(&icd->dev, "%u-%u", icd->iface, icd->devnum);
> -
> - if (!ret)
> - ret = device_register(&icd->dev);
> -
> - if (ret < 0) {
> - /* Prevent calling device_unregister() */
> - icd->dev.parent = NULL;
> - dev_err(&icd->dev, "Cannot register device: %d\n", ret);
> - /* Even if probe() was unsuccessful for all registered drivers,
> - * device_register() returns 0, and we add the link, just to
> - * document this camera's control device */
> - } else if (icd->control)
> - /* Have to sysfs_remove_link() before device_unregister()? */
> - if (sysfs_create_link(&icd->dev.kobj, &icd->control->kobj,
> - "control"))
> - dev_warn(&icd->dev,
> - "Failed creating the control symlink\n");
> - return ret;
> -}
> -
> /* So far this function cannot fail */
> static void scan_add_host(struct soc_camera_host *ici)
> {
> @@ -794,103 +793,78 @@ static void scan_add_host(struct soc_camera_host *ici)
>
> list_for_each_entry(icd, &devices, list) {
> if (icd->iface == ici->nr) {
> + int ret;
> icd->dev.parent = ici->dev;
> - device_register_link(icd);
> - }
> - }
> -
> - mutex_unlock(&list_lock);
> -}
> -
> -/* return: 0 if no match found or a match found and
> - * device_register() successful, error code otherwise */
> -static int scan_add_device(struct soc_camera_device *icd)
> -{
> - struct soc_camera_host *ici;
> - int ret = 0;
> -
> - mutex_lock(&list_lock);
> -
> - list_add_tail(&icd->list, &devices);
> -
> - /* Watch out for class_for_each_device / class_find_device API by
> - * Dave Young <hidave.darkstar@gmail.com> */
> - list_for_each_entry(ici, &hosts, list) {
> - if (icd->iface == ici->nr) {
> - ret = 1;
> - icd->dev.parent = ici->dev;
> - break;
> + dev_set_name(&icd->dev, "%u-%u", icd->iface,
> + icd->devnum);
> + ret = device_register(&icd->dev);
> + if (ret < 0) {
> + icd->dev.parent = NULL;
> + dev_err(&icd->dev,
> + "Cannot register device: %d\n", ret);
> + }
> }
> }
>
> mutex_unlock(&list_lock);
> -
> - if (ret)
> - ret = device_register_link(icd);
> -
> - return ret;
> }
>
> +static int video_dev_create(struct soc_camera_device *icd);
> +/* Called during host-driver probe */
> static int soc_camera_probe(struct device *dev)
> {
> struct soc_camera_device *icd = to_soc_camera_dev(dev);
> - struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> int ret;
> + struct i2c_client *client;
> + struct i2c_adapter *adap = i2c_get_adapter(icl->i2c_adapter_id);
>
> - /*
> - * Possible race scenario:
> - * modprobe <camera-host-driver> triggers __func__
> - * at this moment respective <camera-sensor-driver> gets rmmod'ed
> - * to protect take module references.
> - */
> -
> - if (!try_module_get(icd->ops->owner)) {
> - dev_err(&icd->dev, "Couldn't lock sensor driver.\n");
> - ret = -EINVAL;
> - goto emgd;
> - }
> -
> - if (!try_module_get(ici->ops->owner)) {
> - dev_err(&icd->dev, "Couldn't lock capture bus driver.\n");
> - ret = -EINVAL;
> - goto emgi;
> + if (!adap) {
> + ret = -ENODEV;
> + dev_err(dev, "Cannot get I2C adapter %d\n", icl->i2c_adapter_id);
> + goto ei2cga;
> }
>
> - mutex_lock(&icd->video_lock);
> + dev_info(dev, "Probing %s\n", dev_name(dev));
>
> - /* We only call ->add() here to activate and probe the camera.
> - * We shall ->remove() and deactivate it immediately afterwards. */
> - ret = ici->ops->add(icd);
> + ret = video_dev_create(icd);
> if (ret < 0)
> - goto eiadd;
> + goto evdc;
>
> - ret = icd->ops->probe(icd);
> - if (ret >= 0) {
> - const struct v4l2_queryctrl *qctrl;
> + client = i2c_new_device(adap, icl->board_info);
> + if (!client) {
> + ret = -ENOMEM;
> + goto ei2cnd;
> + }
>
> - qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
> - icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
> - qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
> - icd->exposure = qctrl ? qctrl->default_value :
> - (unsigned short)~0;
> + /*
> + * We set icd drvdata at two locations - here and in
> + * soc_camera_video_start(). Depending on the module loading /
> + * initialisation order one of these locations will be entered first
> + */
> + /* Use to_i2c_client(dev) to recover the i2c client */
> + dev_set_drvdata(&icd->dev, &client->dev);
>
> - ret = soc_camera_init_user_formats(icd);
> - if (ret < 0)
> - goto eiufmt;
> + /* Do we have to sysfs_remove_link() before device_unregister()? */
> + if (sysfs_create_link(&dev->kobj, &to_soc_camera_control(icd)->kobj,
> + "control"))
> + dev_warn(dev, "Failed creating the control symlink\n");
>
> - icd->height = DEFAULT_HEIGHT;
> - icd->width = DEFAULT_WIDTH;
> - icd->field = V4L2_FIELD_ANY;
> + ret = video_register_device(icd->vdev, VFL_TYPE_GRABBER, icd->vdev->minor);
> + if (ret < 0) {
> + dev_err(&icd->dev, "video_register_device failed: %d\n", ret);
> + goto evidregd;
> }
>
> -eiufmt:
> - ici->ops->remove(icd);
> -eiadd:
> - mutex_unlock(&icd->video_lock);
> - module_put(ici->ops->owner);
> -emgi:
> - module_put(icd->ops->owner);
> -emgd:
> + return 0;
> +
> +evidregd:
> + i2c_unregister_device(client);
> +ei2cnd:
> + video_device_release(icd->vdev);
> +evdc:
> + i2c_put_adapter(adap);
> +ei2cga:
> return ret;
> }
>
> @@ -899,11 +873,24 @@ emgd:
> static int soc_camera_remove(struct device *dev)
> {
> struct soc_camera_device *icd = to_soc_camera_dev(dev);
> + struct video_device *vdev = icd->vdev;
>
> - if (icd->ops->remove)
> - icd->ops->remove(icd);
> + BUG_ON(!dev->parent);
>
> - soc_camera_free_user_formats(icd);
> + if (vdev) {
> + mutex_lock(&icd->video_lock);
> + video_unregister_device(vdev);
> + icd->vdev = NULL;
> + mutex_unlock(&icd->video_lock);
> + }
> +
> + if (to_soc_camera_control(icd)) {
> + struct i2c_client *client =
> + to_i2c_client(to_soc_camera_control(icd));
> + dev_set_drvdata(&icd->dev, NULL);
> + i2c_unregister_device(client);
> + i2c_put_adapter(client->adapter);
> + }
>
> return 0;
> }
> @@ -998,10 +985,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
>
> list_for_each_entry(icd, &devices, list) {
> if (icd->dev.parent == ici->dev) {
> + /* The bus->remove will be called */
> device_unregister(&icd->dev);
> /* Not before device_unregister(), .remove
> * needs parent to call ici->ops->remove() */
> icd->dev.parent = NULL;
> +
> + /* If the host module is loaded again, device_register()
> + * would complain "already initialised" */
> memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj));
> }
> }
> @@ -1013,26 +1004,14 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
> EXPORT_SYMBOL(soc_camera_host_unregister);
>
> /* Image capture device */
> -int soc_camera_device_register(struct soc_camera_device *icd)
> +static int soc_camera_device_register(struct soc_camera_device *icd)
> {
> struct soc_camera_device *ix;
> int num = -1, i;
>
> - if (!icd || !icd->ops ||
> - !icd->ops->probe ||
> - !icd->ops->init ||
> - !icd->ops->release ||
> - !icd->ops->start_capture ||
> - !icd->ops->stop_capture ||
> - !icd->ops->set_crop ||
> - !icd->ops->set_fmt ||
> - !icd->ops->try_fmt ||
> - !icd->ops->query_bus_param ||
> - !icd->ops->set_bus_param)
> - return -EINVAL;
> -
> for (i = 0; i < 256 && num < 0; i++) {
> num = i;
> + /* Check if this index is available on this interface */
> list_for_each_entry(ix, &devices, list) {
> if (ix->iface == icd->iface && ix->devnum == i) {
> num = -1;
> @@ -1054,21 +1033,15 @@ int soc_camera_device_register(struct soc_camera_device *icd)
> icd->host_priv = NULL;
> mutex_init(&icd->video_lock);
>
> - return scan_add_device(icd);
> + list_add_tail(&icd->list, &devices);
> +
> + return 0;
> }
> -EXPORT_SYMBOL(soc_camera_device_register);
>
> -void soc_camera_device_unregister(struct soc_camera_device *icd)
> +static void soc_camera_device_unregister(struct soc_camera_device *icd)
> {
> - mutex_lock(&list_lock);
> list_del(&icd->list);
> -
> - /* The bus->remove will be eventually called */
> - if (icd->dev.parent)
> - device_unregister(&icd->dev);
> - mutex_unlock(&list_lock);
> }
> -EXPORT_SYMBOL(soc_camera_device_unregister);
>
> static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
> .vidioc_querycap = soc_camera_querycap,
> @@ -1099,22 +1072,13 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
> #endif
> };
>
> -/*
> - * Usually called from the struct soc_camera_ops .probe() method, i.e., from
> - * soc_camera_probe() above with .video_lock held
> - */
> -int soc_camera_video_start(struct soc_camera_device *icd)
> +static int video_dev_create(struct soc_camera_device *icd)
> {
> struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
> - int err = -ENOMEM;
> - struct video_device *vdev;
> + struct video_device *vdev = video_device_alloc();
>
> - if (!icd->dev.parent)
> - return -ENODEV;
> -
> - vdev = video_device_alloc();
> if (!vdev)
> - goto evidallocd;
> + return -ENOMEM;
> dev_dbg(ici->dev, "Allocated video_device %p\n", vdev);
>
> strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
> @@ -1125,40 +1089,103 @@ int soc_camera_video_start(struct soc_camera_device *icd)
> vdev->ioctl_ops = &soc_camera_ioctl_ops;
> vdev->release = video_device_release;
> vdev->minor = -1;
> - vdev->tvnorms = V4L2_STD_UNKNOWN,
> + vdev->tvnorms = V4L2_STD_UNKNOWN;
>
> - err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
> - if (err < 0) {
> - dev_err(vdev->parent, "video_register_device failed\n");
> - goto evidregd;
> - }
> icd->vdev = vdev;
>
> return 0;
> +}
>
> -evidregd:
> - video_device_release(vdev);
> -evidallocd:
> - return err;
> +/*
> + * Usually called from the struct soc_camera_ops .probe() method, i.e., from
> + * soc_camera_probe() above with .video_lock held
> + */
> +int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev)
> +{
> + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
> + const struct v4l2_queryctrl *qctrl;
> +
> + if (!icd->dev.parent)
> + return -ENODEV;
> +
> + if (!icd->ops ||
> + !icd->ops->init ||
> + !icd->ops->release ||
> + !icd->ops->start_capture ||
> + !icd->ops->stop_capture ||
> + !icd->ops->set_fmt ||
> + !icd->ops->try_fmt ||
> + !icd->ops->query_bus_param ||
> + !icd->ops->set_bus_param)
> + return -EINVAL;
> +
> + /* See comment in soc_camera_probe() */
> + dev_set_drvdata(&icd->dev, dev);
> +
> + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_GAIN);
> + icd->gain = qctrl ? qctrl->default_value : (unsigned short)~0;
> + qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
> + icd->exposure = qctrl ? qctrl->default_value : (unsigned short)~0;
> +
> + return ici->ops->add(icd);
> }
> EXPORT_SYMBOL(soc_camera_video_start);
>
> void soc_camera_video_stop(struct soc_camera_device *icd)
> {
> - struct video_device *vdev = icd->vdev;
> + struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
>
> dev_dbg(&icd->dev, "%s\n", __func__);
>
> - if (!icd->dev.parent || !vdev)
> - return;
> -
> - mutex_lock(&icd->video_lock);
> - video_unregister_device(vdev);
> - icd->vdev = NULL;
> - mutex_unlock(&icd->video_lock);
> + ici->ops->remove(icd);
> }
> EXPORT_SYMBOL(soc_camera_video_stop);
>
> +static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
> +{
> + struct soc_camera_link *icl = pdev->dev.platform_data;
> + struct soc_camera_device *icd;
> +
> + if (!icl)
> + return -EINVAL;
> +
> + icd = kzalloc(sizeof(*icd), GFP_KERNEL);
> + if (!icd)
> + return -ENOMEM;
> +
> + icd->iface = icl->bus_id;
> + icl->board_info->platform_data = icd;
> + platform_set_drvdata(pdev, icd);
> + icd->dev.platform_data = icl;
> +
> + return soc_camera_device_register(icd);
> +}
> +
> +/* Only called on rmmod for each platform device, since they are not
> + * hot-pluggable. Now we know, that all our users - hosts and devices have
> + * been unloaded already */
> +static int __devexit soc_camera_pdrv_remove(struct platform_device *pdev)
> +{
> + struct soc_camera_device *icd = platform_get_drvdata(pdev);
> +
> + if (!icd)
> + return -EINVAL;
> +
> + soc_camera_device_unregister(icd);
> +
> + kfree(icd);
> +
> + return 0;
> +}
> +
> +static struct platform_driver soc_camera_pdrv = {
> + .remove = __exit_p(soc_camera_pdrv_remove),
> + .driver = {
> + .name = "soc-camera-pdrv",
> + .owner = THIS_MODULE,
> + },
> +};
> +
> static int __init soc_camera_init(void)
> {
> int ret = bus_register(&soc_camera_bus_type);
> @@ -1168,8 +1195,14 @@ static int __init soc_camera_init(void)
> if (ret)
> goto edrvr;
>
> + ret = platform_driver_probe(&soc_camera_pdrv, soc_camera_pdrv_probe);
> + if (ret)
> + goto epdr;
> +
> return 0;
>
> +epdr:
> + driver_unregister(&ic_drv);
> edrvr:
> bus_unregister(&soc_camera_bus_type);
> return ret;
> @@ -1177,6 +1210,7 @@ edrvr:
>
> static void __exit soc_camera_exit(void)
> {
> + platform_driver_unregister(&soc_camera_pdrv);
> driver_unregister(&ic_drv);
> bus_unregister(&soc_camera_bus_type);
> }
> @@ -1187,3 +1221,4 @@ module_exit(soc_camera_exit);
> MODULE_DESCRIPTION("Image capture bus driver");
> MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
> MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:soc-camera-pdrv");
> diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c
> index c486763..021f9f1 100644
> --- a/drivers/media/video/soc_camera_platform.c
> +++ b/drivers/media/video/soc_camera_platform.c
> @@ -20,49 +20,52 @@
> #include <media/soc_camera.h>
> #include <media/soc_camera_platform.h>
>
> +static const char drv_name[] = "soc_camera_platform";
> +
> struct soc_camera_platform_priv {
> struct soc_camera_platform_info *info;
> - struct soc_camera_device icd;
> struct soc_camera_data_format format;
> };
>
> -static struct soc_camera_platform_info *
> -soc_camera_platform_get_info(struct soc_camera_device *icd)
> +static struct soc_camera_platform_info *i2c_to_info(struct i2c_client *client)
> {
> - struct soc_camera_platform_priv *priv;
> - priv = container_of(icd, struct soc_camera_platform_priv, icd);
> + struct soc_camera_platform_priv *priv = i2c_get_clientdata(client);
> return priv->info;
> }
>
> static int soc_camera_platform_init(struct soc_camera_device *icd)
> {
> - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_platform_info *p = i2c_to_info(client);
>
> - if (p->power)
> - p->power(1);
> + if (p->link.power)
> + p->link.power(&client->dev, 1);
>
> return 0;
> }
>
> static int soc_camera_platform_release(struct soc_camera_device *icd)
> {
> - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_platform_info *p = i2c_to_info(client);
>
> - if (p->power)
> - p->power(0);
> + if (p->link.power)
> + p->link.power(&client->dev, 0);
>
> return 0;
> }
>
> static int soc_camera_platform_start_capture(struct soc_camera_device *icd)
> {
> - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_platform_info *p = i2c_to_info(client);
> return p->set_capture(p, 1);
> }
>
> static int soc_camera_platform_stop_capture(struct soc_camera_device *icd)
> {
> - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_platform_info *p = i2c_to_info(client);
> return p->set_capture(p, 0);
> }
>
> @@ -75,7 +78,8 @@ static int soc_camera_platform_set_bus_param(struct soc_camera_device *icd,
> static unsigned long
> soc_camera_platform_query_bus_param(struct soc_camera_device *icd)
> {
> - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_platform_info *p = i2c_to_info(client);
> return p->bus_param;
> }
>
> @@ -94,7 +98,8 @@ static int soc_camera_platform_set_fmt(struct soc_camera_device *icd,
> static int soc_camera_platform_try_fmt(struct soc_camera_device *icd,
> struct v4l2_format *f)
> {
> - struct soc_camera_platform_info *p = soc_camera_platform_get_info(icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_platform_info *p = i2c_to_info(client);
> struct v4l2_pix_format *pix = &f->fmt.pix;
>
> pix->width = p->format.width;
> @@ -102,31 +107,30 @@ static int soc_camera_platform_try_fmt(struct soc_camera_device *icd,
> return 0;
> }
>
> -static int soc_camera_platform_video_probe(struct soc_camera_device *icd)
> +static int soc_camera_platform_video_probe(struct soc_camera_device *icd,
> + struct i2c_client *client)
> {
> - struct soc_camera_platform_priv *priv;
> - priv = container_of(icd, struct soc_camera_platform_priv, icd);
> + struct soc_camera_platform_priv *priv = i2c_get_clientdata(client);
> + struct soc_camera_platform_info *p = priv->info;
>
> - priv->format.name = priv->info->format_name;
> - priv->format.depth = priv->info->format_depth;
> - priv->format.fourcc = priv->info->format.pixelformat;
> - priv->format.colorspace = priv->info->format.colorspace;
> + priv->format.name = p->format_name;
> + priv->format.depth = p->format_depth;
> + priv->format.fourcc = p->format.pixelformat;
> + priv->format.colorspace = p->format.colorspace;
>
> icd->formats = &priv->format;
> icd->num_formats = 1;
>
> - return soc_camera_video_start(icd);
> + return 0;
> }
>
> static void soc_camera_platform_video_remove(struct soc_camera_device *icd)
> {
> - soc_camera_video_stop(icd);
> + icd->ops = NULL;
> }
>
> static struct soc_camera_ops soc_camera_platform_ops = {
> .owner = THIS_MODULE,
> - .probe = soc_camera_platform_video_probe,
> - .remove = soc_camera_platform_video_remove,
> .init = soc_camera_platform_init,
> .release = soc_camera_platform_release,
> .start_capture = soc_camera_platform_start_capture,
> @@ -138,66 +142,85 @@ static struct soc_camera_ops soc_camera_platform_ops = {
> .query_bus_param = soc_camera_platform_query_bus_param,
> };
>
> -static int soc_camera_platform_probe(struct platform_device *pdev)
> +static int soc_camera_platform_probe(struct i2c_client *client,
> + const struct i2c_device_id *did)
> {
> struct soc_camera_platform_priv *priv;
> struct soc_camera_platform_info *p;
> - struct soc_camera_device *icd;
> + struct soc_camera_device *icd = client->dev.platform_data;
> + struct soc_camera_link *icl;
> int ret;
>
> - p = pdev->dev.platform_data;
> - if (!p)
> + if (!icd) {
> + dev_err(&client->dev, "%s: missing soc-camera data!\n", drv_name);
> return -EINVAL;
> + }
> +
> + icl = dev_get_drvdata(&icd->dev);
> + if (!icl) {
> + dev_err(&client->dev, "%s driver needs platform data\n", drv_name);
> + return -EINVAL;
> + }
> +
> + p = container_of(icl, struct soc_camera_platform_info, link);
>
> priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> if (!priv)
> return -ENOMEM;
>
> priv->info = p;
> - platform_set_drvdata(pdev, priv);
> + i2c_set_clientdata(client, priv);
>
> - icd = &priv->icd;
> icd->ops = &soc_camera_platform_ops;
> - icd->control = &pdev->dev;
> icd->width_min = 0;
> - icd->width_max = priv->info->format.width;
> + icd->width_max = p->format.width;
> icd->height_min = 0;
> - icd->height_max = priv->info->format.height;
> + icd->height_max = p->format.height;
> icd->y_skip_top = 0;
> - icd->iface = priv->info->iface;
>
> - ret = soc_camera_device_register(icd);
> - if (ret)
> + ret = soc_camera_platform_video_probe(icd, client);
> + if (ret) {
> + i2c_set_clientdata(client, NULL);
> kfree(priv);
> + }
>
> return ret;
> }
>
> -static int soc_camera_platform_remove(struct platform_device *pdev)
> +static int soc_camera_platform_remove(struct i2c_client *client)
> {
> - struct soc_camera_platform_priv *priv = platform_get_drvdata(pdev);
> + struct soc_camera_platform_priv *priv = i2c_get_clientdata(client);
> + struct soc_camera_device *icd = client->dev.platform_data;
>
> - soc_camera_device_unregister(&priv->icd);
> + soc_camera_platform_video_remove(icd);
> + i2c_set_clientdata(client, NULL);
> kfree(priv);
> return 0;
> }
>
> -static struct platform_driver soc_camera_platform_driver = {
> +static const struct i2c_device_id soc_camera_platform_id[] = {
> + { "soc_camera_platform", 0 },
> + { }
> +};
> +MODULE_DEVICE_TABLE(i2c, soc_camera_platform_id);
> +
> +static struct i2c_driver soc_camera_platform_driver = {
> .driver = {
> .name = "soc_camera_platform",
> },
> .probe = soc_camera_platform_probe,
> .remove = soc_camera_platform_remove,
> + .id_table = soc_camera_platform_id,
> };
>
> static int __init soc_camera_platform_module_init(void)
> {
> - return platform_driver_register(&soc_camera_platform_driver);
> + return i2c_add_driver(&soc_camera_platform_driver);
> }
>
> static void __exit soc_camera_platform_module_exit(void)
> {
> - platform_driver_unregister(&soc_camera_platform_driver);
> + i2c_del_driver(&soc_camera_platform_driver);
> }
>
> module_init(soc_camera_platform_module_init);
> @@ -206,3 +229,4 @@ module_exit(soc_camera_platform_module_exit);
> MODULE_DESCRIPTION("SoC Camera Platform driver");
> MODULE_AUTHOR("Magnus Damm");
> MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:soc_camera_platform");
> diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c
> index a399476..419e596 100644
> --- a/drivers/media/video/tw9910.c
> +++ b/drivers/media/video/tw9910.c
> @@ -224,8 +224,6 @@ struct tw9910_hsync_ctrl {
>
> struct tw9910_priv {
> struct tw9910_video_info *info;
> - struct i2c_client *client;
> - struct soc_camera_device icd;
> const struct tw9910_scale_ctrl *scale;
> };
>
> @@ -511,35 +509,38 @@ tw9910_select_norm(struct soc_camera_device *icd, u32 width, u32 height)
> */
> static int tw9910_init(struct soc_camera_device *icd)
> {
> - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> int ret = 0;
>
> - if (priv->info->link.power) {
> - ret = priv->info->link.power(&priv->client->dev, 1);
> + if (icl->power) {
> + ret = icl->power(&client->dev, 1);
> if (ret < 0)
> return ret;
> }
>
> - if (priv->info->link.reset)
> - ret = priv->info->link.reset(&priv->client->dev);
> + if (icl->reset)
> + ret = icl->reset(&client->dev);
>
> return ret;
> }
>
> static int tw9910_release(struct soc_camera_device *icd)
> {
> - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> int ret = 0;
>
> - if (priv->info->link.power)
> - ret = priv->info->link.power(&priv->client->dev, 0);
> + if (icl->power)
> + ret = icl->power(&client->dev, 0);
>
> return ret;
> }
>
> static int tw9910_start_capture(struct soc_camera_device *icd)
> {
> - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct tw9910_priv *priv = i2c_get_clientdata(client);
>
> if (!priv->scale) {
> dev_err(&icd->dev, "norm select error\n");
> @@ -567,8 +568,9 @@ static int tw9910_set_bus_param(struct soc_camera_device *icd,
>
> static unsigned long tw9910_query_bus_param(struct soc_camera_device *icd)
> {
> - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
> - struct soc_camera_link *icl = priv->client->dev.platform_data;
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct tw9910_priv *priv = i2c_get_clientdata(client);
> + struct soc_camera_link *icl = to_soc_camera_link(icd);
> unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
> SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
> SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
> @@ -610,13 +612,13 @@ static int tw9910_enum_input(struct soc_camera_device *icd,
> static int tw9910_get_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> int ret;
>
> if (reg->reg > 0xff)
> return -EINVAL;
>
> - ret = i2c_smbus_read_byte_data(priv->client, reg->reg);
> + ret = i2c_smbus_read_byte_data(client, reg->reg);
> if (ret < 0)
> return ret;
>
> @@ -631,20 +633,21 @@ static int tw9910_get_register(struct soc_camera_device *icd,
> static int tw9910_set_register(struct soc_camera_device *icd,
> struct v4l2_dbg_register *reg)
> {
> - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
>
> if (reg->reg > 0xff ||
> reg->val > 0xff)
> return -EINVAL;
>
> - return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val);
> + return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
> }
> #endif
>
> static int tw9910_set_crop(struct soc_camera_device *icd,
> struct v4l2_rect *rect)
> {
> - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
> + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
> + struct tw9910_priv *priv = i2c_get_clientdata(client);
> int ret = -EINVAL;
> u8 val;
>
> @@ -658,8 +661,8 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
> /*
> * reset hardware
> */
> - tw9910_reset(priv->client);
> - ret = tw9910_write_array(priv->client, tw9910_default_regs);
> + tw9910_reset(client);
> + ret = tw9910_write_array(client, tw9910_default_regs);
> if (ret < 0)
> goto tw9910_set_fmt_error;
>
> @@ -670,7 +673,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
> if (SOCAM_DATAWIDTH_16 == priv->info->buswidth)
> val = LEN;
>
> - ret = tw9910_mask_set(priv->client, OPFORM, LEN, val);
> + ret = tw9910_mask_set(client, OPFORM, LEN, val);
> if (ret < 0)
> goto tw9910_set_fmt_error;
>
> @@ -698,28 +701,28 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
> val = 0;
> }
>
> - ret = tw9910_mask_set(priv->client, VBICNTL, RTSEL_MASK, val);
> + ret = tw9910_mask_set(client, VBICNTL, RTSEL_MASK, val);
> if (ret < 0)
> goto tw9910_set_fmt_error;
>
> /*
> * set scale
> */
> - ret = tw9910_set_scale(priv->client, priv->scale);
> + ret = tw9910_set_scale(client, priv->scale);
> if (ret < 0)
> goto tw9910_set_fmt_error;
>
> /*
> * set cropping
> */
> - ret = tw9910_set_cropping(priv->client, &tw9910_cropping_ctrl);
> + ret = tw9910_set_cropping(client, &tw9910_cropping_ctrl);
> if (ret < 0)
> goto tw9910_set_fmt_error;
>
> /*
> * set hsync
> */
> - ret = tw9910_set_hsync(priv->client, &tw9910_hsync_ctrl);
> + ret = tw9910_set_hsync(client, &tw9910_hsync_ctrl);
> if (ret < 0)
> goto tw9910_set_fmt_error;
>
> @@ -727,7 +730,7 @@ static int tw9910_set_crop(struct soc_camera_device *icd,
>
> tw9910_set_fmt_error:
>
> - tw9910_reset(priv->client);
> + tw9910_reset(client);
> priv->scale = NULL;
>
> return ret;
> @@ -784,9 +787,10 @@ static int tw9910_try_fmt(struct soc_camera_device *icd,
> return 0;
> }
>
> -static int tw9910_video_probe(struct soc_camera_device *icd)
> +static int tw9910_video_probe(struct soc_camera_device *icd,
> + struct i2c_client *client)
> {
> - struct tw9910_priv *priv = container_of(icd, struct tw9910_priv, icd);
> + struct tw9910_priv *priv = i2c_get_clientdata(client);
> s32 val;
> int ret;
>
> @@ -810,10 +814,18 @@ static int tw9910_video_probe(struct soc_camera_device *icd)
> icd->formats = tw9910_color_fmt;
> icd->num_formats = ARRAY_SIZE(tw9910_color_fmt);
>
> + /* Switch master clock on */
> + ret = soc_camera_video_start(icd, &client->dev);
> + if (ret)
> + return ret;
> +
> /*
> * check and show Product ID
> */
> - val = i2c_smbus_read_byte_data(priv->client, ID);
> + val = i2c_smbus_read_byte_data(client, ID);
> +
> + soc_camera_video_stop(icd);
> +
> if (0x0B != GET_ID(val) ||
> 0x00 != GET_ReV(val)) {
> dev_err(&icd->dev,
> @@ -824,10 +836,6 @@ static int tw9910_video_probe(struct soc_camera_device *icd)
> dev_info(&icd->dev,
> "tw9910 Product ID %0x:%0x\n", GET_ID(val), GET_ReV(val));
>
> - ret = soc_camera_video_start(icd);
> - if (ret < 0)
> - return ret;
> -
> icd->vdev->tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL;
> icd->vdev->current_norm = V4L2_STD_NTSC;
>
> @@ -836,13 +844,11 @@ static int tw9910_video_probe(struct soc_camera_device *icd)
>
> static void tw9910_video_remove(struct soc_camera_device *icd)
> {
> - soc_camera_video_stop(icd);
> + icd->ops = NULL;
> }
>
> static struct soc_camera_ops tw9910_ops = {
> .owner = THIS_MODULE,
> - .probe = tw9910_video_probe,
> - .remove = tw9910_video_remove,
> .init = tw9910_init,
> .release = tw9910_release,
> .start_capture = tw9910_start_capture,
> @@ -871,16 +877,25 @@ static int tw9910_probe(struct i2c_client *client,
> {
> struct tw9910_priv *priv;
> struct tw9910_video_info *info;
> - struct soc_camera_device *icd;
> + struct soc_camera_device *icd = client->dev.platform_data;
> + struct i2c_adapter *adapter =
> + to_i2c_adapter(client->dev.parent);
> + struct soc_camera_link *icl;
> const struct tw9910_scale_ctrl *scale;
> int i, ret;
>
> - info = client->dev.platform_data;
> - if (!info)
> + if (!icd) {
> + dev_err(&client->dev, "TW9910: missing soc-camera data!\n");
> return -EINVAL;
> + }
>
> - if (!i2c_check_functionality(to_i2c_adapter(client->dev.parent),
> - I2C_FUNC_SMBUS_BYTE_DATA)) {
> + icl = to_soc_camera_link(icd);
> + if (!icl)
> + return -EINVAL;
> +
> + info = container_of(icl, struct tw9910_video_info, link);
> +
> + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
> dev_err(&client->dev,
> "I2C-Adapter doesn't support "
> "I2C_FUNC_SMBUS_BYTE_DATA\n");
> @@ -892,12 +907,9 @@ static int tw9910_probe(struct i2c_client *client,
> return -ENOMEM;
>
> priv->info = info;
> - priv->client = client;
> i2c_set_clientdata(client, priv);
>
> - icd = &priv->icd;
> icd->ops = &tw9910_ops;
> - icd->control = &client->dev;
> icd->iface = info->link.bus_id;
>
> /*
> @@ -923,8 +935,7 @@ static int tw9910_probe(struct i2c_client *client,
> icd->height_min = min(scale[i].height, icd->height_min);
> }
>
> - ret = soc_camera_device_register(icd);
> -
> + ret = tw9910_video_probe(icd, client);
> if (ret) {
> i2c_set_clientdata(client, NULL);
> kfree(priv);
> @@ -936,8 +947,9 @@ static int tw9910_probe(struct i2c_client *client,
> static int tw9910_remove(struct i2c_client *client)
> {
> struct tw9910_priv *priv = i2c_get_clientdata(client);
> + struct soc_camera_device *icd = client->dev.platform_data;
>
> - soc_camera_device_unregister(&priv->icd);
> + tw9910_video_remove(icd);
> i2c_set_clientdata(client, NULL);
> kfree(priv);
> return 0;
> diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
> index bef5e81..977326e 100644
> --- a/include/media/soc_camera.h
> +++ b/include/media/soc_camera.h
> @@ -12,6 +12,7 @@
> #ifndef SOC_CAMERA_H
> #define SOC_CAMERA_H
>
> +#include <linux/i2c.h>
> #include <linux/mutex.h>
> #include <linux/pm.h>
> #include <linux/videodev2.h>
> @@ -20,7 +21,6 @@
> struct soc_camera_device {
> struct list_head list;
> struct device dev;
> - struct device *control;
> unsigned short width; /* Current window */
> unsigned short height; /* sizes */
> unsigned short x_min; /* Camera capabilities */
> @@ -97,6 +97,8 @@ struct soc_camera_link {
> int bus_id;
> /* Per camera SOCAM_SENSOR_* bus flags */
> unsigned long flags;
> + int i2c_adapter_id;
> + struct i2c_board_info *board_info;
> /* Optional callbacks to power on or off and reset the sensor */
> int (*power)(struct device *, int);
> int (*reset)(struct device *);
> @@ -120,17 +122,25 @@ static inline struct soc_camera_host *to_soc_camera_host(struct device *dev)
> return dev_get_drvdata(dev);
> }
>
> -extern int soc_camera_host_register(struct soc_camera_host *ici);
> -extern void soc_camera_host_unregister(struct soc_camera_host *ici);
> -extern int soc_camera_device_register(struct soc_camera_device *icd);
> -extern void soc_camera_device_unregister(struct soc_camera_device *icd);
> +static inline struct soc_camera_link *to_soc_camera_link(struct soc_camera_device *icd)
> +{
> + return icd->dev.platform_data;
> +}
>
> -extern int soc_camera_video_start(struct soc_camera_device *icd);
> -extern void soc_camera_video_stop(struct soc_camera_device *icd);
> +static inline struct device *to_soc_camera_control(struct soc_camera_device *icd)
> +{
> + return dev_get_drvdata(&icd->dev);
> +}
>
> -extern const struct soc_camera_data_format *soc_camera_format_by_fourcc(
> +int soc_camera_host_register(struct soc_camera_host *ici);
> +void soc_camera_host_unregister(struct soc_camera_host *ici);
> +
> +int soc_camera_video_start(struct soc_camera_device *icd, struct device *dev);
> +void soc_camera_video_stop(struct soc_camera_device *icd);
> +
> +const struct soc_camera_data_format *soc_camera_format_by_fourcc(
> struct soc_camera_device *icd, unsigned int fourcc);
> -extern const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
> +const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
> struct soc_camera_device *icd, unsigned int fourcc);
>
> struct soc_camera_data_format {
> @@ -159,8 +169,6 @@ struct soc_camera_format_xlate {
>
> struct soc_camera_ops {
> struct module *owner;
> - int (*probe)(struct soc_camera_device *);
> - void (*remove)(struct soc_camera_device *);
> int (*suspend)(struct soc_camera_device *, pm_message_t state);
> int (*resume)(struct soc_camera_device *);
> int (*init)(struct soc_camera_device *);
> diff --git a/include/media/soc_camera_platform.h b/include/media/soc_camera_platform.h
> index 1d092b4..db7ff89 100644
> --- a/include/media/soc_camera_platform.h
> +++ b/include/media/soc_camera_platform.h
> @@ -14,13 +14,12 @@
> #include <linux/videodev2.h>
>
> struct soc_camera_platform_info {
> - int iface;
> - char *format_name;
> + const char *format_name;
> unsigned long format_depth;
> struct v4l2_pix_format format;
> unsigned long bus_param;
> - void (*power)(int);
> int (*set_capture)(struct soc_camera_platform_info *info, int enable);
> + struct soc_camera_link link;
> };
>
> #endif /* __SOC_CAMERA_H__ */
^ permalink raw reply [flat|nested] 46+ messages in thread