From afe267f2d368f5673514b1b97449c3ec43c64601 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 19 Jun 2023 14:22:10 +0200 Subject: media: i2c: add DS90UB960 driver Add driver for TI DS90UB960 FPD-Link III Deserializer. Signed-off-by: Tomi Valkeinen Reviewed-by: Andy Shevchenko Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- include/media/i2c/ds90ub9xx.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 include/media/i2c/ds90ub9xx.h (limited to 'include/media') diff --git a/include/media/i2c/ds90ub9xx.h b/include/media/i2c/ds90ub9xx.h new file mode 100644 index 000000000000..0245198469ec --- /dev/null +++ b/include/media/i2c/ds90ub9xx.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __MEDIA_I2C_DS90UB9XX_H__ +#define __MEDIA_I2C_DS90UB9XX_H__ + +#include + +struct i2c_atr; + +/** + * struct ds90ub9xx_platform_data - platform data for FPD-Link Serializers. + * @port: Deserializer RX port for this Serializer + * @atr: I2C ATR + * @bc_rate: back-channel clock rate + */ +struct ds90ub9xx_platform_data { + u32 port; + struct i2c_atr *atr; + unsigned long bc_rate; +}; + +#endif /* __MEDIA_I2C_DS90UB9XX_H__ */ -- cgit From bda8953e8c3e7ecbbf6cb1be11790496300e3961 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Tue, 18 Apr 2023 11:52:07 +0200 Subject: media: v4l: async: Drop v4l2_async_nf_parse_fwnode_endpoints() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The v4l2_async_nf_parse_fwnode_endpoints() function, part of v4l2-fwnode.c, was a helper meant to register one async sub-dev for each fwnode endpoint of a device. The function is marked as deprecated in the documentation and is actually not used anywhere anymore. Drop it and remove the helper function v4l2_async_nf_fwnode_parse_endpoint() from v4l2-fwnode.c. This change allows to make the helper function __v4l2_async_nf_add_connection() visibility private to v4l2-async.c so that there is no risk drivers can mistakenly use it. [Sakari Ailus: Small fixups on top.] Signed-off-by: Jacopo Mondi Signed-off-by: Sakari Ailus Tested-by: Philipp Zabel # imx6qp Tested-by: Niklas Söderlund # rcar + adv746x Reviewed-by: Laurent Pinchart Tested-by: Aishwarya Kothari # Apalis i.MX6Q with TC358743 Tested-by: Lad Prabhakar # Renesas RZ/G2L SMARC Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-async.h | 34 +++-------------------- include/media/v4l2-fwnode.h | 68 --------------------------------------------- 2 files changed, 4 insertions(+), 98 deletions(-) (limited to 'include/media') diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 25eb1d138c06..2c9baa3c9266 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -131,32 +131,10 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir); * * This function initializes the notifier @asd_list. It must be called * before adding a subdevice to a notifier, using one of: - * v4l2_async_nf_add_fwnode_remote(), - * v4l2_async_nf_add_fwnode(), - * v4l2_async_nf_add_i2c(), - * __v4l2_async_nf_add_subdev() or - * v4l2_async_nf_parse_fwnode_endpoints(). - */ -void v4l2_async_nf_init(struct v4l2_async_notifier *notifier); - -/** - * __v4l2_async_nf_add_subdev - Add an async subdev to the - * notifier's master asd list. - * - * @notifier: pointer to &struct v4l2_async_notifier - * @asd: pointer to &struct v4l2_async_subdev - * - * \warning: Drivers should avoid using this function and instead use one of: - * v4l2_async_nf_add_fwnode(), - * v4l2_async_nf_add_fwnode_remote() or + * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or * v4l2_async_nf_add_i2c(). - * - * Call this function before registering a notifier to link the provided @asd to - * the notifiers master @asd_list. The @asd must be allocated with k*alloc() as - * it will be freed by the framework when the notifier is destroyed. */ -int __v4l2_async_nf_add_subdev(struct v4l2_async_notifier *notifier, - struct v4l2_async_subdev *asd); +void v4l2_async_nf_init(struct v4l2_async_notifier *notifier); struct v4l2_async_subdev * __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier, @@ -263,12 +241,8 @@ void v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier); * Release memory resources related to a notifier, including the async * sub-devices allocated for the purposes of the notifier but not the notifier * itself. The user is responsible for calling this function to clean up the - * notifier after calling - * v4l2_async_nf_add_fwnode_remote(), - * v4l2_async_nf_add_fwnode(), - * v4l2_async_nf_add_i2c(), - * __v4l2_async_nf_add_subdev() or - * v4l2_async_nf_parse_fwnode_endpoints(). + * notifier after calling v4l2_async_nf_add_fwnode_remote(), + * v4l2_async_nf_add_fwnode() or v4l2_async_nf_add_i2c(). * * There is no harm from calling v4l2_async_nf_cleanup() in other * cases as long as its memory has been zeroed after it has been diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h index 394d798f3dfa..a9a89035e282 100644 --- a/include/media/v4l2-fwnode.h +++ b/include/media/v4l2-fwnode.h @@ -22,8 +22,6 @@ #include struct fwnode_handle; -struct v4l2_async_notifier; -struct v4l2_async_subdev; /** * struct v4l2_fwnode_endpoint - the endpoint data structure @@ -393,72 +391,6 @@ int v4l2_fwnode_connector_add_link(struct fwnode_handle *fwnode, int v4l2_fwnode_device_parse(struct device *dev, struct v4l2_fwnode_device_properties *props); -/** - * typedef parse_endpoint_func - Driver's callback function to be called on - * each V4L2 fwnode endpoint. - * - * @dev: pointer to &struct device - * @vep: pointer to &struct v4l2_fwnode_endpoint - * @asd: pointer to &struct v4l2_async_subdev - * - * Return: - * * %0 on success - * * %-ENOTCONN if the endpoint is to be skipped but this - * should not be considered as an error - * * %-EINVAL if the endpoint configuration is invalid - */ -typedef int (*parse_endpoint_func)(struct device *dev, - struct v4l2_fwnode_endpoint *vep, - struct v4l2_async_subdev *asd); - -/** - * v4l2_async_nf_parse_fwnode_endpoints - Parse V4L2 fwnode endpoints in a - * device node - * @dev: the device the endpoints of which are to be parsed - * @notifier: notifier for @dev - * @asd_struct_size: size of the driver's async sub-device struct, including - * sizeof(struct v4l2_async_subdev). The &struct - * v4l2_async_subdev shall be the first member of - * the driver's async sub-device struct, i.e. both - * begin at the same memory address. - * @parse_endpoint: Driver's callback function called on each V4L2 fwnode - * endpoint. Optional. - * - * DEPRECATED! This function is deprecated. Don't use it in new drivers. - * Instead see an example in cio2_parse_firmware() function in - * drivers/media/pci/intel/ipu3/ipu3-cio2.c . - * - * Parse the fwnode endpoints of the @dev device and populate the async sub- - * devices list in the notifier. The @parse_endpoint callback function is - * called for each endpoint with the corresponding async sub-device pointer to - * let the caller initialize the driver-specific part of the async sub-device - * structure. - * - * The notifier memory shall be zeroed before this function is called on the - * notifier. - * - * This function may not be called on a registered notifier and may be called on - * a notifier only once. - * - * The &struct v4l2_fwnode_endpoint passed to the callback function - * @parse_endpoint is released once the function is finished. If there is a need - * to retain that configuration, the user needs to allocate memory for it. - * - * Any notifier populated using this function must be released with a call to - * v4l2_async_nf_cleanup() after it has been unregistered and the async - * sub-devices are no longer in use, even if the function returned an error. - * - * Return: %0 on success, including when no async sub-devices are found - * %-ENOMEM if memory allocation failed - * %-EINVAL if graph or endpoint parsing failed - * Other error codes as returned by @parse_endpoint - */ -int -v4l2_async_nf_parse_fwnode_endpoints(struct device *dev, - struct v4l2_async_notifier *notifier, - size_t asd_struct_size, - parse_endpoint_func parse_endpoint); - /* Helper macros to access the connector links. */ /** v4l2_connector_last_link - Helper macro to get the first -- cgit From b2cc2a32d266dbea4011e1020ad5fbecf1713c89 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 13 Jun 2023 18:33:58 +0200 Subject: media: v4l: fwnode: Remove unneeded forward declaration Remove an unneeded declaration for struct fwnode_handle. Signed-off-by: Sakari Ailus Tested-by: Lad Prabhakar # Renesas RZ/G2L SMARC Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-fwnode.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include/media') diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h index a9a89035e282..f7c57c776589 100644 --- a/include/media/v4l2-fwnode.h +++ b/include/media/v4l2-fwnode.h @@ -21,8 +21,6 @@ #include -struct fwnode_handle; - /** * struct v4l2_fwnode_endpoint - the endpoint data structure * @base: fwnode endpoint of the v4l2_fwnode -- cgit From f0e10d0a971c43fb2035fccc06de8bdd22674ec9 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Sun, 19 Feb 2023 13:09:00 +0100 Subject: media: v4l: async: Make V4L2 async match information a struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make V4L2 async match information a struct, making it easier to use it elsewhere outside the scope of struct v4l2_async_subdev. Also remove an obsolete comment --- none of these fields are supposed to be touched by drivers. Signed-off-by: Sakari Ailus Tested-by: Philipp Zabel # imx6qp Tested-by: Niklas Söderlund # rcar + adv746x Reviewed-by: Laurent Pinchart Tested-by: Aishwarya Kothari # Apalis i.MX6Q with TC358743 Tested-by: Lad Prabhakar # Renesas RZ/G2L SMARC Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-async.h | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'include/media') diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 2c9baa3c9266..d347ef32f4ec 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -34,23 +34,37 @@ enum v4l2_async_match_type { }; /** - * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge + * struct v4l2_async_match_desc - async sub-device match information * - * @match_type: type of match that will be used - * @match: union of per-bus type matching data sets - * @match.fwnode: - * pointer to &struct fwnode_handle to be matched. + * @type: type of match that will be used + * @fwnode: pointer to &struct fwnode_handle to be matched. * Used if @match_type is %V4L2_ASYNC_MATCH_FWNODE. - * @match.i2c: embedded struct with I2C parameters to be matched. + * @i2c: embedded struct with I2C parameters to be matched. * Both @match.i2c.adapter_id and @match.i2c.address * should be matched. * Used if @match_type is %V4L2_ASYNC_MATCH_I2C. - * @match.i2c.adapter_id: + * @i2c.adapter_id: * I2C adapter ID to be matched. * Used if @match_type is %V4L2_ASYNC_MATCH_I2C. - * @match.i2c.address: + * @i2c.address: * I2C address to be matched. * Used if @match_type is %V4L2_ASYNC_MATCH_I2C. + */ +struct v4l2_async_match_desc { + enum v4l2_async_match_type type; + union { + struct fwnode_handle *fwnode; + struct { + int adapter_id; + unsigned short address; + } i2c; + }; +}; + +/** + * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge + * + * @match: struct of match type and per-bus type matching data sets * @asd_list: used to add struct v4l2_async_subdev objects to the * master notifier @asd_list * @list: used to link struct v4l2_async_subdev objects, waiting to be @@ -61,16 +75,7 @@ enum v4l2_async_match_type { * v4l2_async_subdev as its first member. */ struct v4l2_async_subdev { - enum v4l2_async_match_type match_type; - union { - struct fwnode_handle *fwnode; - struct { - int adapter_id; - unsigned short address; - } i2c; - } match; - - /* v4l2-async core private: not to be used by drivers */ + struct v4l2_async_match_desc match; struct list_head list; struct list_head asd_list; }; -- cgit From 7a2259fc5182bc792b7ce90d83d8f6e197808b9a Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 5 May 2023 09:09:10 +0200 Subject: media: v4l: async: Rename V4L2_ASYNC_MATCH_ macros, add TYPE_ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The async match type is a struct field now, rename V4L2_ASYNC_MATCH_* macros as V4L2_ASYNC_MATCH_TYPE_* instead. This patch has been produced by: git grep -l V4L2_ASYNC_MATCH_ -- drivers/media/ drivers/staging/media/ \ include/ Documentation/|xargs perl -i -pe \ 's/V4L2_ASYNC_MATCH_\K/TYPE_/g' so it must be correct. Signed-off-by: Sakari Ailus Tested-by: Philipp Zabel # imx6qp Tested-by: Niklas Söderlund # rcar + adv746x Reviewed-by: Laurent Pinchart Tested-by: Aishwarya Kothari # Apalis i.MX6Q with TC358743 Tested-by: Lad Prabhakar # Renesas RZ/G2L SMARC Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-async.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'include/media') diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index d347ef32f4ec..8d1506a9755c 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -22,15 +22,15 @@ struct v4l2_async_notifier; * enum v4l2_async_match_type - type of asynchronous subdevice logic to be used * in order to identify a match * - * @V4L2_ASYNC_MATCH_I2C: Match will check for I2C adapter ID and address - * @V4L2_ASYNC_MATCH_FWNODE: Match will use firmware node + * @V4L2_ASYNC_MATCH_TYPE_I2C: Match will check for I2C adapter ID and address + * @V4L2_ASYNC_MATCH_TYPE_FWNODE: Match will use firmware node * * This enum is used by the asynchronous sub-device logic to define the * algorithm that will be used to match an asynchronous device. */ enum v4l2_async_match_type { - V4L2_ASYNC_MATCH_I2C, - V4L2_ASYNC_MATCH_FWNODE, + V4L2_ASYNC_MATCH_TYPE_I2C, + V4L2_ASYNC_MATCH_TYPE_FWNODE, }; /** @@ -38,17 +38,17 @@ enum v4l2_async_match_type { * * @type: type of match that will be used * @fwnode: pointer to &struct fwnode_handle to be matched. - * Used if @match_type is %V4L2_ASYNC_MATCH_FWNODE. + * Used if @match_type is %V4L2_ASYNC_MATCH_TYPE_FWNODE. * @i2c: embedded struct with I2C parameters to be matched. * Both @match.i2c.adapter_id and @match.i2c.address * should be matched. - * Used if @match_type is %V4L2_ASYNC_MATCH_I2C. + * Used if @match_type is %V4L2_ASYNC_MATCH_TYPE_I2C. * @i2c.adapter_id: * I2C adapter ID to be matched. - * Used if @match_type is %V4L2_ASYNC_MATCH_I2C. + * Used if @match_type is %V4L2_ASYNC_MATCH_TYPE_I2C. * @i2c.address: * I2C address to be matched. - * Used if @match_type is %V4L2_ASYNC_MATCH_I2C. + * Used if @match_type is %V4L2_ASYNC_MATCH_TYPE_I2C. */ struct v4l2_async_match_desc { enum v4l2_async_match_type type; -- cgit From b6d42c35c03dc1a0e5c2800c2137017a62ee58f9 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 22 Feb 2023 12:02:39 +0100 Subject: media: v4l: async: Clean up list heads and entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The naming of list heads and list entries is confusing as they're named similarly. Use _list for list head and _entry for list entries. Signed-off-by: Sakari Ailus Tested-by: Philipp Zabel # imx6qp Tested-by: Niklas Söderlund # rcar + adv746x Tested-by: Aishwarya Kothari # Apalis i.MX6Q with TC358743 Tested-by: Lad Prabhakar # Renesas RZ/G2L SMARC Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-async.h | 22 +++++++++++----------- include/media/v4l2-subdev.h | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) (limited to 'include/media') diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 8d1506a9755c..03ac6520f3d2 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -65,10 +65,10 @@ struct v4l2_async_match_desc { * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge * * @match: struct of match type and per-bus type matching data sets - * @asd_list: used to add struct v4l2_async_subdev objects to the + * @asd_entry: used to add struct v4l2_async_subdev objects to the * master notifier @asd_list - * @list: used to link struct v4l2_async_subdev objects, waiting to be - * probed, to a notifier->waiting list + * @waiting_entry: used to link struct v4l2_async_subdev objects, waiting to be + * probed, to a notifier->waiting_list list * * When this struct is used as a member in a driver specific struct, * the driver specific struct shall contain the &struct @@ -76,8 +76,8 @@ struct v4l2_async_match_desc { */ struct v4l2_async_subdev { struct v4l2_async_match_desc match; - struct list_head list; - struct list_head asd_list; + struct list_head asd_entry; + struct list_head waiting_entry; }; /** @@ -107,9 +107,9 @@ struct v4l2_async_notifier_operations { * @sd: sub-device that registered the notifier, NULL otherwise * @parent: parent notifier * @asd_list: master list of struct v4l2_async_subdev - * @waiting: list of struct v4l2_async_subdev, waiting for their drivers - * @done: list of struct v4l2_subdev, already probed - * @list: member in a global list of notifiers + * @waiting_list: list of struct v4l2_async_subdev, waiting for their drivers + * @done_list: list of struct v4l2_subdev, already probed + * @notifier_entry: member in a global list of notifiers */ struct v4l2_async_notifier { const struct v4l2_async_notifier_operations *ops; @@ -117,9 +117,9 @@ struct v4l2_async_notifier { struct v4l2_subdev *sd; struct v4l2_async_notifier *parent; struct list_head asd_list; - struct list_head waiting; - struct list_head done; - struct list_head list; + struct list_head waiting_list; + struct list_head done_list; + struct list_head notifier_entry; }; /** diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index b325df0d54d6..b58c7a325e99 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -1020,8 +1020,8 @@ struct v4l2_subdev_platform_data { * @dev: pointer to the physical device, if any * @fwnode: The fwnode_handle of the subdev, usually the same as * either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL). - * @async_list: Links this subdev to a global subdev_list or @notifier->done - * list. + * @async_list: Links this subdev to a global subdev_list or + * @notifier->done_list list. * @asd: Pointer to respective &struct v4l2_async_subdev. * @notifier: Pointer to the managing notifier. * @subdev_notifier: A sub-device notifier implicitly registered for the sub- -- cgit From adb2dcd5f2d49d3ba3171160fabd4be0d4b2a86c Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 16 Feb 2023 14:54:53 +0100 Subject: media: v4l: async: Rename v4l2_async_subdev as v4l2_async_connection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename v4l2_async_subdev as v4l2_async_connection, in order to differentiate between the sub-devices and their connections: one sub-device can have many connections but the V4L2 async framework has so far allowed just a single one. Connections in this context will later translate into either MC ancillary or data links. This patch prepares changing that relation by changing existing users of v4l2_async_subdev to switch to v4l2_async_connection. Async sub-devices themselves will not be needed anymore Additionally, __v4l2_async_nf_add_subdev() has been renamed __v4l2_async_nf_add_connection(). Signed-off-by: Sakari Ailus Tested-by: Philipp Zabel # imx6qp Tested-by: Niklas Söderlund # rcar + adv746x Tested-by: Aishwarya Kothari # Apalis i.MX6Q with TC358743 Tested-by: Lad Prabhakar # Renesas RZ/G2L SMARC Signed-off-by: Mauro Carvalho Chehab --- include/media/davinci/vpif_types.h | 2 +- include/media/v4l2-async.h | 87 +++++++++++++++++++------------------- include/media/v4l2-subdev.h | 4 +- 3 files changed, 47 insertions(+), 46 deletions(-) (limited to 'include/media') diff --git a/include/media/davinci/vpif_types.h b/include/media/davinci/vpif_types.h index d03e5c54347a..6cce1f09c721 100644 --- a/include/media/davinci/vpif_types.h +++ b/include/media/davinci/vpif_types.h @@ -72,7 +72,7 @@ struct vpif_capture_config { int i2c_adapter_id; const char *card_name; - struct v4l2_async_subdev *asd[VPIF_CAPTURE_MAX_CHANNELS]; + struct v4l2_async_connection *asd[VPIF_CAPTURE_MAX_CHANNELS]; int asd_sizes[VPIF_CAPTURE_MAX_CHANNELS]; }; #endif /* _VPIF_TYPES_H */ diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 03ac6520f3d2..a27d9dc8afcb 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -25,7 +25,7 @@ struct v4l2_async_notifier; * @V4L2_ASYNC_MATCH_TYPE_I2C: Match will check for I2C adapter ID and address * @V4L2_ASYNC_MATCH_TYPE_FWNODE: Match will use firmware node * - * This enum is used by the asynchronous sub-device logic to define the + * This enum is used by the asynchronous connection logic to define the * algorithm that will be used to match an asynchronous device. */ enum v4l2_async_match_type { @@ -34,7 +34,7 @@ enum v4l2_async_match_type { }; /** - * struct v4l2_async_match_desc - async sub-device match information + * struct v4l2_async_match_desc - async connection match information * * @type: type of match that will be used * @fwnode: pointer to &struct fwnode_handle to be matched. @@ -62,21 +62,21 @@ struct v4l2_async_match_desc { }; /** - * struct v4l2_async_subdev - sub-device descriptor, as known to a bridge + * struct v4l2_async_connection - connection descriptor, as known to a bridge * * @match: struct of match type and per-bus type matching data sets - * @asd_entry: used to add struct v4l2_async_subdev objects to the - * master notifier @asd_list - * @waiting_entry: used to link struct v4l2_async_subdev objects, waiting to be - * probed, to a notifier->waiting_list list + * @asc_entry: used to add struct v4l2_async_connection objects to the + * master notifier @asc_list + * @waiting_entry: used to link struct v4l2_async_connection objects, waiting to + * be probed, to a notifier->waiting_list list * * When this struct is used as a member in a driver specific struct, * the driver specific struct shall contain the &struct - * v4l2_async_subdev as its first member. + * v4l2_async_connection as its first member. */ -struct v4l2_async_subdev { +struct v4l2_async_connection { struct v4l2_async_match_desc match; - struct list_head asd_entry; + struct list_head asc_entry; struct list_head waiting_entry; }; @@ -86,17 +86,17 @@ struct v4l2_async_subdev { * @complete: All subdevices have been probed successfully. The complete * callback is only executed for the root notifier. * @unbind: a subdevice is leaving - * @destroy: the asd is about to be freed + * @destroy: the asc is about to be freed */ struct v4l2_async_notifier_operations { int (*bound)(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd); + struct v4l2_async_connection *asc); int (*complete)(struct v4l2_async_notifier *notifier); void (*unbind)(struct v4l2_async_notifier *notifier, struct v4l2_subdev *subdev, - struct v4l2_async_subdev *asd); - void (*destroy)(struct v4l2_async_subdev *asd); + struct v4l2_async_connection *asc); + void (*destroy)(struct v4l2_async_connection *asc); }; /** @@ -106,8 +106,9 @@ struct v4l2_async_notifier_operations { * @v4l2_dev: v4l2_device of the root notifier, NULL otherwise * @sd: sub-device that registered the notifier, NULL otherwise * @parent: parent notifier - * @asd_list: master list of struct v4l2_async_subdev - * @waiting_list: list of struct v4l2_async_subdev, waiting for their drivers + * @asc_list: master list of struct v4l2_async_connection + * @waiting_list: list of struct v4l2_async_connection, waiting for their + * drivers * @done_list: list of struct v4l2_subdev, already probed * @notifier_entry: member in a global list of notifiers */ @@ -116,7 +117,7 @@ struct v4l2_async_notifier { struct v4l2_device *v4l2_dev; struct v4l2_subdev *sd; struct v4l2_async_notifier *parent; - struct list_head asd_list; + struct list_head asc_list; struct list_head waiting_list; struct list_head done_list; struct list_head notifier_entry; @@ -134,53 +135,53 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir); * * @notifier: pointer to &struct v4l2_async_notifier * - * This function initializes the notifier @asd_list. It must be called + * This function initializes the notifier @asc_list. It must be called * before adding a subdevice to a notifier, using one of: * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or * v4l2_async_nf_add_i2c(). */ void v4l2_async_nf_init(struct v4l2_async_notifier *notifier); -struct v4l2_async_subdev * +struct v4l2_async_connection * __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier, struct fwnode_handle *fwnode, - unsigned int asd_struct_size); + unsigned int asc_struct_size); /** * v4l2_async_nf_add_fwnode - Allocate and add a fwnode async - * subdev to the notifier's master asd_list. + * subdev to the notifier's master asc_list. * * @notifier: pointer to &struct v4l2_async_notifier * @fwnode: fwnode handle of the sub-device to be matched, pointer to * &struct fwnode_handle - * @type: Type of the driver's async sub-device struct. The &struct - * v4l2_async_subdev shall be the first member of the driver's async - * sub-device struct, i.e. both begin at the same memory address. + * @type: Type of the driver's async sub-device or connection struct. The + * &struct v4l2_async_connection shall be the first member of the + * driver's async struct, i.e. both begin at the same memory address. * - * Allocate a fwnode-matched asd of size asd_struct_size, and add it to the - * notifiers @asd_list. The function also gets a reference of the fwnode which + * Allocate a fwnode-matched asc of size asc_struct_size, and add it to the + * notifiers @asc_list. The function also gets a reference of the fwnode which * is released later at notifier cleanup time. */ #define v4l2_async_nf_add_fwnode(notifier, fwnode, type) \ ((type *)__v4l2_async_nf_add_fwnode(notifier, fwnode, sizeof(type))) -struct v4l2_async_subdev * +struct v4l2_async_connection * __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif, struct fwnode_handle *endpoint, - unsigned int asd_struct_size); + unsigned int asc_struct_size); /** * v4l2_async_nf_add_fwnode_remote - Allocate and add a fwnode * remote async subdev to the - * notifier's master asd_list. + * notifier's master asc_list. * * @notifier: pointer to &struct v4l2_async_notifier - * @ep: local endpoint pointing to the remote sub-device to be matched, + * @ep: local endpoint pointing to the remote connection to be matched, * pointer to &struct fwnode_handle - * @type: Type of the driver's async sub-device struct. The &struct - * v4l2_async_subdev shall be the first member of the driver's async - * sub-device struct, i.e. both begin at the same memory address. + * @type: Type of the driver's async connection struct. The &struct + * v4l2_async_connection shall be the first member of the driver's async + * connection struct, i.e. both begin at the same memory address. * * Gets the remote endpoint of a given local endpoint, set it up for fwnode - * matching and adds the async sub-device to the notifier's @asd_list. The + * matching and adds the async connection to the notifier's @asc_list. The * function also gets a reference of the fwnode which is released later at * notifier cleanup time. * @@ -190,23 +191,23 @@ __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif, #define v4l2_async_nf_add_fwnode_remote(notifier, ep, type) \ ((type *)__v4l2_async_nf_add_fwnode_remote(notifier, ep, sizeof(type))) -struct v4l2_async_subdev * +struct v4l2_async_connection * __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id, unsigned short address, - unsigned int asd_struct_size); + unsigned int asc_struct_size); /** * v4l2_async_nf_add_i2c - Allocate and add an i2c async - * subdev to the notifier's master asd_list. + * subdev to the notifier's master asc_list. * * @notifier: pointer to &struct v4l2_async_notifier * @adapter: I2C adapter ID to be matched - * @address: I2C address of sub-device to be matched - * @type: Type of the driver's async sub-device struct. The &struct - * v4l2_async_subdev shall be the first member of the driver's async - * sub-device struct, i.e. both begin at the same memory address. + * @address: I2C address of connection to be matched + * @type: Type of the driver's async connection struct. The &struct + * v4l2_async_connection shall be the first member of the driver's async + * connection struct, i.e. both begin at the same memory address. * * Same as v4l2_async_nf_add_fwnode() but for I2C matched - * sub-devices. + * connections. */ #define v4l2_async_nf_add_i2c(notifier, adapter, address, type) \ ((type *)__v4l2_async_nf_add_i2c(notifier, adapter, address, \ @@ -244,7 +245,7 @@ void v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier); * @notifier: the notifier the resources of which are to be cleaned up * * Release memory resources related to a notifier, including the async - * sub-devices allocated for the purposes of the notifier but not the notifier + * connections allocated for the purposes of the notifier but not the notifier * itself. The user is responsible for calling this function to clean up the * notifier after calling v4l2_async_nf_add_fwnode_remote(), * v4l2_async_nf_add_fwnode() or v4l2_async_nf_add_i2c(). diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index b58c7a325e99..212d7f1ac525 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -1022,7 +1022,7 @@ struct v4l2_subdev_platform_data { * either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL). * @async_list: Links this subdev to a global subdev_list or * @notifier->done_list list. - * @asd: Pointer to respective &struct v4l2_async_subdev. + * @asd: Pointer to respective &struct v4l2_async_connection. * @notifier: Pointer to the managing notifier. * @subdev_notifier: A sub-device notifier implicitly registered for the sub- * device using v4l2_async_register_subdev_sensor(). @@ -1065,7 +1065,7 @@ struct v4l2_subdev { struct device *dev; struct fwnode_handle *fwnode; struct list_head async_list; - struct v4l2_async_subdev *asd; + struct v4l2_async_connection *asd; struct v4l2_async_notifier *notifier; struct v4l2_async_notifier *subdev_notifier; struct v4l2_subdev_platform_data *pdata; -- cgit From 9bf19fbf0c8bc4392210c1ea104a8db732624f3d Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 18 Apr 2023 14:00:54 +0200 Subject: media: v4l: async: Rework internal lists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch re-arranges internal V4L2 async lists for preparation of supporting multiple connections per sub-device as well as cleaning up used lists. The list of unbound V4L2 sub-devices shall be maintained for the purpose of listing those sub-devices only, not for their bindin status. Also, the V4L2 async connections now have, instead of two list entries, a single list entry in the notifier's list, be that either waiting or done lists, while the notifier's asc_list is removed. The one-to-one relation between a sub-device and a connection is still maintained in this patch. Signed-off-by: Sakari Ailus Tested-by: Philipp Zabel # imx6qp Tested-by: Niklas Söderlund # rcar + adv746x Tested-by: Aishwarya Kothari # Apalis i.MX6Q with TC358743 Tested-by: Lad Prabhakar # Renesas RZ/G2L SMARC Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-async.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'include/media') diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index a27d9dc8afcb..c06b3b832228 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -66,9 +66,8 @@ struct v4l2_async_match_desc { * * @match: struct of match type and per-bus type matching data sets * @asc_entry: used to add struct v4l2_async_connection objects to the - * master notifier @asc_list - * @waiting_entry: used to link struct v4l2_async_connection objects, waiting to - * be probed, to a notifier->waiting_list list + * notifier @waiting_list or @done_list + * @sd: the related sub-device * * When this struct is used as a member in a driver specific struct, * the driver specific struct shall contain the &struct @@ -77,7 +76,7 @@ struct v4l2_async_match_desc { struct v4l2_async_connection { struct v4l2_async_match_desc match; struct list_head asc_entry; - struct list_head waiting_entry; + struct v4l2_subdev *sd; }; /** @@ -106,7 +105,6 @@ struct v4l2_async_notifier_operations { * @v4l2_dev: v4l2_device of the root notifier, NULL otherwise * @sd: sub-device that registered the notifier, NULL otherwise * @parent: parent notifier - * @asc_list: master list of struct v4l2_async_connection * @waiting_list: list of struct v4l2_async_connection, waiting for their * drivers * @done_list: list of struct v4l2_subdev, already probed @@ -117,7 +115,6 @@ struct v4l2_async_notifier { struct v4l2_device *v4l2_dev; struct v4l2_subdev *sd; struct v4l2_async_notifier *parent; - struct list_head asc_list; struct list_head waiting_list; struct list_head done_list; struct list_head notifier_entry; -- cgit From c91fd7b7a8ae17ab8be0b6e765e4a38783749330 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Mon, 15 May 2023 11:06:50 +0200 Subject: media: v4l: async: Obtain async connection based on sub-device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add v4l2_async_connection_unique() function for obtaining a struct v4l2_async_connection, typically allocated by drivers together with their own information on an external sub-device. The relation between connections and sub-devices still remains 1:1 but this code becomes more complex when the relation soon changes. Signed-off-by: Sakari Ailus Tested-by: Philipp Zabel # imx6qp Tested-by: Niklas Söderlund # rcar + adv746x Tested-by: Aishwarya Kothari # Apalis i.MX6Q with TC358743 Tested-by: Lad Prabhakar # Renesas RZ/G2L SMARC Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-async.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'include/media') diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index c06b3b832228..5bc2efe720c2 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -210,6 +210,17 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, ((type *)__v4l2_async_nf_add_i2c(notifier, adapter, address, \ sizeof(type))) +/** + * v4l2_async_connection_unique - return a unique &struct v4l2_async_connection + * for a sub-device + * @sd: the sub-device + * + * Return an async connection for a sub-device, when there is a single + * one only. + */ +struct v4l2_async_connection * +v4l2_async_connection_unique(struct v4l2_subdev *sd); + /** * v4l2_async_nf_register - registers a subdevice asynchronous notifier * -- cgit From 28a1295795d85a25f2e7dd391c43969e95fcb341 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 19 May 2023 13:44:03 +0200 Subject: media: v4l: async: Allow multiple connections between entities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the v4l2-async framework was introduced, the use case for it was to connect a camera sensor with a parallel receiver. Both tended to be rather simple devices with a single connection between them. The framework has been since improved in multiple ways but there are limitations that have remained, for instance the assumption an async sub-device is connected towards a single notifier and via a single link only. This patch enables connecting a sub-device to one or more notifiers simultaneously, with one or more connections per notifier. The notifier information is moved from the sub-device to the connection and the connections in sub-device are no longer a pointer but a linked list. Signed-off-by: Sakari Ailus Tested-by: Philipp Zabel # imx6qp Tested-by: Niklas Söderlund # rcar + adv746x Tested-by: Aishwarya Kothari # Apalis i.MX6Q with TC358743 Tested-by: Lad Prabhakar # Renesas RZ/G2L SMARC Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-async.h | 17 +++++++++++------ include/media/v4l2-subdev.h | 7 +++---- 2 files changed, 14 insertions(+), 10 deletions(-) (limited to 'include/media') diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 5bc2efe720c2..8670b8e44851 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -62,27 +62,32 @@ struct v4l2_async_match_desc { }; /** - * struct v4l2_async_connection - connection descriptor, as known to a bridge + * struct v4l2_async_connection - sub-device connection descriptor, as known to + * a bridge * * @match: struct of match type and per-bus type matching data sets + * @notifier: the async notifier the connection is related to * @asc_entry: used to add struct v4l2_async_connection objects to the * notifier @waiting_list or @done_list + * @asc_subdev_entry: entry in struct v4l2_async_subdev.asc_list list * @sd: the related sub-device * - * When this struct is used as a member in a driver specific struct, - * the driver specific struct shall contain the &struct - * v4l2_async_connection as its first member. + * When this struct is used as a member in a driver specific struct, the driver + * specific struct shall contain the &struct v4l2_async_connection as its first + * member. */ struct v4l2_async_connection { struct v4l2_async_match_desc match; + struct v4l2_async_notifier *notifier; struct list_head asc_entry; + struct list_head asc_subdev_entry; struct v4l2_subdev *sd; }; /** * struct v4l2_async_notifier_operations - Asynchronous V4L2 notifier operations - * @bound: a subdevice driver has successfully probed one of the subdevices - * @complete: All subdevices have been probed successfully. The complete + * @bound: a sub-device has been bound by the given connection + * @complete: All connections have been bound successfully. The complete * callback is only executed for the root notifier. * @unbind: a subdevice is leaving * @destroy: the asc is about to be freed diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index 212d7f1ac525..a8078ae99596 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -1022,10 +1022,10 @@ struct v4l2_subdev_platform_data { * either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL). * @async_list: Links this subdev to a global subdev_list or * @notifier->done_list list. - * @asd: Pointer to respective &struct v4l2_async_connection. - * @notifier: Pointer to the managing notifier. * @subdev_notifier: A sub-device notifier implicitly registered for the sub- * device using v4l2_async_register_subdev_sensor(). + * @asc_list: Async connection list, of &struct + * v4l2_async_connection.subdev_entry. * @pdata: common part of subdevice platform data * @state_lock: A pointer to a lock used for all the subdev's states, set by the * driver. This is optional. If NULL, each state instance will get @@ -1065,9 +1065,8 @@ struct v4l2_subdev { struct device *dev; struct fwnode_handle *fwnode; struct list_head async_list; - struct v4l2_async_connection *asd; - struct v4l2_async_notifier *notifier; struct v4l2_async_notifier *subdev_notifier; + struct list_head asc_list; struct v4l2_subdev_platform_data *pdata; struct mutex *state_lock; -- cgit From e74f7a96787c46e90b3c8519d4e0d127f5cc106d Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 28 Apr 2023 15:58:42 +0200 Subject: media: v4l: async: Support fwnode endpoint list matching for subdevs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support matching V4L2 async sub-devices based on particular fwnode endpoint. This makes it possible to instantiate multiple V4L2 sub-devices based on given fwnode endpoints from a single device, based on driver needs. Signed-off-by: Sakari Ailus Tested-by: Philipp Zabel # imx6qp Tested-by: Niklas Söderlund # rcar + adv746x Tested-by: Aishwarya Kothari # Apalis i.MX6Q with TC358743 Tested-by: Lad Prabhakar # Renesas RZ/G2L SMARC Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-async.h | 30 ++++++++++++++++++++++++++++++ include/media/v4l2-subdev.h | 8 ++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) (limited to 'include/media') diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 8670b8e44851..41a9c4bada8a 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -125,6 +125,18 @@ struct v4l2_async_notifier { struct list_head notifier_entry; }; +/** + * struct v4l2_async_subdev_endpoint - Entry in sub-device's fwnode list + * + * @async_subdev_endpoint_entry: An entry in async_subdev_endpoint_list of + * &struct v4l2_subdev + * @endpoint: Endpoint fwnode agains which to match the sub-device + */ +struct v4l2_async_subdev_endpoint { + struct list_head async_subdev_endpoint_entry; + struct fwnode_handle *endpoint; +}; + /** * v4l2_async_debug_init - Initialize debugging tools. * @@ -215,6 +227,24 @@ __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, ((type *)__v4l2_async_nf_add_i2c(notifier, adapter, address, \ sizeof(type))) +/** + * v4l2_async_subdev_endpoint_add - Add an endpoint fwnode to async sub-device + * matching list + * + * @sd: the sub-device + * @fwnode: the endpoint fwnode to match + * + * Add a fwnode to the async sub-device's matching list. This allows registering + * multiple async sub-devices from a single device. + * + * Note that calling v4l2_subdev_cleanup() as part of the sub-device's cleanup + * if endpoints have been added to the sub-device's fwnode matching list. + * + * Returns an error on failure, 0 on success. + */ +int v4l2_async_subdev_endpoint_add(struct v4l2_subdev *sd, + struct fwnode_handle *fwnode); + /** * v4l2_async_connection_unique - return a unique &struct v4l2_async_connection * for a sub-device diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index a8078ae99596..a012741cc876 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -1022,6 +1022,8 @@ struct v4l2_subdev_platform_data { * either dev->of_node->fwnode or dev->fwnode (whichever is non-NULL). * @async_list: Links this subdev to a global subdev_list or * @notifier->done_list list. + * @async_subdev_endpoint_list: List entry in async_subdev_endpoint_entry of + * &struct v4l2_async_subdev_endpoint. * @subdev_notifier: A sub-device notifier implicitly registered for the sub- * device using v4l2_async_register_subdev_sensor(). * @asc_list: Async connection list, of &struct @@ -1065,6 +1067,7 @@ struct v4l2_subdev { struct device *dev; struct fwnode_handle *fwnode; struct list_head async_list; + struct list_head async_subdev_endpoint_list; struct v4l2_async_notifier *subdev_notifier; struct list_head asc_list; struct v4l2_subdev_platform_data *pdata; @@ -1382,8 +1385,9 @@ int __v4l2_subdev_init_finalize(struct v4l2_subdev *sd, const char *name, * v4l2_subdev_cleanup() - Releases the resources allocated by the subdevice * @sd: The subdevice * - * This function will release the resources allocated in - * v4l2_subdev_init_finalize. + * Clean up a V4L2 async sub-device. Must be called for a sub-device as part of + * its release if resources have been associated with it using + * v4l2_async_subdev_endpoint_add() or v4l2_subdev_init_finalize(). */ void v4l2_subdev_cleanup(struct v4l2_subdev *sd); -- cgit From b8ec754ae4c563f6aab8c0cb47aeb2eae67f1da3 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Thu, 23 Feb 2023 16:24:48 +0100 Subject: media: v4l: async: Set v4l2_device and subdev in async notifier init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the v4l2_device already in async notifier init, so struct device related to it will be available before the notifier is registered. This requires separating notifier initialisation into two functions, one that takes v4l2_device as its argument, v4l2_async_nf_init and v4l2_async_subdev_nf_init, for sub-device notifiers. Registering the notifier will use a single function, v4l2_async_nf_register. This is done in order to make struct device available earlier, during construction of the async connections, for sensible debug prints. Signed-off-by: Sakari Ailus Tested-by: Philipp Zabel # imx6qp Tested-by: Niklas Söderlund # rcar + adv746x Tested-by: Aishwarya Kothari # Apalis i.MX6Q with TC358743 Tested-by: Lad Prabhakar # Renesas RZ/G2L SMARC Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-async.h | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'include/media') diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index 41a9c4bada8a..9bd326d31181 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -148,13 +148,30 @@ void v4l2_async_debug_init(struct dentry *debugfs_dir); * v4l2_async_nf_init - Initialize a notifier. * * @notifier: pointer to &struct v4l2_async_notifier + * @v4l2_dev: pointer to &struct v4l2_device + * + * This function initializes the notifier @asc_entry. It must be called + * before adding a subdevice to a notifier, using one of: + * v4l2_async_nf_add_fwnode_remote(), + * v4l2_async_nf_add_fwnode() or + * v4l2_async_nf_add_i2c(). + */ +void v4l2_async_nf_init(struct v4l2_async_notifier *notifier, + struct v4l2_device *v4l2_dev); + +/** + * v4l2_async_subdev_nf_init - Initialize a sub-device notifier. + * + * @notifier: pointer to &struct v4l2_async_notifier + * @sd: pointer to &struct v4l2_subdev * * This function initializes the notifier @asc_list. It must be called * before adding a subdevice to a notifier, using one of: * v4l2_async_nf_add_fwnode_remote(), v4l2_async_nf_add_fwnode() or * v4l2_async_nf_add_i2c(). */ -void v4l2_async_nf_init(struct v4l2_async_notifier *notifier); +void v4l2_async_subdev_nf_init(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd); struct v4l2_async_connection * __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier, @@ -259,21 +276,9 @@ v4l2_async_connection_unique(struct v4l2_subdev *sd); /** * v4l2_async_nf_register - registers a subdevice asynchronous notifier * - * @v4l2_dev: pointer to &struct v4l2_device - * @notifier: pointer to &struct v4l2_async_notifier - */ -int v4l2_async_nf_register(struct v4l2_device *v4l2_dev, - struct v4l2_async_notifier *notifier); - -/** - * v4l2_async_subdev_nf_register - registers a subdevice asynchronous - * notifier for a sub-device - * - * @sd: pointer to &struct v4l2_subdev * @notifier: pointer to &struct v4l2_async_notifier */ -int v4l2_async_subdev_nf_register(struct v4l2_subdev *sd, - struct v4l2_async_notifier *notifier); +int v4l2_async_nf_register(struct v4l2_async_notifier *notifier); /** * v4l2_async_nf_unregister - unregisters a subdevice -- cgit From da53c36ddd3f118a525a04faa8c47ca471e6c467 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 12 Jun 2023 15:58:37 +0200 Subject: media: cec: core: add adap_nb_transmit_canceled() callback A potential deadlock was found by Zheng Zhang with a local syzkaller instance. The problem is that when a non-blocking CEC transmit is canceled by calling cec_data_cancel, that in turn can call the high-level received() driver callback, which can call cec_transmit_msg() to transmit a new message. The cec_data_cancel() function is called with the adap->lock mutex held, and cec_transmit_msg() tries to take that same lock. The root cause is that the received() callback can either be used to pass on a received message (and then adap->lock is not held), or to report a canceled transmit (and then adap->lock is held). This is confusing, so create a new low-level adap_nb_transmit_canceled callback that reports back that a non-blocking transmit was canceled. And the received() callback is only called when a message is received, as was the case before commit f9d0ecbf56f4 ("media: cec: correctly pass on reply results") complicated matters. Reported-by: Zheng Zhang Signed-off-by: Hans Verkuil Fixes: f9d0ecbf56f4 ("media: cec: correctly pass on reply results") Signed-off-by: Mauro Carvalho Chehab --- include/media/cec.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'include/media') diff --git a/include/media/cec.h b/include/media/cec.h index abee41ae02d0..6556cc161dc0 100644 --- a/include/media/cec.h +++ b/include/media/cec.h @@ -121,14 +121,16 @@ struct cec_adap_ops { void (*adap_configured)(struct cec_adapter *adap, bool configured); int (*adap_transmit)(struct cec_adapter *adap, u8 attempts, u32 signal_free_time, struct cec_msg *msg); + void (*adap_nb_transmit_canceled)(struct cec_adapter *adap, + const struct cec_msg *msg); void (*adap_status)(struct cec_adapter *adap, struct seq_file *file); void (*adap_free)(struct cec_adapter *adap); - /* Error injection callbacks */ + /* Error injection callbacks, called without adap->lock held */ int (*error_inj_show)(struct cec_adapter *adap, struct seq_file *sf); bool (*error_inj_parse_line)(struct cec_adapter *adap, char *line); - /* High-level CEC message callback */ + /* High-level CEC message callback, called without adap->lock held */ int (*received)(struct cec_adapter *adap, struct cec_msg *msg); }; -- cgit From 948a77aaecf202f722cf2264025f9987e5bd5c26 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 12 Jun 2023 15:58:38 +0200 Subject: media: cec: core: add adap_unconfigured() callback The adap_configured() callback was called with the adap->lock mutex held if the 'configured' argument was false, and without the adap->lock mutex held if that argument was true. That was very confusing, and so split this up in a adap_unconfigured() callback and a high-level configured() callback. This also makes it easier to understand when the mutex is held: all low-level adap_* callbacks are called with the mutex held. All other callbacks are called without that mutex held. Signed-off-by: Hans Verkuil Fixes: f1b57164305d ("media: cec: add optional adap_configured callback") Signed-off-by: Mauro Carvalho Chehab --- include/media/cec.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include/media') diff --git a/include/media/cec.h b/include/media/cec.h index 6556cc161dc0..9c007f83569a 100644 --- a/include/media/cec.h +++ b/include/media/cec.h @@ -113,12 +113,12 @@ struct cec_fh { #define CEC_FREE_TIME_TO_USEC(ft) ((ft) * 2400) struct cec_adap_ops { - /* Low-level callbacks */ + /* Low-level callbacks, called with adap->lock held */ int (*adap_enable)(struct cec_adapter *adap, bool enable); int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable); int (*adap_monitor_pin_enable)(struct cec_adapter *adap, bool enable); int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr); - void (*adap_configured)(struct cec_adapter *adap, bool configured); + void (*adap_unconfigured)(struct cec_adapter *adap); int (*adap_transmit)(struct cec_adapter *adap, u8 attempts, u32 signal_free_time, struct cec_msg *msg); void (*adap_nb_transmit_canceled)(struct cec_adapter *adap, @@ -131,6 +131,7 @@ struct cec_adap_ops { bool (*error_inj_parse_line)(struct cec_adapter *adap, char *line); /* High-level CEC message callback, called without adap->lock held */ + void (*configured)(struct cec_adapter *adap); int (*received)(struct cec_adapter *adap, struct cec_msg *msg); }; -- cgit From bb05820e87dc81469efc7262149d2b945a28527a Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 19 Jun 2023 13:27:06 +0200 Subject: media: subdev: Constify v4l2_subdev_set_routing_with_fmt() param The routing parameter of v4l2_subdev_set_routing_with_fmt() is missing 'const'. Add it. Signed-off-by: Tomi Valkeinen Reviewed-by: Jacopo Mondi Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-subdev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/media') diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index a012741cc876..d9fca929c10b 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -1535,7 +1535,7 @@ __v4l2_subdev_next_active_route(const struct v4l2_subdev_krouting *routing, */ int v4l2_subdev_set_routing_with_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, - struct v4l2_subdev_krouting *routing, + const struct v4l2_subdev_krouting *routing, const struct v4l2_mbus_framefmt *fmt); /** -- cgit From 613cbb91e9cee7cf5a61f0816d2acab7bc117407 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 27 Jun 2023 14:51:04 +0200 Subject: media: Add MIPI CCI register access helper functions The CSI2 specification specifies a standard method to access camera sensor registers called "Camera Control Interface (CCI)". This uses either 8 or 16 bit (big-endian wire order) register addresses and supports 8, 16, 24 or 32 bit (big-endian wire order) register widths. Currently a lot of Linux camera sensor drivers all have their own custom helpers for this, often copy and pasted from other drivers. Add a set of generic helpers for this so that all sensor drivers can switch to a single common implementation. These helpers take an extra optional "int *err" function parameter, this can be used to chain a bunch of register accesses together with only a single error check at the end, rather than needing to error check each individual register access. The first failing call will set the contents of err to a non 0 value and all other calls will then become no-ops. Link: https://lore.kernel.org/linux-media/59aefa7f-7bf9-6736-6040-39551329cd0a@redhat.com/ Reviewed-by: Andy Shevchenko Tested-by: Tommaso Merciai Reviewed-by: Tommaso Merciai Signed-off-by: Hans de Goede Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- include/media/v4l2-cci.h | 125 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 include/media/v4l2-cci.h (limited to 'include/media') diff --git a/include/media/v4l2-cci.h b/include/media/v4l2-cci.h new file mode 100644 index 000000000000..0f6803e4b17e --- /dev/null +++ b/include/media/v4l2-cci.h @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * MIPI Camera Control Interface (CCI) register access helpers. + * + * Copyright (C) 2023 Hans de Goede + */ +#ifndef _V4L2_CCI_H +#define _V4L2_CCI_H + +#include + +struct i2c_client; +struct regmap; + +/** + * struct cci_reg_sequence - An individual write from a sequence of CCI writes + * + * @reg: Register address, use CCI_REG#() macros to encode reg width + * @val: Register value + * + * Register/value pairs for sequences of writes. + */ +struct cci_reg_sequence { + u32 reg; + u64 val; +}; + +/* + * Macros to define register address with the register width encoded + * into the higher bits. + */ +#define CCI_REG_ADDR_MASK GENMASK(15, 0) +#define CCI_REG_WIDTH_SHIFT 16 +#define CCI_REG_WIDTH_MASK GENMASK(19, 16) + +#define CCI_REG8(x) ((1 << CCI_REG_WIDTH_SHIFT) | (x)) +#define CCI_REG16(x) ((2 << CCI_REG_WIDTH_SHIFT) | (x)) +#define CCI_REG24(x) ((3 << CCI_REG_WIDTH_SHIFT) | (x)) +#define CCI_REG32(x) ((4 << CCI_REG_WIDTH_SHIFT) | (x)) +#define CCI_REG64(x) ((8 << CCI_REG_WIDTH_SHIFT) | (x)) + +/** + * cci_read() - Read a value from a single CCI register + * + * @map: Register map to read from + * @reg: Register address to read, use CCI_REG#() macros to encode reg width + * @val: Pointer to store read value + * @err: Optional pointer to store errors, if a previous error is set + * then the read will be skipped + * + * Return: %0 on success or a negative error code on failure. + */ +int cci_read(struct regmap *map, u32 reg, u64 *val, int *err); + +/** + * cci_write() - Write a value to a single CCI register + * + * @map: Register map to write to + * @reg: Register address to write, use CCI_REG#() macros to encode reg width + * @val: Value to be written + * @err: Optional pointer to store errors, if a previous error is set + * then the write will be skipped + * + * Return: %0 on success or a negative error code on failure. + */ +int cci_write(struct regmap *map, u32 reg, u64 val, int *err); + +/** + * cci_update_bits() - Perform a read/modify/write cycle on + * a single CCI register + * + * @map: Register map to update + * @reg: Register address to update, use CCI_REG#() macros to encode reg width + * @mask: Bitmask to change + * @val: New value for bitmask + * @err: Optional pointer to store errors, if a previous error is set + * then the update will be skipped + * + * Note this uses read-modify-write to update the bits, atomicity with regards + * to other cci_*() register access functions is NOT guaranteed. + * + * Return: %0 on success or a negative error code on failure. + */ +int cci_update_bits(struct regmap *map, u32 reg, u64 mask, u64 val, int *err); + +/** + * cci_multi_reg_write() - Write multiple registers to the device + * + * @map: Register map to write to + * @regs: Array of structures containing register-address, -value pairs to be + * written, register-addresses use CCI_REG#() macros to encode reg width + * @num_regs: Number of registers to write + * @err: Optional pointer to store errors, if a previous error is set + * then the write will be skipped + * + * Write multiple registers to the device where the set of register, value + * pairs are supplied in any order, possibly not all in a single range. + * + * Use of the CCI_REG#() macros to encode reg width is mandatory. + * + * For raw lists of register-address, -value pairs with only 8 bit + * wide writes regmap_multi_reg_write() can be used instead. + * + * Return: %0 on success or a negative error code on failure. + */ +int cci_multi_reg_write(struct regmap *map, const struct cci_reg_sequence *regs, + unsigned int num_regs, int *err); + +#if IS_ENABLED(CONFIG_V4L2_CCI_I2C) +/** + * devm_cci_regmap_init_i2c() - Create regmap to use with cci_*() register + * access functions + * + * @client: i2c_client to create the regmap for + * @reg_addr_bits: register address width to use (8 or 16) + * + * Note the memory for the created regmap is devm() managed, tied to the client. + * + * Return: %0 on success or a negative error code on failure. + */ +struct regmap *devm_cci_regmap_init_i2c(struct i2c_client *client, + int reg_addr_bits); +#endif + +#endif -- cgit From 057e4809f3b8b9ec6cd974c9ab1808e4c29962c5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 27 Jun 2023 14:51:08 +0200 Subject: media: Remove ov_16bit_addr_reg_helpers.h The helpers in this header are not used anywhere anymore, they have been superseded by the new CCI register access helpers. Reviewed-by: Laurent Pinchart Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- include/media/ov_16bit_addr_reg_helpers.h | 92 ------------------------------- 1 file changed, 92 deletions(-) delete mode 100644 include/media/ov_16bit_addr_reg_helpers.h (limited to 'include/media') diff --git a/include/media/ov_16bit_addr_reg_helpers.h b/include/media/ov_16bit_addr_reg_helpers.h deleted file mode 100644 index 1c60a50bd795..000000000000 --- a/include/media/ov_16bit_addr_reg_helpers.h +++ /dev/null @@ -1,92 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * I2C register access helpers for Omnivision OVxxxx image sensors which expect - * a 16 bit register address in big-endian format and which have 1-3 byte - * wide registers, in big-endian format (for the higher width registers). - * - * Based on the register helpers from drivers/media/i2c/ov2680.c which is: - * Copyright (C) 2018 Linaro Ltd - */ -#ifndef __OV_16BIT_ADDR_REG_HELPERS_H -#define __OV_16BIT_ADDR_REG_HELPERS_H - -#include -#include -#include - -static inline int ov_read_reg(struct i2c_client *client, u16 reg, - unsigned int len, u32 *val) -{ - u8 addr_buf[2], data_buf[4] = { }; - struct i2c_msg msgs[2]; - int ret; - - if (len > 4) - return -EINVAL; - - put_unaligned_be16(reg, addr_buf); - - msgs[0].addr = client->addr; - msgs[0].flags = 0; - msgs[0].len = ARRAY_SIZE(addr_buf); - msgs[0].buf = addr_buf; - - msgs[1].addr = client->addr; - msgs[1].flags = I2C_M_RD; - msgs[1].len = len; - msgs[1].buf = &data_buf[4 - len]; - - ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); - if (ret != ARRAY_SIZE(msgs)) { - dev_err(&client->dev, "read error: reg=0x%4x: %d\n", reg, ret); - return -EIO; - } - - *val = get_unaligned_be32(data_buf); - - return 0; -} - -#define ov_read_reg8(s, r, v) ov_read_reg(s, r, 1, v) -#define ov_read_reg16(s, r, v) ov_read_reg(s, r, 2, v) -#define ov_read_reg24(s, r, v) ov_read_reg(s, r, 3, v) - -static inline int ov_write_reg(struct i2c_client *client, u16 reg, - unsigned int len, u32 val) -{ - u8 buf[6]; - int ret; - - if (len > 4) - return -EINVAL; - - put_unaligned_be16(reg, buf); - put_unaligned_be32(val << (8 * (4 - len)), buf + 2); - ret = i2c_master_send(client, buf, len + 2); - if (ret != len + 2) { - dev_err(&client->dev, "write error: reg=0x%4x: %d\n", reg, ret); - return -EIO; - } - - return 0; -} - -#define ov_write_reg8(s, r, v) ov_write_reg(s, r, 1, v) -#define ov_write_reg16(s, r, v) ov_write_reg(s, r, 2, v) -#define ov_write_reg24(s, r, v) ov_write_reg(s, r, 3, v) - -static inline int ov_update_reg(struct i2c_client *client, u16 reg, u8 mask, u8 val) -{ - u32 readval; - int ret; - - ret = ov_read_reg8(client, reg, &readval); - if (ret < 0) - return ret; - - val = (readval & ~mask) | (val & mask); - - return ov_write_reg8(client, reg, val); -} - -#endif -- cgit From 21fabfb1072c44be9dd88ecf6c28ae88b24281db Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 5 Jul 2023 23:30:03 +0200 Subject: media: ipu-bridge: Move ipu-bridge.h to include/media/ Move ipu-bridge.h to include/media/, so that it can also be used by the atomisp code. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- include/media/ipu-bridge.h | 165 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 include/media/ipu-bridge.h (limited to 'include/media') diff --git a/include/media/ipu-bridge.h b/include/media/ipu-bridge.h new file mode 100644 index 000000000000..7d84b22b2111 --- /dev/null +++ b/include/media/ipu-bridge.h @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Author: Dan Scally */ +#ifndef __IPU_BRIDGE_H +#define __IPU_BRIDGE_H + +#include +#include +#include + +struct i2c_client; + +#define IPU_HID "INT343E" +#define IPU_MAX_LANES 4 +#define IPU_MAX_PORTS 4 +#define MAX_NUM_LINK_FREQS 3 + +/* Values are educated guesses as we don't have a spec */ +#define IPU_SENSOR_ROTATION_NORMAL 0 +#define IPU_SENSOR_ROTATION_INVERTED 1 + +#define IPU_SENSOR_CONFIG(_HID, _NR, ...) \ + (const struct ipu_sensor_config) { \ + .hid = _HID, \ + .nr_link_freqs = _NR, \ + .link_freqs = { __VA_ARGS__ } \ + } + +#define NODE_SENSOR(_HID, _PROPS) \ + (const struct software_node) { \ + .name = _HID, \ + .properties = _PROPS, \ + } + +#define NODE_PORT(_PORT, _SENSOR_NODE) \ + (const struct software_node) { \ + .name = _PORT, \ + .parent = _SENSOR_NODE, \ + } + +#define NODE_ENDPOINT(_EP, _PORT, _PROPS) \ + (const struct software_node) { \ + .name = _EP, \ + .parent = _PORT, \ + .properties = _PROPS, \ + } + +#define NODE_VCM(_TYPE) \ + (const struct software_node) { \ + .name = _TYPE, \ + } + +enum ipu_sensor_swnodes { + SWNODE_SENSOR_HID, + SWNODE_SENSOR_PORT, + SWNODE_SENSOR_ENDPOINT, + SWNODE_IPU_PORT, + SWNODE_IPU_ENDPOINT, + /* Must be last because it is optional / maybe empty */ + SWNODE_VCM, + SWNODE_COUNT +}; + +/* Data representation as it is in ACPI SSDB buffer */ +struct ipu_sensor_ssdb { + u8 version; + u8 sku; + u8 guid_csi2[16]; + u8 devfunction; + u8 bus; + u32 dphylinkenfuses; + u32 clockdiv; + u8 link; + u8 lanes; + u32 csiparams[10]; + u32 maxlanespeed; + u8 sensorcalibfileidx; + u8 sensorcalibfileidxInMBZ[3]; + u8 romtype; + u8 vcmtype; + u8 platforminfo; + u8 platformsubinfo; + u8 flash; + u8 privacyled; + u8 degree; + u8 mipilinkdefined; + u32 mclkspeed; + u8 controllogicid; + u8 reserved1[3]; + u8 mclkport; + u8 reserved2[13]; +} __packed; + +struct ipu_property_names { + char clock_frequency[16]; + char rotation[9]; + char orientation[12]; + char bus_type[9]; + char data_lanes[11]; + char remote_endpoint[16]; + char link_frequencies[17]; +}; + +struct ipu_node_names { + char port[7]; + char endpoint[11]; + char remote_port[7]; + char vcm[16]; +}; + +struct ipu_sensor_config { + const char *hid; + const u8 nr_link_freqs; + const u64 link_freqs[MAX_NUM_LINK_FREQS]; +}; + +struct ipu_sensor { + /* append ssdb.link(u8) in "-%u" format as suffix of HID */ + char name[ACPI_ID_LEN + 4]; + struct acpi_device *adev; + struct i2c_client *vcm_i2c_client; + + /* SWNODE_COUNT + 1 for terminating NULL */ + const struct software_node *group[SWNODE_COUNT + 1]; + struct software_node swnodes[SWNODE_COUNT]; + struct ipu_node_names node_names; + + u8 link; + u8 lanes; + u32 mclkspeed; + u32 rotation; + enum v4l2_fwnode_orientation orientation; + const char *vcm_type; + + struct ipu_property_names prop_names; + struct property_entry ep_properties[5]; + struct property_entry dev_properties[5]; + struct property_entry ipu_properties[3]; + struct software_node_ref_args local_ref[1]; + struct software_node_ref_args remote_ref[1]; + struct software_node_ref_args vcm_ref[1]; +}; + +typedef int (*ipu_parse_sensor_fwnode_t)(struct acpi_device *adev, + struct ipu_sensor *sensor); + +struct ipu_bridge { + struct device *dev; + ipu_parse_sensor_fwnode_t parse_sensor_fwnode; + char ipu_node_name[ACPI_ID_LEN]; + struct software_node ipu_hid_node; + u32 data_lanes[4]; + unsigned int n_sensors; + struct ipu_sensor sensors[IPU_MAX_PORTS]; +}; + +#if IS_ENABLED(CONFIG_IPU_BRIDGE) +int ipu_bridge_init(struct device *dev, + ipu_parse_sensor_fwnode_t parse_sensor_fwnode); +int ipu_bridge_parse_ssdb(struct acpi_device *adev, struct ipu_sensor *sensor); +#else +/* Use a define to avoid the @parse_sensor_fwnode argument getting evaluated */ +#define ipu_bridge_init(dev, parse_sensor_fwnode) (0) +#endif + +#endif -- cgit From 8e3e916e23f5ab0ceb046d57f4d41d53159b8192 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 5 Jul 2023 23:30:05 +0200 Subject: media: ipu-bridge: Add a runtime-pm device-link between VCM and sensor In most cases when a VCM is used there is a single integrated module with the sensor + VCM + lens. This means that the sensor and VCM often share regulators and possibly also something like a powerdown pin. In the ACPI tables this is modelled as a single ACPI device with multiple I2cSerialBus resources. On atomisp devices the regulators and clks are modelled as ACPI power-resources, which are controlled by the (ACPI) power state of the sensor. So the sensor must be in D0 power state for the VCM to work. To make this work add a device-link with DL_FLAG_PM_RUNTIME flag so that the sensor will automatically be runtime-resumed whenever the VCM is runtime-resumed. This requires the probing of the VCM and thus the creation of the VCM I2C-client to be delayed till after the sensor driver has bound. Move the instantiation of the VCM I2C-client to the v4l2_async_notifier bound op, so that it is done after the sensor driver has bound; and add code to add the device-link. This fixes the problem with the shared ACPI power-resources on atomisp2 and this avoids the need for VCM related workarounds on IPU3 / IPU6. E.g. until now the dw9719 driver needed to get and control a Vsio (V sensor IO) regulator since that needs to be enabled to enable I2C pass-through on the PMIC on the sensor module. So the driver was controlling this regulator even though the actual dw9719 chip has no Vsio pin / power-plane. This also removes the need for ipu_bridge_init() to return -EPROBE_DEFER since the VCM is now instantiated later. Reviewed-by: Andy Shevchenko Reviewed-by: Daniel Scally Tested-by: Daniel Scally Signed-off-by: Hans de Goede Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- include/media/ipu-bridge.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'include/media') diff --git a/include/media/ipu-bridge.h b/include/media/ipu-bridge.h index 7d84b22b2111..ceda2a801948 100644 --- a/include/media/ipu-bridge.h +++ b/include/media/ipu-bridge.h @@ -7,8 +7,6 @@ #include #include -struct i2c_client; - #define IPU_HID "INT343E" #define IPU_MAX_LANES 4 #define IPU_MAX_PORTS 4 @@ -117,7 +115,6 @@ struct ipu_sensor { /* append ssdb.link(u8) in "-%u" format as suffix of HID */ char name[ACPI_ID_LEN + 4]; struct acpi_device *adev; - struct i2c_client *vcm_i2c_client; /* SWNODE_COUNT + 1 for terminating NULL */ const struct software_node *group[SWNODE_COUNT + 1]; @@ -157,9 +154,11 @@ struct ipu_bridge { int ipu_bridge_init(struct device *dev, ipu_parse_sensor_fwnode_t parse_sensor_fwnode); int ipu_bridge_parse_ssdb(struct acpi_device *adev, struct ipu_sensor *sensor); +int ipu_bridge_instantiate_vcm(struct device *sensor); #else /* Use a define to avoid the @parse_sensor_fwnode argument getting evaluated */ #define ipu_bridge_init(dev, parse_sensor_fwnode) (0) +static inline int ipu_bridge_instantiate_vcm(struct device *s) { return 0; } #endif #endif -- cgit From c66821f381aed2c7c754d6ac8920a8665a3a01f7 Mon Sep 17 00:00:00 2001 From: Wentong Wu Date: Thu, 3 Aug 2023 07:38:14 +0200 Subject: media: pci: intel: Add IVSC support for IPU bridge driver Previously on ACPI platforms, sensors that are intended to be connected to an IPU device for use with the ipu3-cio2 driver lacking the necessary connection information in firmware. IPU bridge driver is to connect sensors to IPU device via software nodes. Currently IVSC located between IPU device and sensors is available in existing commercial platforms from multiple OEMs. But the connection information between them in firmware is also not enough to build V4L2 connection graph. This patch parses the connection properties from the SSDB buffer in DSDT and build the connection using software nodes. IVSC driver is based on MEI framework (previously known as HECI), it has two MEI clients, MEI CSI and MEI ACE. Both clients are used to communicate messages with IVSC firmware. Linux abstracts MEI client as a device, whose bus type is MEI. And the device is addressed by a GUID/UUID which is part of the device name of MEI client. After figured out MEI CSI via the UUID composed device name, this patch setup the connection between MEI CSI and IPU, and the connection between MEI CSI and sensor via software nodes. Signed-off-by: Wentong Wu Reviewed-by: Andy Shevchenko Signed-off-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- include/media/ipu-bridge.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'include/media') diff --git a/include/media/ipu-bridge.h b/include/media/ipu-bridge.h index ceda2a801948..bdc654a45521 100644 --- a/include/media/ipu-bridge.h +++ b/include/media/ipu-bridge.h @@ -53,7 +53,12 @@ enum ipu_sensor_swnodes { SWNODE_SENSOR_ENDPOINT, SWNODE_IPU_PORT, SWNODE_IPU_ENDPOINT, - /* Must be last because it is optional / maybe empty */ + /* below are optional / maybe empty */ + SWNODE_IVSC_HID, + SWNODE_IVSC_SENSOR_PORT, + SWNODE_IVSC_SENSOR_ENDPOINT, + SWNODE_IVSC_IPU_PORT, + SWNODE_IVSC_IPU_ENDPOINT, SWNODE_VCM, SWNODE_COUNT }; @@ -100,6 +105,8 @@ struct ipu_property_names { struct ipu_node_names { char port[7]; + char ivsc_sensor_port[7]; + char ivsc_ipu_port[7]; char endpoint[11]; char remote_port[7]; char vcm[16]; @@ -116,6 +123,10 @@ struct ipu_sensor { char name[ACPI_ID_LEN + 4]; struct acpi_device *adev; + struct device *csi_dev; + struct acpi_device *ivsc_adev; + char ivsc_name[ACPI_ID_LEN + 4]; + /* SWNODE_COUNT + 1 for terminating NULL */ const struct software_node *group[SWNODE_COUNT + 1]; struct software_node swnodes[SWNODE_COUNT]; @@ -132,9 +143,15 @@ struct ipu_sensor { struct property_entry ep_properties[5]; struct property_entry dev_properties[5]; struct property_entry ipu_properties[3]; + struct property_entry ivsc_properties[1]; + struct property_entry ivsc_sensor_ep_properties[4]; + struct property_entry ivsc_ipu_ep_properties[4]; + struct software_node_ref_args local_ref[1]; struct software_node_ref_args remote_ref[1]; struct software_node_ref_args vcm_ref[1]; + struct software_node_ref_args ivsc_sensor_ref[1]; + struct software_node_ref_args ivsc_ipu_ref[1]; }; typedef int (*ipu_parse_sensor_fwnode_t)(struct acpi_device *adev, -- cgit