Skip to contentSkip to conversation

PATCH: soc-camera: Support multiple camera chips per host

PATCH Sascha Hauer 1 participant 2 messages Jul 15, 2008 Media (V4L/DVB)

lore
Share & tools
lore
#0 lore raw

Hi,

soc-camera already supports more than one camera chip per host which can be used exclusively. This patch adds a hook for the board code to switch between different cameras.

---
 drivers/media/video/soc_camera.c |   20 ++++++++++++++++----
 include/media/soc_camera.h       |    7 ++++++-
 2 files changed, 22 insertions(+), 5 deletions(-)
media/video/soc_camera.c renamed from media/video/soc_camera.c.orig +16 -4
Index: drivers/media/video/soc_camera.c
===================================================================
@@ -218,6 +218,9 @@ static int soc_camera_open(struct inode 
 
 	icd->use_count++;
 
+	if (icd->link->activate)
+		icd->link->activate(icd->link, 1);
+
 	/* Now we really have to activate the camera */
 	if (icd->use_count == 1) {
 		ret = ici->ops->add(icd);
@@ -269,6 +272,8 @@ static int soc_camera_close(struct inode
 	icd->use_count--;
 	if (!icd->use_count)
 		ici->ops->remove(icd);
+	if (icd->link->activate)
+		icd->link->activate(icd->link, 0);
 	icf->lock = NULL;
 	if (ici->ops->spinlock_free)
 		ici->ops->spinlock_free(lock);
@@ -670,7 +675,7 @@ static void scan_add_host(struct soc_cam
 	mutex_lock(&list_lock);
 
 	list_for_each_entry(icd, &devices, list) {
-		if (icd->iface == ici->nr) {
+		if (icd->link->bus_id == ici->nr) {
 			icd->dev.parent = &ici->dev;
 			device_register_link(icd);
 		}
@@ -693,7 +698,7 @@ static int scan_add_device(struct soc_ca
 	/* Watch out for class_for_each_device / class_find_device API by
 	 * Dave Young <[email protected]> */
 	list_for_each_entry(ici, &hosts, list) {
-		if (icd->iface == ici->nr) {
+		if (icd->link->bus_id == ici->nr) {
 			ret = 1;
 			icd->dev.parent = &ici->dev;
 			break;
@@ -718,6 +723,9 @@ static int soc_camera_probe(struct devic
 	if (!icd->ops->probe)
 		return -ENODEV;
 
+	if (icd->link->activate)
+		icd->link->activate(icd->link, 1);
+
 	/* We only call ->add() here to activate and probe the camera.
 	 * We shall ->remove() and deactivate it immediately afterwards. */
 	ret = ici->ops->add(icd);
@@ -736,6 +744,9 @@ static int soc_camera_probe(struct devic
 	}
 	ici->ops->remove(icd);
 
+	if (icd->link->activate)
+		icd->link->activate(icd->link, 0);
+
 	return ret;
 }
 
@@ -866,7 +877,8 @@ int soc_camera_device_register(struct so
 	for (i = 0; i < 256 && num < 0; i++) {
 		num = i;
 		list_for_each_entry(ix, &devices, list) {
-			if (ix->iface == icd->iface && ix->devnum == i) {
+			if (ix->link->bus_id == icd->link->bus_id &&
+					ix->devnum == i) {
 				num = -1;
 				break;
 			}
@@ -881,7 +893,7 @@ int soc_camera_device_register(struct so
 	icd->devnum = num;
 	icd->dev.bus = &soc_camera_bus_type;
 	snprintf(icd->dev.bus_id, sizeof(icd->dev.bus_id),
-		 "%u-%u", icd->iface, icd->devnum);
+		 "%u-%u", icd->link->bus_id, icd->devnum);
 
 	icd->dev.release = dummy_release;
 
media/soc_camera.h renamed from media/soc_camera.h.orig +6 -1
Index: include/media/soc_camera.h
===================================================================
@@ -15,6 +15,8 @@
 #include <linux/videodev2.h>
 #include <media/videobuf-dma-sg.h>
 
+struct soc_camera_link;
+
 struct soc_camera_device {
 	struct list_head list;
 	struct device dev;
@@ -32,7 +34,7 @@ struct soc_camera_device {
 	unsigned short y_skip_top;	/* Lines to skip at the top */
 	unsigned short gain;
 	unsigned short exposure;
-	unsigned char iface;		/* Host number */
+	struct soc_camera_link *link;	/* Link to this camera */
 	unsigned char devnum;		/* Device number per host */
 	unsigned char buswidth;		/* See comment in .c */
 	struct soc_camera_ops *ops;
@@ -83,6 +85,9 @@ struct soc_camera_link {
 	int bus_id;
 	/* GPIO number to switch between 8 and 10 bit modes */
 	unsigned int gpio;
+	/* (de-)activate this camera. Can be left empty if only one camera is
+	 * connected to this bus. */
+	void (*activate)(struct soc_camera_link *, int);
 };
 
 static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev)
Signature · 9 lines
 Pengutronix - Linux Solutions for Science and Industry
   Handelsregister:  Amtsgericht Hildesheim, HRA 2686
     Hannoversche Str. 2, 31134 Hildesheim, Germany
   Phone: +49-5121-206917-0 |  Fax: +49-5121-206917-9

--
video4linux-list mailing list
Unsubscribe mailto:[email protected]?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list
#1 lore raw

Excuse me for sending -p0 patches. Here's an updated version:

soc-camera already supports more than one camera chip per host which can be used exclusively. This patch adds a hook for the board code to switch between different cameras.

---
 drivers/media/video/mt9m001.c    |    4 ++--
 drivers/media/video/mt9v022.c    |    4 ++--
 drivers/media/video/soc_camera.c |   20 ++++++++++++++++----
 include/media/soc_camera.h       |    7 ++++++-
 4 files changed, 26 insertions(+), 9 deletions(-)
drivers/media/video/soc_camera.c +16 -4
Index: linux-2.6/drivers/media/video/soc_camera.c
===================================================================
@@ -218,6 +218,9 @@ static int soc_camera_open(struct inode 
 
 	icd->use_count++;
 
+	if (icd->link->activate)
+		icd->link->activate(icd->link, 1);
+
 	/* Now we really have to activate the camera */
 	if (icd->use_count == 1) {
 		ret = ici->ops->add(icd);
@@ -269,6 +272,8 @@ static int soc_camera_close(struct inode
 	icd->use_count--;
 	if (!icd->use_count)
 		ici->ops->remove(icd);
+	if (icd->link->activate)
+		icd->link->activate(icd->link, 0);
 	icf->lock = NULL;
 	if (ici->ops->spinlock_free)
 		ici->ops->spinlock_free(lock);
@@ -670,7 +675,7 @@ static void scan_add_host(struct soc_cam
 	mutex_lock(&list_lock);
 
 	list_for_each_entry(icd, &devices, list) {
-		if (icd->iface == ici->nr) {
+		if (icd->link->bus_id == ici->nr) {
 			icd->dev.parent = &ici->dev;
 			device_register_link(icd);
 		}
@@ -693,7 +698,7 @@ static int scan_add_device(struct soc_ca
 	/* Watch out for class_for_each_device / class_find_device API by
 	 * Dave Young <[email protected]> */
 	list_for_each_entry(ici, &hosts, list) {
-		if (icd->iface == ici->nr) {
+		if (icd->link->bus_id == ici->nr) {
 			ret = 1;
 			icd->dev.parent = &ici->dev;
 			break;
@@ -718,6 +723,9 @@ static int soc_camera_probe(struct devic
 	if (!icd->ops->probe)
 		return -ENODEV;
 
+	if (icd->link->activate)
+		icd->link->activate(icd->link, 1);
+
 	/* We only call ->add() here to activate and probe the camera.
 	 * We shall ->remove() and deactivate it immediately afterwards. */
 	ret = ici->ops->add(icd);
@@ -736,6 +744,9 @@ static int soc_camera_probe(struct devic
 	}
 	ici->ops->remove(icd);
 
+	if (icd->link->activate)
+		icd->link->activate(icd->link, 0);
+
 	return ret;
 }
 
@@ -866,7 +877,8 @@ int soc_camera_device_register(struct so
 	for (i = 0; i < 256 && num < 0; i++) {
 		num = i;
 		list_for_each_entry(ix, &devices, list) {
-			if (ix->iface == icd->iface && ix->devnum == i) {
+			if (ix->link->bus_id == icd->link->bus_id &&
+					ix->devnum == i) {
 				num = -1;
 				break;
 			}
@@ -881,7 +893,7 @@ int soc_camera_device_register(struct so
 	icd->devnum = num;
 	icd->dev.bus = &soc_camera_bus_type;
 	snprintf(icd->dev.bus_id, sizeof(icd->dev.bus_id),
-		 "%u-%u", icd->iface, icd->devnum);
+		 "%u-%u", icd->link->bus_id, icd->devnum);
 
 	icd->dev.release = dummy_release;
 
include/media/soc_camera.h +6 -1
Index: linux-2.6/include/media/soc_camera.h
===================================================================
@@ -15,6 +15,8 @@
 #include <linux/videodev2.h>
 #include <media/videobuf-dma-sg.h>
 
+struct soc_camera_link;
+
 struct soc_camera_device {
 	struct list_head list;
 	struct device dev;
@@ -32,7 +34,7 @@ struct soc_camera_device {
 	unsigned short y_skip_top;	/* Lines to skip at the top */
 	unsigned short gain;
 	unsigned short exposure;
-	unsigned char iface;		/* Host number */
+	struct soc_camera_link *link;	/* Link to this camera */
 	unsigned char devnum;		/* Device number per host */
 	unsigned char buswidth;		/* See comment in .c */
 	struct soc_camera_ops *ops;
@@ -83,6 +85,9 @@ struct soc_camera_link {
 	int bus_id;
 	/* GPIO number to switch between 8 and 10 bit modes */
 	unsigned int gpio;
+	/* (de-)activate this camera. Can be left empty if only one camera is
+	 * connected to this bus. */
+	void (*activate)(struct soc_camera_link *, int);
 };
 
 static inline struct soc_camera_device *to_soc_camera_dev(struct device *dev)
drivers/media/video/mt9m001.c +2 -2
Index: linux-2.6/drivers/media/video/mt9m001.c
===================================================================
@@ -557,7 +557,7 @@ static int mt9m001_video_probe(struct so
 	/* We must have a parent by now. And it cannot be a wrong one.
 	 * So this entire test is completely redundant. */
 	if (!icd->dev.parent ||
-	    to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+	    to_soc_camera_host(icd->dev.parent)->nr != icd->link->bus_id)
 		return -ENODEV;
 
 	/* Enable the chip */
@@ -657,7 +657,7 @@ static int mt9m001_probe(struct i2c_clie
 	icd->height_min	= 32;
 	icd->height_max	= 1024;
 	icd->y_skip_top	= 1;
-	icd->iface	= icl->bus_id;
+	icd->link	= icl;
 	/* Default datawidth - this is the only width this camera (normally)
 	 * supports. It is only with extra logic that it can support
 	 * other widths. Therefore it seems to be a sensible default. */
drivers/media/video/mt9v022.c +2 -2
Index: linux-2.6/drivers/media/video/mt9v022.c
===================================================================
@@ -672,7 +672,7 @@ static int mt9v022_video_probe(struct so
 	int ret;
 
 	if (!icd->dev.parent ||
-	    to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+	    to_soc_camera_host(icd->dev.parent)->nr != icd->link->bus_id)
 		return -ENODEV;
 
 	/* Read out the chip version register */
@@ -782,7 +782,7 @@ static int mt9v022_probe(struct i2c_clie
 	icd->height_min	= 32;
 	icd->height_max	= 480;
 	icd->y_skip_top	= 1;
-	icd->iface	= icl->bus_id;
+	icd->link	= icl;
 	/* Default datawidth - this is the only width this camera (normally)
 	 * supports. It is only with extra logic that it can support
 	 * other widths. Therefore it seems to be a sensible default. */
Signature · 10 lines
-- 
 Pengutronix - Linux Solutions for Science and Industry
   Handelsregister:  Amtsgericht Hildesheim, HRA 2686
     Hannoversche Str. 2, 31134 Hildesheim, Germany
   Phone: +49-5121-206917-0 |  Fax: +49-5121-206917-9

--
video4linux-list mailing list
Unsubscribe mailto:[email protected]?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list