All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC/PATCH 1/2] v4l: Add generic board subdev registration function
@ 2011-05-19 18:34 Laurent Pinchart
  2011-05-19 18:34 ` [RFC/PATCH 2/2] omap3isp: Use generic " Laurent Pinchart
  2011-05-20  7:14 ` [RFC/PATCH 1/2] v4l: Add generic board " Sylwester Nawrocki
  0 siblings, 2 replies; 18+ messages in thread
From: Laurent Pinchart @ 2011-05-19 18:34 UTC (permalink / raw)
  To: linux-media; +Cc: sakari.ailus, michael.jones

The new v4l2_new_subdev_board() function creates and register a subdev
based on generic board information. The board information structure
includes a bus type and bus type-specific information.

Only I2C and SPI busses are currently supported.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/media/video/v4l2-common.c |   70 +++++++++++++++++++++++++++++++++++++
 drivers/media/video/v4l2-device.c |    8 ++++
 include/media/v4l2-common.h       |   28 +++++++++++++++
 include/media/v4l2-subdev.h       |    3 ++
 4 files changed, 109 insertions(+), 0 deletions(-)

Hi everybody,

This approach has been briefly discussed during the Warsaw V4L meeting. Now
that support for platform subdevs has been requested, I'd like to move bus type
handling to the V4L2 core instead of duplicating the logic in every driver. As
usual, comments will be appreciated.

diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index 06b9f9f..46aee94 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -474,6 +474,76 @@ EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev);
 
 #endif /* defined(CONFIG_SPI) */
 
+/*
+ * v4l2_new_subdev_board - Register a subdevice based on board information
+ * @v4l2_dev: Parent V4L2 device
+ * @info: I2C subdevs board information array
+ *
+ * Register a subdevice identified by a geenric board information structure. The
+ * structure contains the bus type and bus type-specific information.
+ *
+ * Return a pointer to the subdevice if registration was successful, or NULL
+ * otherwise.
+ */
+struct v4l2_subdev *v4l2_new_subdev_board(struct v4l2_device *v4l2_dev,
+		struct v4l2_subdev_board_info *info)
+{
+	struct v4l2_subdev *subdev;
+
+	switch (info->type) {
+#if defined(CONFIG_I2C)
+	case V4L2_SUBDEV_BUS_TYPE_I2C: {
+		struct i2c_adapter *adapter;
+
+		adapter = i2c_get_adapter(info->info.i2c.i2c_adapter_id);
+		if (adapter == NULL) {
+			printk(KERN_ERR "%s: Unable to get I2C adapter %d for "
+				"device %s/%u\n", __func__,
+				info->info.i2c.i2c_adapter_id,
+				info->info.i2c.board_info->type,
+				info->info.i2c.board_info->addr);
+			return NULL;
+		}
+
+		subdev = v4l2_i2c_new_subdev_board(v4l2_dev, adapter,
+					info->info.i2c.board_info, NULL);
+		if (subdev == NULL) {
+			i2c_put_adapter(adapter);
+			return NULL;
+		}
+
+		subdev->flags |= V4L2_SUBDEV_FL_RELEASE_ADAPTER;
+		break;
+	}
+#endif /* defined(CONFIG_I2C) */
+#if defined(CONFIG_SPI)
+	case V4L2_SUBDEV_BUS_TYPE_SPI: {
+		struct spi_master *master;
+
+		master = spi_busnum_to_master(info->info.spi->bus_num);
+		if (master == NULL) {
+			printk(KERN_ERR "%s: Unable to get SPI master %u for "
+				"device %s/%u\n", __func__,
+				info->info.spi->bus_num,
+				info->info.spi->modalias,
+				info->info.spi->chip_select);
+			return NULL;
+		}
+
+		subdev = v4l2_spi_new_subdev(v4l2_dev, master, info->info.spi);
+		spi_master_put(master);
+		break;
+	}
+#endif /* defined(CONFIG_SPI) */
+	default:
+		subdev = NULL;
+		break;
+	}
+
+	return subdev;
+}
+EXPORT_SYMBOL_GPL(v4l2_new_subdev_board);
+
 /* Clamp x to be between min and max, aligned to a multiple of 2^align.  min
  * and max don't have to be aligned, but there must be at least one valid
  * value.  E.g., min=17,max=31,align=4 is not allowed as there are no multiples
diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c
index 4aae501..cfd9caf 100644
--- a/drivers/media/video/v4l2-device.c
+++ b/drivers/media/video/v4l2-device.c
@@ -246,5 +246,13 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
 #endif
 	video_unregister_device(&sd->devnode);
 	module_put(sd->owner);
+
+#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
+	if ((sd->flags & V4L2_SUBDEV_FL_IS_I2C) &&
+	    (sd->flags & V4L2_SUBDEV_FL_RELEASE_ADAPTER)) {
+		struct i2c_client *client = v4l2_get_subdevdata(sd);
+		i2c_put_adapter(client->adapter);
+	}
+#endif
 }
 EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index a298ec4..88c38d9 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -171,6 +171,34 @@ void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
 		const struct v4l2_subdev_ops *ops);
 #endif
 
+/* -------------------------------------------------------------------------- */
+
+/* Generic helper functions */
+
+struct v4l2_subdev_i2c_board_info {
+	struct i2c_board_info *board_info;
+	int i2c_adapter_id;
+};
+
+enum v4l2_subdev_bus_type {
+	V4L2_SUBDEV_BUS_TYPE_NONE,
+	V4L2_SUBDEV_BUS_TYPE_I2C,
+	V4L2_SUBDEV_BUS_TYPE_SPI,
+};
+
+struct v4l2_subdev_board_info {
+	enum v4l2_subdev_bus_type type;
+	union {
+		struct v4l2_subdev_i2c_board_info i2c;
+		struct spi_board_info *spi;
+	} info;
+};
+
+/* Create a subdevice and load its module. The info argumentidentifies the
+ * subdev bus type and the bus type-specific information. */
+struct v4l2_subdev *v4l2_new_subdev_board(struct v4l2_device *v4l2_dev,
+		struct v4l2_subdev_board_info *info);
+
 /* ------------------------------------------------------------------------- */
 
 /* Note: these remaining ioctls/structs should be removed as well, but they are
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 1562c4f..bc1c4d8 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -483,6 +483,9 @@ struct v4l2_subdev_internal_ops {
 #define V4L2_SUBDEV_FL_HAS_DEVNODE		(1U << 2)
 /* Set this flag if this subdev generates events. */
 #define V4L2_SUBDEV_FL_HAS_EVENTS		(1U << 3)
+/* Set by the core if the bus adapter needs to be released. Do NOT use in
+ * drivers. */
+#define V4L2_SUBDEV_FL_RELEASE_ADAPTER		(1U << 4)
 
 /* Each instance of a subdev driver should create this struct, either
    stand-alone or embedded in a larger struct.
-- 
Regards,

Laurent Pinchart


^ permalink raw reply related	[flat|nested] 18+ messages in thread
* Re: [RFC/PATCH 1/2] v4l: Add generic board subdev registration function
@ 2011-11-07 22:35 Rick Bronson
  0 siblings, 0 replies; 18+ messages in thread
From: Rick Bronson @ 2011-11-07 22:35 UTC (permalink / raw)
  To: linux-media; +Cc: laurent.pinchart

Hi All,

  I'm trying to add a SPI camera to 2.6.39 but ran into trouble with
isp_register_subdev_group() in drivers/media/video/omap3isp/isp.c
hardcoded to use i2c.  The platform is a BeagleBoardXM.  I tried these
two patches:

http://patchwork.linuxtv.org/patch/6651/mbox/
http://patchwork.linuxtv.org/patch/6650/raw/

  or:

RFC-PATCH-2-2-omap3isp-Use-generic-subdev-registration-function.patch
RFC-PATCH-1-2-v4l-Add-generic-board-subdev-registration-function.patch

  It crashes, from what I can tell, it seems to be coming into
isp_register_entities(), then iterating in:

---------------------------------
	/* Register external entities */
	for (subdevs = pdata->subdevs; subdevs->subdevs; ++subdevs) {
---------------------------------

  But it's iterating through ev76c560_camera_subdevs (see
http://efn.org/~rick/pub/board-portal7-camera.c), seems like
it should be iterating through portal7_camera_subdevs in the same
file.

  Any help would be greatly appreciated.

  Thanks,

  Rick Bronson

^ permalink raw reply	[flat|nested] 18+ messages in thread
* Re: [RFC/PATCH 1/2] v4l: Add generic board subdev registration function
@ 2011-11-08 14:13 Rick Bronson
  0 siblings, 0 replies; 18+ messages in thread
From: Rick Bronson @ 2011-11-08 14:13 UTC (permalink / raw)
  To: laurent.pinchart; +Cc: linux-media

Hi All,

  I'm trying to add a SPI camera to 2.6.39 but ran into trouble with
isp_register_subdev_group() in drivers/media/video/omap3isp/isp.c
hardcoded to use i2c.  The platform is a BeagleBoardXM.  I tried these
two patches:

http://patchwork.linuxtv.org/patch/6651/mbox/
http://patchwork.linuxtv.org/patch/6650/raw/

  or:

RFC-PATCH-2-2-omap3isp-Use-generic-subdev-registration-function.patch
RFC-PATCH-1-2-v4l-Add-generic-board-subdev-registration-function.patch

  It crashes, from what I can tell, it seems to be coming into
isp_register_entities(), then iterating in:

---------------------------------
	/* Register external entities */
	for (subdevs = pdata->subdevs; subdevs->subdevs; ++subdevs) {
---------------------------------

  But it's iterating through ev76c560_camera_subdevs (see
http://efn.org/~rick/pub/board-portal7-camera.c), seems like
it should be iterating through portal7_camera_subdevs in the same
file.

  Any help would be greatly appreciated.

  Thanks,

  Rick Bronson


^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2011-11-08 14:13 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-19 18:34 [RFC/PATCH 1/2] v4l: Add generic board subdev registration function Laurent Pinchart
2011-05-19 18:34 ` [RFC/PATCH 2/2] omap3isp: Use generic " Laurent Pinchart
2011-05-20  7:14 ` [RFC/PATCH 1/2] v4l: Add generic board " Sylwester Nawrocki
2011-05-20  7:29   ` Laurent Pinchart
2011-05-20  7:52     ` Michael Jones
2011-05-20  8:53     ` Hans Verkuil
2011-05-20  9:05       ` Laurent Pinchart
2011-05-20  9:19         ` Hans Verkuil
2011-05-20  9:37           ` Laurent Pinchart
2011-05-20  9:52             ` Hans Verkuil
2011-05-20 10:12               ` Laurent Pinchart
2011-05-20 11:14                 ` Hans Verkuil
2011-05-24 12:41                   ` Laurent Pinchart
2011-05-20 10:36               ` Sylwester Nawrocki
2011-05-20 13:08     ` Guennadi Liakhovetski
2011-05-20 16:03       ` Laurent Pinchart
2011-11-07 22:35 Rick Bronson
2011-11-08 14:13 Rick Bronson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.