linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows
@ 2020-11-30 13:31 Daniel Scally
  2020-11-30 13:31 ` [PATCH 01/18] property: Return true in fwnode_device_is_available for node types that do not implement this operation Daniel Scally
                   ` (17 more replies)
  0 siblings, 18 replies; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hello all

Previous version:

https://lore.kernel.org/linux-media/20201019225903.14276-1-djrscally@gmail.com/

This series aims to add support for webcams on laptops with ACPI tables
designed for use with CIO2 on Windows. There are two main parts; the
first is extending the ipu3-cio2 driver to allow for patching the
firmware via software_nodes if endpoints aren't defined by ACPI. Patch #13
deals directly with that, all preceding patches are either supplemental
changes or incidental fixes along the way.

The second main part is a way to handle the unusual definition of resource
destined for the sensors in these ACPI tables; regulators and GPIO lines
that are supposed to be consumed by the sensor are lumped in the _CRS of
a dummy ACPI device upon which the sensor is dependent. Patch 18 defines a
new driver to handle those dummy devices and map the resources to the
sensor instead. 14-17 are supporting changes for that driver.

Changelogs mostly in the individual patches, but a broad summary:

	- Altered fwnode_device_is_available() to return true if the
	fwnode_handle doesn't implement that operation.
	- Altered fwnode_graph_get_endpoint_by_id() to parse secondary
	if no endpoint found on primary.
	- Enforce parent->child ordering of software_nodes on registration
	- Added a function to get the next ACPI device with matching _HID,
	plus an iterator macro
	- Altered cio2-bridge.c to store the bridge struct (and basically
	everything else) in heap, plus removed the requirement to delay
	ipu3-cio2 probe until after the i2c devices were instantiated. 
	Also now ensured we handle multiple sensors with the same _HID.
	- Added a function to get devices _dependent_ on a given ACPI dev,
	according to their _DEP entries.
	- Added a function to explicitly construct the name of an I2C dev
	created from an ACPI dev.
	- Added a driver to handle the dummy ACPI devices discussed above.

Comments very welcome!

Dan Scally (1):
  i2c: i2c-core-base: Use the new i2c_acpi_dev_name() in
    i2c_set_dev_name()

Daniel Scally (16):
  property: Return true in fwnode_device_is_available for node types
    that do not implement this operation
  property: Add support for calling fwnode_graph_get_endpoint_by_id()
    for fwnode->secondary
  software_node: Fix failure to put() and get() references to children
    in software_node_get_next_child()
  software_node: Enforce parent before child ordering of nodes array for
    software_node_register_nodes()
  software_node: Alter software_node_unregister_nodes() to unregister
    the array in reverse order
  software_node: amend software_node_unregister_node_group() to perform
    unregistration of array in reverse order to be consistent with
    software_node_unregister_nodes()
  lib/test_printf.c: Use helper function to unwind array of
    software_nodes
  ipu3-cio2: Add T: entry to MAINTAINERS
  ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from
    multiple source files retaining ipu3-cio2 name
  media: v4l2-core: v4l2-async: Check possible match in match_fwnode
    based on sd->fwnode->secondary
  acpi: Add acpi_dev_get_next_match_dev() and macro to iterate through
    acpi_devices matching a given _HID
  ipu3-cio2: Add functionality allowing software_node connections to
    sensors on platforms designed for Windows
  acpi: utils: Add function to fetch dependent acpi_devices
  i2c: i2c-core-acpi: Add i2c_acpi_dev_name()
  gpio: gpiolib-acpi: Export acpi_get_gpiod()
  ipu3: Add driver for dummy INT3472 ACPI device

Heikki Krogerus (1):
  software_node: Add support for fwnode_graph*() family of functions

 MAINTAINERS                                   |   9 +
 drivers/acpi/utils.c                          |  98 ++++-
 drivers/base/property.c                       |   9 +
 drivers/base/swnode.c                         | 157 +++++++-
 drivers/gpio/gpiolib-acpi.c                   |   3 +-
 drivers/i2c/i2c-core-acpi.c                   |  14 +
 drivers/i2c/i2c-core-base.c                   |   2 +-
 drivers/media/pci/intel/ipu3/Kconfig          |  32 ++
 drivers/media/pci/intel/ipu3/Makefile         |   4 +
 drivers/media/pci/intel/ipu3/cio2-bridge.c    | 260 ++++++++++++
 drivers/media/pci/intel/ipu3/cio2-bridge.h    | 108 +++++
 drivers/media/pci/intel/ipu3/int3472.c        | 381 ++++++++++++++++++
 drivers/media/pci/intel/ipu3/int3472.h        |  96 +++++
 .../ipu3/{ipu3-cio2.c => ipu3-cio2-main.c}    |  27 ++
 drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   6 +
 drivers/media/v4l2-core/v4l2-async.c          |   8 +
 include/acpi/acpi_bus.h                       |   9 +
 include/linux/acpi.h                          |   5 +
 include/linux/i2c.h                           |   5 +
 lib/test_printf.c                             |   4 +-
 20 files changed, 1213 insertions(+), 24 deletions(-)
 create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
 create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h
 create mode 100644 drivers/media/pci/intel/ipu3/int3472.c
 create mode 100644 drivers/media/pci/intel/ipu3/int3472.h
 rename drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} (98%)

-- 
2.25.1


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

* [PATCH 01/18] property: Return true in fwnode_device_is_available for node types that do not implement this operation
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 16:05   ` Laurent Pinchart
                     ` (2 more replies)
  2020-11-30 13:31 ` [PATCH 02/18] property: Add support for calling fwnode_graph_get_endpoint_by_id() for fwnode->secondary Daniel Scally
                   ` (16 subsequent siblings)
  17 siblings, 3 replies; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

Some types of fwnode_handle do not implement the device_is_available()
check, such as those created by software_nodes. There isn't really a
meaningful way to check for the availability of a device that doesn't
actually exist, so if the check isn't implemented just assume that the
"device" is present.

Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	patch introduced

 drivers/base/property.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 4c43d30145c6..a5ca2306796f 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -785,9 +785,14 @@ EXPORT_SYMBOL_GPL(fwnode_handle_put);
 /**
  * fwnode_device_is_available - check if a device is available for use
  * @fwnode: Pointer to the fwnode of the device.
+ *
+ * For fwnode node types that don't implement the .device_is_available()
+ * operation, this function returns true.
  */
 bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
 {
+	if (!fwnode_has_op(fwnode, device_is_available))
+		return true;
 	return fwnode_call_bool_op(fwnode, device_is_available);
 }
 EXPORT_SYMBOL_GPL(fwnode_device_is_available);
-- 
2.25.1


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

* [PATCH 02/18] property: Add support for calling fwnode_graph_get_endpoint_by_id() for fwnode->secondary
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
  2020-11-30 13:31 ` [PATCH 01/18] property: Return true in fwnode_device_is_available for node types that do not implement this operation Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 16:08   ` Laurent Pinchart
  2020-11-30 17:29   ` Andy Shevchenko
  2020-11-30 13:31 ` [PATCH 03/18] software_node: Fix failure to put() and get() references to children in software_node_get_next_child() Daniel Scally
                   ` (15 subsequent siblings)
  17 siblings, 2 replies; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

This function is used to find fwnode endpoints against a device. In
some instances those endpoints are software nodes which are children of
fwnode->secondary. Add support to fwnode_graph_get_endpoint_by_id() to
find those endpoints by recursively calling itself passing the ptr to
fwnode->secondary in the event no endpoint is found for the primary.

Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	Patch introduced. In discussion in the last submission I noted
	that the CIO2 device doesn't have an ACPI fwnode - that turns
	out to be true for _some_ devices but not others, so we need
	this function to check the secondary too.

 drivers/base/property.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index a5ca2306796f..4ece6b086e36 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1162,6 +1162,10 @@ fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,
 		best_ep_id = fwnode_ep.id;
 	}
 
+	if (!best_ep && fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
+		return fwnode_graph_get_endpoint_by_id(fwnode->secondary, port,
+						       endpoint, flags);
+
 	return best_ep;
 }
 EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_by_id);
-- 
2.25.1


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

* [PATCH 03/18] software_node: Fix failure to put() and get() references to children in software_node_get_next_child()
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
  2020-11-30 13:31 ` [PATCH 01/18] property: Return true in fwnode_device_is_available for node types that do not implement this operation Daniel Scally
  2020-11-30 13:31 ` [PATCH 02/18] property: Add support for calling fwnode_graph_get_endpoint_by_id() for fwnode->secondary Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 16:10   ` Laurent Pinchart
  2020-11-30 17:30   ` Andy Shevchenko
  2020-11-30 13:31 ` [PATCH 04/18] software_node: Enforce parent before child ordering of nodes array for software_node_register_nodes() Daniel Scally
                   ` (14 subsequent siblings)
  17 siblings, 2 replies; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

The software_node_get_next_child() function currently does not hold
references to the child software_node that it finds or put the ref that
is held against the old child - fix that.

Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	Put reference to previous child.

 drivers/base/swnode.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index 010828fc785b..615a0c93e116 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -443,14 +443,18 @@ software_node_get_next_child(const struct fwnode_handle *fwnode,
 	struct swnode *c = to_swnode(child);
 
 	if (!p || list_empty(&p->children) ||
-	    (c && list_is_last(&c->entry, &p->children)))
+	    (c && list_is_last(&c->entry, &p->children))) {
+		fwnode_handle_put(child);
 		return NULL;
+	}
 
 	if (c)
 		c = list_next_entry(c, entry);
 	else
 		c = list_first_entry(&p->children, struct swnode, entry);
-	return &c->fwnode;
+
+	fwnode_handle_put(child);
+	return fwnode_handle_get(&c->fwnode);
 }
 
 static struct fwnode_handle *
-- 
2.25.1


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

* [PATCH 04/18] software_node: Enforce parent before child ordering of nodes array for software_node_register_nodes()
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (2 preceding siblings ...)
  2020-11-30 13:31 ` [PATCH 03/18] software_node: Fix failure to put() and get() references to children in software_node_get_next_child() Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 16:11   ` Laurent Pinchart
  2020-11-30 17:35   ` Andy Shevchenko
  2020-11-30 13:31 ` [PATCH 05/18] software_node: Alter software_node_unregister_nodes() to unregister the array in reverse order Daniel Scally
                   ` (13 subsequent siblings)
  17 siblings, 2 replies; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Registering software_nodes with the .parent member set to point to a
currently unregistered software_node has the potential for problems,
so enforce parent -> child ordering in arrays passed to this function.

Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	Patch introduced

 drivers/base/swnode.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index 615a0c93e116..af7930b3679e 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -700,14 +700,21 @@ int software_node_register_nodes(const struct software_node *nodes)
 	int i;
 
 	for (i = 0; nodes[i].name; i++) {
+		if (nodes[i].parent)
+			if (!software_node_to_swnode(nodes[i].parent)) {
+				ret = -EINVAL;
+				goto err_unregister_nodes;
+			}
+
 		ret = software_node_register(&nodes[i]);
-		if (ret) {
-			software_node_unregister_nodes(nodes);
-			return ret;
-		}
+		if (ret)
+			goto err_unregister_nodes;
 	}
 
 	return 0;
+err_unregister_nodes:
+	software_node_unregister_nodes(nodes);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(software_node_register_nodes);
 
-- 
2.25.1


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

* [PATCH 05/18] software_node: Alter software_node_unregister_nodes() to unregister the array in reverse order
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (3 preceding siblings ...)
  2020-11-30 13:31 ` [PATCH 04/18] software_node: Enforce parent before child ordering of nodes array for software_node_register_nodes() Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 16:14   ` Laurent Pinchart
  2020-11-30 17:45   ` Andy Shevchenko
  2020-11-30 13:31 ` [PATCH 06/18] software_node: amend software_node_unregister_node_group() to perform unregistration of array in reverse order to be consistent with software_node_unregister_nodes() Daniel Scally
                   ` (12 subsequent siblings)
  17 siblings, 2 replies; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Software nodes that are children of another software node should be
unregistered before their parent. To allow easy unregistering of an array
of software_nodes ordered parent to child, reverse the order in which
this function unregisters software_nodes.

Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	Switched this functionality from a new function to replacing
	the existing software_nodes_unregister_nodes()

 drivers/base/swnode.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index af7930b3679e..d39e1c76d98d 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -720,20 +720,25 @@ EXPORT_SYMBOL_GPL(software_node_register_nodes);
 
 /**
  * software_node_unregister_nodes - Unregister an array of software nodes
- * @nodes: Zero terminated array of software nodes to be unregistered
+ * @nodes: Zero terminated array of software nodes to be unregistered. If
+ * parent pointers are set up in any of the software nodes then the array
+ * MUST be ordered such that parents come before their children.
  *
  * Unregister multiple software nodes at once.
  *
- * NOTE: Be careful using this call if the nodes had parent pointers set up in
- * them before registering.  If so, it is wiser to remove the nodes
- * individually, in the correct order (child before parent) instead of relying
- * on the sequential order of the list of nodes in the array.
+ * NOTE: If you are uncertain whether the array is ordered such that
+ * parents will be unregistered before their children, it is wiser to
+ * remove the nodes individually, in the correct order (child before
+ * parent).
  */
 void software_node_unregister_nodes(const struct software_node *nodes)
 {
-	int i;
+	unsigned int i = 0;
+
+	while (nodes[i].name)
+		i++;
 
-	for (i = 0; nodes[i].name; i++)
+	while (i--)
 		software_node_unregister(&nodes[i]);
 }
 EXPORT_SYMBOL_GPL(software_node_unregister_nodes);
-- 
2.25.1


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

* [PATCH 06/18] software_node: amend software_node_unregister_node_group() to perform unregistration of array in reverse order to be consistent with software_node_unregister_nodes()
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (4 preceding siblings ...)
  2020-11-30 13:31 ` [PATCH 05/18] software_node: Alter software_node_unregister_nodes() to unregister the array in reverse order Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 16:17   ` Laurent Pinchart
                     ` (2 more replies)
  2020-11-30 13:31 ` [PATCH 07/18] software_node: Add support for fwnode_graph*() family of functions Daniel Scally
                   ` (11 subsequent siblings)
  17 siblings, 3 replies; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

To maintain consistency with software_node_unregister_nodes(), reverse
the order in which the software_node_unregister_node_group() function
unregisters nodes.

Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since v3:

	Patch introduced

 drivers/base/swnode.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index d39e1c76d98d..9bd0bb77ad5b 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -782,7 +782,10 @@ void software_node_unregister_node_group(const struct software_node **node_group
 	if (!node_group)
 		return;
 
-	for (i = 0; node_group[i]; i++)
+	while (node_group[i]->name)
+		i++;
+
+	while (i--)
 		software_node_unregister(node_group[i]);
 }
 EXPORT_SYMBOL_GPL(software_node_unregister_node_group);
-- 
2.25.1


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

* [PATCH 07/18] software_node: Add support for fwnode_graph*() family of functions
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (5 preceding siblings ...)
  2020-11-30 13:31 ` [PATCH 06/18] software_node: amend software_node_unregister_node_group() to perform unregistration of array in reverse order to be consistent with software_node_unregister_nodes() Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 16:25   ` Laurent Pinchart
  2020-11-30 13:31 ` [PATCH 08/18] lib/test_printf.c: Use helper function to unwind array of software_nodes Daniel Scally
                   ` (10 subsequent siblings)
  17 siblings, 1 reply; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

From: Heikki Krogerus <heikki.krogerus@linux.intel.com>

From: Heikki Krogerus <heikki.krogerus@linux.intel.com>

This implements the remaining .graph_* callbacks in the
fwnode operations vector for the software nodes. That makes
the fwnode_graph*() functions available in the drivers also
when software nodes are used.

The implementation tries to mimic the "OF graph" as much as
possible, but there is no support for the "reg" device
property. The ports will need to have the index in their
name which starts with "port" (for example "port0", "port1",
...) and endpoints will use the index of the software node
that is given to them during creation. The port nodes can
also be grouped under a specially named "ports" subnode,
just like in DT, if necessary.

The remote-endpoints are reference properties under the
endpoint nodes that are named "remote-endpoint".

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Co-developed-by: Daniel Scally <djrscally@gmail.com>
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
changes since RFC v3:
	- Simplified software_node_get_next_endpoint() a little
	- Squared away references in software_node_get_next_endpoint()
	and swnode_graph_find_next_port(), since they were affected by
	the change to the earlier patch that had *get_next_child() also
	put the previous reference.
	- Dropped Andy's R-b, since the code changed.
changes in RFC v3:
	- removed software_node_device_is_available
	- moved the change to software_node_get_next_child to a separate
	patch
	- switched to use fwnode_handle_put() in graph_get_next_endpoint()
	instead of software_node_put()

changes in RFC v2:
	- added software_node_device_is_available
	- altered software_node_get_next_child to get references
	- altered software_node_get_next_endpoint to release references
	to ports and avoid passing invalid combinations of swnodes to
	software_node_get_next_child
	- altered swnode_graph_find_next_port to release port rather than
	old

 drivers/base/swnode.c | 110 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 109 insertions(+), 1 deletion(-)

diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index 9bd0bb77ad5b..0c7a8d6b9ea8 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -540,6 +540,110 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
 	return 0;
 }
 
+static struct fwnode_handle *
+swnode_graph_find_next_port(const struct fwnode_handle *parent,
+			    struct fwnode_handle *port)
+{
+	struct fwnode_handle *old = port;
+
+	while ((port = software_node_get_next_child(parent, old))) {
+		if (!strncmp(to_swnode(port)->node->name, "port", 4))
+			return port;
+		old = port;
+	}
+
+	return NULL;
+}
+
+static struct fwnode_handle *
+software_node_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
+				      struct fwnode_handle *endpoint)
+{
+	struct swnode *swnode = to_swnode(fwnode);
+	struct fwnode_handle *old = endpoint;
+	struct fwnode_handle *parent;
+	struct fwnode_handle *port;
+
+	if (!swnode)
+		return NULL;
+
+	if (endpoint) {
+		port = software_node_get_parent(endpoint);
+		parent = software_node_get_parent(port);
+	} else {
+		parent = software_node_get_named_child_node(fwnode, "ports");
+		if (!parent)
+			parent = software_node_get(&swnode->fwnode);
+
+		port = swnode_graph_find_next_port(parent, NULL);
+	}
+
+	for (; port; port = swnode_graph_find_next_port(parent, port)) {
+		endpoint = software_node_get_next_child(port, old);
+		if (endpoint) {
+			fwnode_handle_put(port);
+			break;
+		}
+
+		/* No more endpoints for that port, so stop passing old */
+		old = NULL;
+	}
+
+	fwnode_handle_put(parent);
+
+	return endpoint;
+}
+
+static struct fwnode_handle *
+software_node_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
+{
+	struct swnode *swnode = to_swnode(fwnode);
+	const struct software_node_ref_args *ref;
+	const struct property_entry *prop;
+
+	if (!swnode)
+		return NULL;
+
+	prop = property_entry_get(swnode->node->properties, "remote-endpoint");
+	if (!prop || prop->type != DEV_PROP_REF || prop->is_inline)
+		return NULL;
+
+	ref = prop->pointer;
+
+	return software_node_get(software_node_fwnode(ref[0].node));
+}
+
+static struct fwnode_handle *
+software_node_graph_get_port_parent(struct fwnode_handle *fwnode)
+{
+	struct swnode *swnode = to_swnode(fwnode);
+	struct fwnode_handle *parent;
+
+	if (!strcmp(swnode->parent->node->name, "ports"))
+		parent = &swnode->parent->parent->fwnode;
+	else
+		parent = &swnode->parent->fwnode;
+
+	return software_node_get(parent);
+}
+
+static int
+software_node_graph_parse_endpoint(const struct fwnode_handle *fwnode,
+				   struct fwnode_endpoint *endpoint)
+{
+	struct swnode *swnode = to_swnode(fwnode);
+	int ret;
+
+	ret = kstrtou32(swnode->parent->node->name + 4, 10, &endpoint->port);
+	if (ret)
+		return ret;
+
+	endpoint->id = swnode->id;
+	endpoint->local_fwnode = fwnode;
+
+	return 0;
+}
+
 static const struct fwnode_operations software_node_ops = {
 	.get = software_node_get,
 	.put = software_node_put,
@@ -551,7 +655,11 @@ static const struct fwnode_operations software_node_ops = {
 	.get_parent = software_node_get_parent,
 	.get_next_child_node = software_node_get_next_child,
 	.get_named_child_node = software_node_get_named_child_node,
-	.get_reference_args = software_node_get_reference_args
+	.get_reference_args = software_node_get_reference_args,
+	.graph_get_next_endpoint = software_node_graph_get_next_endpoint,
+	.graph_get_remote_endpoint = software_node_graph_get_remote_endpoint,
+	.graph_get_port_parent = software_node_graph_get_port_parent,
+	.graph_parse_endpoint = software_node_graph_parse_endpoint,
 };
 
 /* -------------------------------------------------------------------------- */
-- 
2.25.1


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

* [PATCH 08/18] lib/test_printf.c: Use helper function to unwind array of software_nodes
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (6 preceding siblings ...)
  2020-11-30 13:31 ` [PATCH 07/18] software_node: Add support for fwnode_graph*() family of functions Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 15:54   ` Sergey Senozhatsky
  2020-11-30 16:26   ` Laurent Pinchart
  2020-11-30 13:31 ` [PATCH 09/18] ipu3-cio2: Add T: entry to MAINTAINERS Daniel Scally
                   ` (9 subsequent siblings)
  17 siblings, 2 replies; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Use the software_node_unregister_nodes() helper function to unwind this
array in a cleaner way.

Acked-by: Petr Mladek <pmladek@suse.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	Changed the called function name - didn't drop the tags since it's
	such a trivial change, hope that's alright!

 lib/test_printf.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/lib/test_printf.c b/lib/test_printf.c
index 7ac87f18a10f..7d60f24240a4 100644
--- a/lib/test_printf.c
+++ b/lib/test_printf.c
@@ -644,9 +644,7 @@ static void __init fwnode_pointer(void)
 	test(second_name, "%pfwP", software_node_fwnode(&softnodes[1]));
 	test(third_name, "%pfwP", software_node_fwnode(&softnodes[2]));
 
-	software_node_unregister(&softnodes[2]);
-	software_node_unregister(&softnodes[1]);
-	software_node_unregister(&softnodes[0]);
+	software_node_unregister_nodes(softnodes);
 }
 
 static void __init
-- 
2.25.1


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

* [PATCH 09/18] ipu3-cio2: Add T: entry to MAINTAINERS
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (7 preceding siblings ...)
  2020-11-30 13:31 ` [PATCH 08/18] lib/test_printf.c: Use helper function to unwind array of software_nodes Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 13:31 ` [PATCH 10/18] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple source files retaining ipu3-cio2 name Daniel Scally
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

Development for the ipu3-cio2 driver is taking place in media_tree, but
there's no T: entry in MAINTAINERS to denote that - rectify that oversight

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	- None

 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index e3a828249c8c..9702b886d6a4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8930,6 +8930,7 @@ M:	Bingbu Cao <bingbu.cao@intel.com>
 R:	Tianshu Qiu <tian.shu.qiu@intel.com>
 L:	linux-media@vger.kernel.org
 S:	Maintained
+T:	git git://linuxtv.org/media_tree.git
 F:	Documentation/userspace-api/media/v4l/pixfmt-srggb10-ipu3.rst
 F:	drivers/media/pci/intel/ipu3/
 
-- 
2.25.1


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

* [PATCH 10/18] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple source files retaining ipu3-cio2 name
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (8 preceding siblings ...)
  2020-11-30 13:31 ` [PATCH 09/18] ipu3-cio2: Add T: entry to MAINTAINERS Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-12-01  6:56   ` Bingbu Cao
  2020-11-30 13:31 ` [PATCH 11/18] media: v4l2-core: v4l2-async: Check possible match in match_fwnode based on sd->fwnode->secondary Daniel Scally
                   ` (7 subsequent siblings)
  17 siblings, 1 reply; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

ipu3-cio2 driver needs extending with multiple files; rename the main
source file and specify the renamed file in Makefile to accommodate that.

Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	- None

 drivers/media/pci/intel/ipu3/Makefile                          | 2 ++
 drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} | 0
 2 files changed, 2 insertions(+)
 rename drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} (100%)

diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
index 98ddd5beafe0..429d516452e4 100644
--- a/drivers/media/pci/intel/ipu3/Makefile
+++ b/drivers/media/pci/intel/ipu3/Makefile
@@ -1,2 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
+
+ipu3-cio2-y += ipu3-cio2-main.o
diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
similarity index 100%
rename from drivers/media/pci/intel/ipu3/ipu3-cio2.c
rename to drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
-- 
2.25.1


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

* [PATCH 11/18] media: v4l2-core: v4l2-async: Check possible match in match_fwnode based on sd->fwnode->secondary
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (9 preceding siblings ...)
  2020-11-30 13:31 ` [PATCH 10/18] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple source files retaining ipu3-cio2 name Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 16:27   ` Laurent Pinchart
  2020-11-30 17:55   ` Andy Shevchenko
  2020-11-30 13:31 ` [PATCH 12/18] acpi: Add acpi_dev_get_next_match_dev() and macro to iterate through acpi_devices matching a given _HID Daniel Scally
                   ` (6 subsequent siblings)
  17 siblings, 2 replies; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Where the fwnode graph is comprised of software_nodes, these will be
assigned as the secondary to dev->fwnode. Check the v4l2_subdev's fwnode
for a secondary and attempt to match against it during match_fwnode() to
accommodate that possibility.

Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	- None

 drivers/media/v4l2-core/v4l2-async.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index e3ab003a6c85..6486dbde784f 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -87,6 +87,14 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier,
 	if (sd->fwnode == asd->match.fwnode)
 		return true;
 
+	/*
+	 * Check the same situation for any possible secondary assigned to the
+	 * subdev's fwnode
+	 */
+	if ((!IS_ERR_OR_NULL(sd->fwnode->secondary)) &&
+	    sd->fwnode->secondary == asd->match.fwnode)
+		return true;
+
 	/*
 	 * Otherwise, check if the sd fwnode and the asd fwnode refer to an
 	 * endpoint or a device. If they're of the same type, there's no match.
-- 
2.25.1


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

* [PATCH 12/18] acpi: Add acpi_dev_get_next_match_dev() and macro to iterate through acpi_devices matching a given _HID
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (10 preceding siblings ...)
  2020-11-30 13:31 ` [PATCH 11/18] media: v4l2-core: v4l2-async: Check possible match in match_fwnode based on sd->fwnode->secondary Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 17:58   ` Andy Shevchenko
  2020-11-30 13:31 ` [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (5 subsequent siblings)
  17 siblings, 1 reply; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

To ensure we handle situations in which multiple sensors of the same
model (and therefore _HID) are present in a system, we need to be able
to iterate over devices matching a known _HID but unknown _UID and _HRV
 - add acpi_dev_get_next_match_dev() to accommodate that possibility and
change acpi_dev_get_first_match_dev() to simply call the new function
with a NULL starting point. Add an iterator macro for convenience.

Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	- Patch introduced

 drivers/acpi/utils.c    | 30 ++++++++++++++++++++++++++----
 include/acpi/acpi_bus.h |  7 +++++++
 2 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index d5411a166685..c177165c8db2 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -843,12 +843,13 @@ bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
 EXPORT_SYMBOL(acpi_dev_present);
 
 /**
- * acpi_dev_get_first_match_dev - Return the first match of ACPI device
+ * acpi_dev_get_next_match_dev - Return the next match of ACPI device
+ * @adev: Pointer to the previous acpi_device matching this hid, uid and hrv
  * @hid: Hardware ID of the device.
  * @uid: Unique ID of the device, pass NULL to not check _UID
  * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
  *
- * Return the first match of ACPI device if a matching device was present
+ * Return the next match of ACPI device if another matching device was present
  * at the moment of invocation, or NULL otherwise.
  *
  * The caller is responsible to call put_device() on the returned device.
@@ -856,8 +857,9 @@ EXPORT_SYMBOL(acpi_dev_present);
  * See additional information in acpi_dev_present() as well.
  */
 struct acpi_device *
-acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
+acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv)
 {
+	struct device *start = adev ? &adev->dev : NULL;
 	struct acpi_dev_match_info match = {};
 	struct device *dev;
 
@@ -865,9 +867,29 @@ acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
 	match.uid = uid;
 	match.hrv = hrv;
 
-	dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
+	dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
 	return dev ? to_acpi_device(dev) : NULL;
 }
+EXPORT_SYMBOL(acpi_dev_get_next_match_dev);
+
+/**
+ * acpi_dev_get_first_match_dev - Return the first match of ACPI device
+ * @hid: Hardware ID of the device.
+ * @uid: Unique ID of the device, pass NULL to not check _UID
+ * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
+ *
+ * Return the first match of ACPI device if a matching device was present
+ * at the moment of invocation, or NULL otherwise.
+ *
+ * The caller is responsible to call put_device() on the returned device.
+ *
+ * See additional information in acpi_dev_present() as well.
+ */
+struct acpi_device *
+acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
+{
+	return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
+}
 EXPORT_SYMBOL(acpi_dev_get_first_match_dev);
 
 /*
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index a3abcc4b7d9f..0a028ba967d3 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -688,9 +688,16 @@ static inline bool acpi_device_can_poweroff(struct acpi_device *adev)
 
 bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2);
 
+struct acpi_device *
+acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv);
 struct acpi_device *
 acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv);
 
+#define for_each_acpi_dev_match(adev, hid, uid, hrv)			\
+	for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv);	\
+	     adev;							\
+	     adev = acpi_dev_get_next_match_dev(adev, hid, uid, hrv))
+
 static inline void acpi_dev_put(struct acpi_device *adev)
 {
 	put_device(&adev->dev);
-- 
2.25.1


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

* [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (11 preceding siblings ...)
  2020-11-30 13:31 ` [PATCH 12/18] acpi: Add acpi_dev_get_next_match_dev() and macro to iterate through acpi_devices matching a given _HID Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 16:45   ` kernel test robot
                     ` (3 more replies)
  2020-11-30 13:31 ` [PATCH 14/18] acpi: utils: Add function to fetch dependent acpi_devices Daniel Scally
                   ` (4 subsequent siblings)
  17 siblings, 4 replies; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Currently on platforms designed for Windows, connections between CIO2 and
sensors are not properly defined in DSDT. This patch extends the ipu3-cio2
driver to compensate by building software_node connections, parsing the
connection properties from the sensor's SSDB buffer.

Suggested-by: Jordan Hand <jorhand@linux.microsoft.com>
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	- Removed almost all global variables, dynamically allocated
	the cio2_bridge structure, plus a bunch of associated changes
	like 
	- Added a new function to ipu3-cio2-main.c to check for an 
	existing fwnode_graph before calling cio2_bridge_init()
	- Prefixed cio2_bridge_ to any variables and functions that
	lacked it
	- Assigned the new fwnode directly to the sensor's ACPI device
	fwnode as secondary. This removes the requirement to delay until
	the I2C devices are instantiated before ipu3-cio2 can probe, but
	it has a side effect, which is that those devices then grab a ref
	to the new software_node. This effectively prevents us from
	unloading the driver, because we can't free the memory that they
	live in whilst the device holds a reference to them. The work
	around at the moment is to _not_ unregister the software_nodes
	when ipu3-cio2 is unloaded; this becomes a one-time 'patch', that
	is simply skipped if the module is reloaded.
	- Moved the sensor's SSDB struct to be a member of cio2_sensor
	- Replaced ints with unsigned ints where appropriate
	- Iterated over all ACPI devices of a matching _HID rather than
	just the first to ensure we handle a device with multiple sensors
	of the same model.

 MAINTAINERS                                   |   1 +
 drivers/media/pci/intel/ipu3/Kconfig          |  18 ++
 drivers/media/pci/intel/ipu3/Makefile         |   1 +
 drivers/media/pci/intel/ipu3/cio2-bridge.c    | 260 ++++++++++++++++++
 drivers/media/pci/intel/ipu3/cio2-bridge.h    | 108 ++++++++
 drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  27 ++
 drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   6 +
 7 files changed, 421 insertions(+)
 create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
 create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 9702b886d6a4..188559a0a610 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8927,6 +8927,7 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
 M:	Yong Zhi <yong.zhi@intel.com>
 M:	Sakari Ailus <sakari.ailus@linux.intel.com>
 M:	Bingbu Cao <bingbu.cao@intel.com>
+M:	Dan Scally <djrscally@gmail.com>
 R:	Tianshu Qiu <tian.shu.qiu@intel.com>
 L:	linux-media@vger.kernel.org
 S:	Maintained
diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
index 82d7f17e6a02..2b3350d042be 100644
--- a/drivers/media/pci/intel/ipu3/Kconfig
+++ b/drivers/media/pci/intel/ipu3/Kconfig
@@ -16,3 +16,21 @@ config VIDEO_IPU3_CIO2
 	  Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2
 	  connected camera.
 	  The module will be called ipu3-cio2.
+
+config CIO2_BRIDGE
+	bool "IPU3 CIO2 Sensors Bridge"
+	depends on VIDEO_IPU3_CIO2
+	help
+	  This extension provides an API for the ipu3-cio2 driver to create
+	  connections to cameras that are hidden in SSDB buffer in ACPI. It
+	  can be used to enable support for cameras in detachable / hybrid
+	  devices that ship with Windows.
+
+	  Say Y here if your device is a detachable / hybrid laptop that comes
+	  with Windows installed by the OEM, for example:
+
+	  	- Microsoft Surface models (except Surface Pro 3)
+		- The Lenovo Miix line (for example the 510, 520, 710 and 720)
+		- Dell 7285
+
+	  If in doubt, say N here.
diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
index 429d516452e4..933777e6ea8a 100644
--- a/drivers/media/pci/intel/ipu3/Makefile
+++ b/drivers/media/pci/intel/ipu3/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
 
 ipu3-cio2-y += ipu3-cio2-main.o
+ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
new file mode 100644
index 000000000000..fd3f8ba07274
--- /dev/null
+++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Author: Dan Scally <djrscally@gmail.com> */
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/property.h>
+#include <media/v4l2-subdev.h>
+
+#include "cio2-bridge.h"
+
+/*
+ * Extend this array with ACPI Hardware ID's of devices known to be working.
+ * Do not add a HID for a sensor that is not actually supported.
+ */
+static const char * const cio2_supported_devices[] = {
+	"INT33BE",
+	"OVTI2680",
+};
+
+static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id,
+					void *data, u32 size)
+{
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *obj;
+	acpi_status status;
+	int ret;
+
+	status = acpi_evaluate_object(adev->handle, id, NULL, &buffer);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	obj = buffer.pointer;
+	if (!obj) {
+		dev_err(&adev->dev, "Couldn't locate ACPI buffer\n");
+		return -ENODEV;
+	}
+
+	if (obj->type != ACPI_TYPE_BUFFER) {
+		dev_err(&adev->dev, "Not an ACPI buffer\n");
+		ret = -ENODEV;
+		goto out_free_buff;
+	}
+
+	if (obj->buffer.length > size) {
+		dev_err(&adev->dev, "Given buffer is too small\n");
+		ret = -EINVAL;
+		goto out_free_buff;
+	}
+
+	memcpy(data, obj->buffer.pointer, obj->buffer.length);
+	ret = obj->buffer.length;
+
+out_free_buff:
+	kfree(buffer.pointer);
+	return ret;
+}
+
+static void cio2_bridge_init_property_names(struct cio2_sensor *sensor)
+{
+	strcpy(sensor->prop_names.clock_frequency, "clock-frequency");
+	strcpy(sensor->prop_names.rotation, "rotation");
+	strcpy(sensor->prop_names.bus_type, "bus-type");
+	strcpy(sensor->prop_names.data_lanes, "data-lanes");
+	strcpy(sensor->prop_names.remote_endpoint, "remote-endpoint");
+}
+
+static void cio2_bridge_create_fwnode_properties(struct cio2_sensor *sensor)
+{
+	unsigned int i;
+
+	cio2_bridge_init_property_names(sensor);
+
+	for (i = 0; i < 4; i++)
+		sensor->data_lanes[i] = i + 1;
+
+	/*
+	 * Can't use PROPERTY_ENTRY_REF because it creates a new variable to
+	 * point to, which doesn't survive the function.
+	 */
+	sensor->local_ref[0] = (struct software_node_ref_args){
+		.node = &sensor->swnodes[SWNODE_CIO2_ENDPOINT]
+		};
+	sensor->remote_ref[0] = (struct software_node_ref_args){
+		.node = &sensor->swnodes[SWNODE_SENSOR_ENDPOINT]
+		};
+
+	sensor->dev_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.clock_frequency,
+						       sensor->ssdb.mclkspeed);
+	sensor->dev_properties[1] = PROPERTY_ENTRY_U8(sensor->prop_names.rotation,
+						      sensor->ssdb.degree);
+
+	sensor->ep_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.bus_type, 5);
+	sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes,
+								sensor->data_lanes,
+								sensor->ssdb.lanes);
+	sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint,
+							    sensor->local_ref);
+
+	sensor->cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes,
+								  sensor->data_lanes,
+								  sensor->ssdb.lanes);
+	sensor->cio2_properties[1] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint,
+							      sensor->remote_ref);
+}
+
+static void cio2_bridge_init_swnode_names(struct cio2_sensor *sensor)
+{
+	snprintf(sensor->node_names.remote_port, 6, "port%u", sensor->ssdb.link);
+	strcpy(sensor->node_names.port, "port0");
+	strcpy(sensor->node_names.endpoint, "endpoint0");
+}
+
+static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge,
+						  struct cio2_sensor *sensor)
+{
+	struct software_node *nodes = sensor->swnodes;
+
+	cio2_bridge_init_swnode_names(sensor);
+
+	nodes[SWNODE_SENSOR_HID] = NODE_SENSOR(sensor->name,
+					       sensor->dev_properties);
+	nodes[SWNODE_SENSOR_PORT] = NODE_PORT(sensor->node_names.port,
+					      &nodes[SWNODE_SENSOR_HID]);
+	nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint,
+						      &nodes[SWNODE_SENSOR_PORT],
+						      sensor->ep_properties);
+	nodes[SWNODE_CIO2_PORT] = NODE_PORT(sensor->node_names.remote_port,
+					    &bridge->cio2_hid_node);
+	nodes[SWNODE_CIO2_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint,
+						    &nodes[SWNODE_CIO2_PORT],
+						    sensor->cio2_properties);
+}
+
+static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge)
+{
+	struct cio2_sensor *sensor;
+	unsigned int i;
+
+	for (i = 0; i < bridge->n_sensors; i++) {
+		sensor = &bridge->sensors[i];
+		software_node_unregister_nodes(sensor->swnodes);
+		acpi_dev_put(sensor->adev);
+	}
+}
+
+static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge)
+{
+	struct fwnode_handle *fwnode;
+	struct cio2_sensor *sensor;
+	struct acpi_device *adev;
+	unsigned int i;
+	int ret = 0;
+
+	for (i = 0; i < ARRAY_SIZE(cio2_supported_devices); i++) {
+		const char *this_device = cio2_supported_devices[i];
+
+		for_each_acpi_dev_match(adev, this_device, NULL, -1) {
+			if (!adev || !(adev->status.present && adev->status.enabled))
+				continue;
+
+			sensor = &bridge->sensors[bridge->n_sensors];
+			sensor->adev = adev;
+			strscpy(sensor->name, this_device, sizeof(sensor->name));
+
+			ret = cio2_bridge_read_acpi_buffer(adev, "SSDB",
+							   &sensor->ssdb,
+							   sizeof(sensor->ssdb));
+			if (ret < 0)
+				goto err_put_adev;
+
+			if (sensor->ssdb.lanes > 4) {
+				dev_err(&adev->dev,
+					"Number of lanes in SSDB is invalid\n");
+				goto err_put_adev;
+			}
+
+			cio2_bridge_create_fwnode_properties(sensor);
+			cio2_bridge_create_connection_swnodes(bridge, sensor);
+
+			ret = software_node_register_nodes(sensor->swnodes);
+			if (ret)
+				goto err_put_adev;
+
+			fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR_HID]);
+			if (!fwnode) {
+				ret = -ENODEV;
+				goto err_free_swnodes;
+			}
+
+			adev->fwnode.secondary = fwnode;
+
+			dev_info(&bridge->cio2->dev,
+				 "Found supported sensor %s\n",
+				 acpi_dev_name(adev));
+
+			bridge->n_sensors++;
+		}
+	}
+
+	return ret;
+
+err_free_swnodes:
+	software_node_unregister_nodes(sensor->swnodes);
+err_put_adev:
+	acpi_dev_put(sensor->adev);
+
+	return ret;
+}
+
+int cio2_bridge_init(struct pci_dev *cio2)
+{
+	struct device *dev = &cio2->dev;
+	struct fwnode_handle *fwnode;
+	struct cio2_bridge *bridge;
+	int ret;
+
+	bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
+	if (!bridge)
+		return -ENOMEM;
+
+	strscpy(bridge->cio2_node_name, CIO2_HID, sizeof(bridge->cio2_node_name));
+	bridge->cio2_hid_node = (const struct software_node){ bridge->cio2_node_name };
+	bridge->cio2 = pci_dev_get(cio2);
+
+	ret = software_node_register(&bridge->cio2_hid_node);
+	if (ret < 0) {
+		dev_err(dev, "Failed to register the CIO2 HID node\n");
+		goto err_put_cio2;
+	}
+
+	ret = cio2_bridge_connect_sensors(bridge);
+	if (ret || bridge->n_sensors == 0)
+		goto err_unregister_cio2;
+
+	dev_info(dev, "Connected %d cameras\n", bridge->n_sensors);
+
+	fwnode = software_node_fwnode(&bridge->cio2_hid_node);
+	if (!fwnode) {
+		dev_err(dev, "Error getting fwnode from cio2 software_node\n");
+		ret = -ENODEV;
+		goto err_unregister_sensors;
+	}
+
+	set_secondary_fwnode(dev, fwnode);
+
+	return 0;
+
+err_unregister_sensors:
+	cio2_bridge_unregister_sensors(bridge);
+err_unregister_cio2:
+	software_node_unregister(&bridge->cio2_hid_node);
+err_put_cio2:
+	pci_dev_put(bridge->cio2);
+
+	kfree(bridge);
+	return ret;
+}
diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h
new file mode 100644
index 000000000000..96f5c8a12be0
--- /dev/null
+++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Author: Dan Scally <djrscally@gmail.com> */
+#ifndef __CIO2_BRIDGE_H
+#define __CIO2_BRIDGE_H
+
+#include <linux/property.h>
+
+#define CIO2_HID				"INT343E"
+#define CIO2_NUM_PORTS			  4
+
+#define NODE_SENSOR(_HID, _PROPS)		\
+	((const struct software_node) {		\
+		.name = _HID,			\
+		.properties = _PROPS,		\
+	})
+
+#define NODE_PORT(_PORT, _SENSOR_NODE)		\
+	((const struct software_node) {		\
+		_PORT,				\
+		_SENSOR_NODE,			\
+	})
+
+#define NODE_ENDPOINT(_EP, _PORT, _PROPS)	\
+	((const struct software_node) {		\
+		_EP,				\
+		_PORT,				\
+		_PROPS,				\
+	})
+
+enum cio2_sensor_swnodes {
+	SWNODE_SENSOR_HID,
+	SWNODE_SENSOR_PORT,
+	SWNODE_SENSOR_ENDPOINT,
+	SWNODE_CIO2_PORT,
+	SWNODE_CIO2_ENDPOINT,
+	NR_OF_SENSOR_SWNODES
+};
+
+/* Data representation as it is in ACPI SSDB buffer */
+struct cio2_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 cio2_property_names {
+	char clock_frequency[16];
+	char rotation[9];
+	char bus_type[9];
+	char data_lanes[11];
+	char remote_endpoint[16];
+};
+
+struct cio2_node_names {
+	char port[6];
+	char endpoint[10];
+	char remote_port[6];
+};
+
+struct cio2_sensor {
+	char name[ACPI_ID_LEN];
+	struct acpi_device *adev;
+
+	struct software_node swnodes[6];
+	struct cio2_node_names node_names;
+
+	u32 data_lanes[4];
+	struct cio2_sensor_ssdb ssdb;
+	struct cio2_property_names prop_names;
+	struct property_entry ep_properties[4];
+	struct property_entry dev_properties[3];
+	struct property_entry cio2_properties[3];
+	struct software_node_ref_args local_ref[1];
+	struct software_node_ref_args remote_ref[1];
+};
+
+struct cio2_bridge {
+	struct pci_dev *cio2;
+	char cio2_node_name[ACPI_ID_LEN];
+	struct software_node cio2_hid_node;
+	unsigned int n_sensors;
+	struct cio2_sensor sensors[CIO2_NUM_PORTS];
+};
+
+#endif
diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
index 36e354ecf71e..0d69b593e9f0 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
@@ -1702,6 +1702,22 @@ static void cio2_queues_exit(struct cio2_device *cio2)
 		cio2_queue_exit(cio2, &cio2->queue[i]);
 }
 
+static bool cio2_check_fwnode_graph(struct fwnode_handle *fwnode)
+{
+	struct fwnode_handle *endpoint;
+
+	if (IS_ERR_OR_NULL(fwnode))
+		return false;
+
+	endpoint = fwnode_graph_get_next_endpoint(fwnode, NULL);
+	if (endpoint) {
+		fwnode_handle_put(endpoint);
+		return true;
+	}
+
+	return cio2_check_fwnode_graph(fwnode->secondary);
+}
+
 /**************** PCI interface ****************/
 
 static int cio2_pci_probe(struct pci_dev *pci_dev,
@@ -1715,6 +1731,17 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
 		return -ENOMEM;
 	cio2->pci_dev = pci_dev;
 
+	/*
+	 * On some platforms no connections to sensors are defined in firmware,
+	 * if the device has no endpoints then we can try to build those as
+	 * software_nodes parsed from SSDB.
+	 */
+	if (!cio2_check_fwnode_graph(dev_fwnode(&pci_dev->dev))) {
+		r = cio2_bridge_init(pci_dev);
+		if (r)
+			return r;
+	}
+
 	r = pcim_enable_device(pci_dev);
 	if (r) {
 		dev_err(&pci_dev->dev, "failed to enable device (%d)\n", r);
diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.h b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
index ccf0b85ae36f..520a27c9cdad 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2.h
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
@@ -437,4 +437,10 @@ static inline struct cio2_queue *vb2q_to_cio2_queue(struct vb2_queue *vq)
 	return container_of(vq, struct cio2_queue, vbq);
 }
 
+#if IS_ENABLED(CONFIG_CIO2_BRIDGE)
+int cio2_bridge_init(struct pci_dev *cio2);
+#else
+int cio2_bridge_init(struct pci_dev *cio2) { return 0; }
+#endif
+
 #endif
-- 
2.25.1


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

* [PATCH 14/18] acpi: utils: Add function to fetch dependent acpi_devices
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (12 preceding siblings ...)
  2020-11-30 13:31 ` [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 18:23   ` Andy Shevchenko
  2020-11-30 13:31 ` [PATCH 15/18] i2c: i2c-core-acpi: Add i2c_acpi_dev_name() Daniel Scally
                   ` (3 subsequent siblings)
  17 siblings, 1 reply; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

ACPI devices declare themselves dependent on other devices via the _DEP
buffer. Fetching the dependee from dependent is a matter of parsing
_DEP, but currently there's no method to fetch dependent from dependee.
Add one, so we can parse sensors dependent on a PMIC from the PMIC's
acpi_driver.

Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	- Patch introduced

 drivers/acpi/utils.c    | 68 +++++++++++++++++++++++++++++++++++++++++
 include/acpi/acpi_bus.h |  2 ++
 2 files changed, 70 insertions(+)

diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index c177165c8db2..7099529121db 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -807,6 +807,52 @@ static int acpi_dev_match_cb(struct device *dev, const void *data)
 	return hrv == match->hrv;
 }
 
+static int acpi_dev_match_by_dep(struct device *dev, const void *data)
+{
+	struct acpi_device *adev = to_acpi_device(dev);
+	const struct acpi_device *dependee = data;
+	struct acpi_handle_list dep_handles;
+	struct acpi_device *candidate;
+	acpi_handle handle;
+	acpi_status status;
+	unsigned int i;
+	int ret;
+
+	handle = adev->handle;
+
+	if (!acpi_has_method(handle, "_DEP"))
+		return 0;
+
+	status = acpi_evaluate_reference(handle, "_DEP", NULL, &dep_handles);
+	if (ACPI_FAILURE(status))
+		return 0;
+
+	for (i = 0; i < dep_handles.count; i++) {
+		struct acpi_device_info *info;
+
+		status = acpi_get_object_info(dep_handles.handles[i], &info);
+		if (ACPI_FAILURE(status))
+			continue;
+
+		if (info->valid & ACPI_VALID_HID) {
+			ret = acpi_bus_get_device(dep_handles.handles[i], &candidate);
+			if (ret || !candidate) {
+				kfree(info);
+				continue;
+			}
+
+			if (candidate == dependee) {
+				acpi_dev_put(candidate);
+				kfree(info);
+				return 1;
+			}
+
+			kfree(info);
+		}
+	}
+	return 0;
+}
+
 /**
  * acpi_dev_present - Detect that a given ACPI device is present
  * @hid: Hardware ID of the device.
@@ -842,6 +888,28 @@ bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
 }
 EXPORT_SYMBOL(acpi_dev_present);
 
+/**
+ * acpi_dev_get_next_dep_dev - Return next ACPI device dependent on input dev
+ * @adev: Pointer to the dependee device
+ * @prev: Pointer to the previous dependent device (or NULL for first match)
+ *
+ * Return the next ACPI device which declares itself dependent on @adev in
+ * the _DEP buffer.
+ *
+ * The caller is responsible to call put_device() on the returned device.
+ */
+struct acpi_device *acpi_dev_get_next_dep_dev(struct acpi_device *adev,
+					      struct acpi_device *prev)
+{
+	struct device *start = prev ? &prev->dev : NULL;
+	struct device *dev;
+
+	dev = bus_find_device(&acpi_bus_type, start, adev, acpi_dev_match_by_dep);
+
+	return dev ? to_acpi_device(dev) : NULL;
+}
+EXPORT_SYMBOL(acpi_dev_get_next_dep_dev);
+
 /**
  * acpi_dev_get_next_match_dev - Return the next match of ACPI device
  * @adev: Pointer to the previous acpi_device matching this hid, uid and hrv
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 0a028ba967d3..f5dfeb030b9c 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -688,6 +688,8 @@ static inline bool acpi_device_can_poweroff(struct acpi_device *adev)
 
 bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2);
 
+struct acpi_device *
+acpi_dev_get_next_dep_dev(struct acpi_device *adev, struct acpi_device *prev);
 struct acpi_device *
 acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv);
 struct acpi_device *
-- 
2.25.1


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

* [PATCH 15/18] i2c: i2c-core-acpi: Add i2c_acpi_dev_name()
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (13 preceding siblings ...)
  2020-11-30 13:31 ` [PATCH 14/18] acpi: utils: Add function to fetch dependent acpi_devices Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 17:11   ` Laurent Pinchart
  2020-11-30 13:31 ` [PATCH 16/18] i2c: i2c-core-base: Use the new i2c_acpi_dev_name() in i2c_set_dev_name() Daniel Scally
                   ` (2 subsequent siblings)
  17 siblings, 1 reply; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Some places in the kernel allow users to map resources to a device
using device name (for example, gpiod_lookup_table). Currently
this involves waiting for the i2c_client to have been registered so we
can use dev_name(&client->dev). Adding this function means that we can
achieve the same thing without having to wait to the i2c device.

Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	- Patch introduced

 drivers/i2c/i2c-core-acpi.c | 14 ++++++++++++++
 include/linux/i2c.h         |  5 +++++
 2 files changed, 19 insertions(+)

diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index 37c510d9347a..d3a653eac79e 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -497,6 +497,20 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
 }
 EXPORT_SYMBOL_GPL(i2c_acpi_new_device);
 
+/**
+ * i2c_acpi_dev_name - Construct i2c device name for devs sourced from ACPI
+ * @adev:     ACPI device to construct the name for
+ *
+ * Prefixes "i2c-" to the ACPI device name, for use in i2c_dev_set_name() and
+ * also anywhere else in the kernel that needs to refer to an i2c device by
+ * name but before they have been instantiated.
+ */
+char *i2c_acpi_dev_name(struct acpi_device *adev)
+{
+	return kasprintf(GFP_KERNEL, "i2c-%s", acpi_dev_name(adev));
+}
+EXPORT_SYMBOL_GPL(i2c_acpi_dev_name);
+
 #ifdef CONFIG_ACPI_I2C_OPREGION
 static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
 		u8 cmd, u8 *data, u8 data_len)
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 56622658b215..ab0e505b2ca6 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -995,6 +995,7 @@ bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
 u32 i2c_acpi_find_bus_speed(struct device *dev);
 struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
 				       struct i2c_board_info *info);
+char *i2c_acpi_dev_name(struct acpi_device *adev);
 struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle);
 #else
 static inline bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
@@ -1011,6 +1012,10 @@ static inline struct i2c_client *i2c_acpi_new_device(struct device *dev,
 {
 	return ERR_PTR(-ENODEV);
 }
+static inline char *i2c_acpi_dev_name(struct acpi_device *adev)
+{
+	return NULL;
+}
 static inline struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle)
 {
 	return NULL;
-- 
2.25.1


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

* [PATCH 16/18] i2c: i2c-core-base: Use the new i2c_acpi_dev_name() in i2c_set_dev_name()
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (14 preceding siblings ...)
  2020-11-30 13:31 ` [PATCH 15/18] i2c: i2c-core-acpi: Add i2c_acpi_dev_name() Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 17:12   ` Laurent Pinchart
  2020-11-30 13:31 ` [PATCH 17/18] gpio: gpiolib-acpi: Export acpi_get_gpiod() Daniel Scally
  2020-11-30 13:31 ` [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device Daniel Scally
  17 siblings, 1 reply; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Dan Scally

From: Dan Scally <djrscally@gmail.com>

To make sure the new i2c_acpi_dev_name() always reflects the name of i2c
devices sourced from ACPI, use it in i2c_set_dev_name().

Signed-off-by: Dan Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	- Patch introduced

 drivers/i2c/i2c-core-base.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index 573b5da145d1..a6d4ceb01077 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -814,7 +814,7 @@ static void i2c_dev_set_name(struct i2c_adapter *adap,
 	}
 
 	if (adev) {
-		dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev));
+		dev_set_name(&client->dev, i2c_acpi_dev_name(adev));
 		return;
 	}
 
-- 
2.25.1


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

* [PATCH 17/18] gpio: gpiolib-acpi: Export acpi_get_gpiod()
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (15 preceding siblings ...)
  2020-11-30 13:31 ` [PATCH 16/18] i2c: i2c-core-base: Use the new i2c_acpi_dev_name() in i2c_set_dev_name() Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 17:02   ` kernel test robot
                     ` (2 more replies)
  2020-11-30 13:31 ` [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device Daniel Scally
  17 siblings, 3 replies; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

I need to be able to translate GPIO resources in an acpi_device's _CRS
into gpio_descs. Those are represented in _CRS as a pathname to a GPIO
device plus the pin's index number: this function is perfect for that
purpose.

Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	- Patch introduced

 drivers/gpio/gpiolib-acpi.c | 3 ++-
 include/linux/acpi.h        | 5 +++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 834a12f3219e..cfadbc263475 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -111,7 +111,7 @@ static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
  * controller does not have GPIO chip registered at the moment. This is to
  * support probe deferral.
  */
-static struct gpio_desc *acpi_get_gpiod(char *path, int pin)
+struct gpio_desc *acpi_get_gpiod(char *path, int pin)
 {
 	struct gpio_chip *chip;
 	acpi_handle handle;
@@ -127,6 +127,7 @@ static struct gpio_desc *acpi_get_gpiod(char *path, int pin)
 
 	return gpiochip_get_desc(chip, pin);
 }
+EXPORT_SYMBOL_GPL(acpi_get_gpiod);
 
 static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
 {
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 39263c6b52e1..737115a93138 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -1066,6 +1066,7 @@ void __acpi_handle_debug(struct _ddebug *descriptor, acpi_handle handle, const c
 bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
 				struct acpi_resource_gpio **agpio);
 int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index);
+struct gpio_desc *acpi_get_gpiod(char *path, int pin);
 #else
 static inline bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
 					      struct acpi_resource_gpio **agpio)
@@ -1076,6 +1077,10 @@ static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
 {
 	return -ENXIO;
 }
+struct gpio_desc *acpi_get_gpiod(char *path, int pin)
+{
+	return NULL;
+}
 #endif
 
 /* Device properties */
-- 
2.25.1


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

* [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                   ` (16 preceding siblings ...)
  2020-11-30 13:31 ` [PATCH 17/18] gpio: gpiolib-acpi: Export acpi_get_gpiod() Daniel Scally
@ 2020-11-30 13:31 ` Daniel Scally
  2020-11-30 16:17   ` Jean-Michel Hautbois
                     ` (3 more replies)
  17 siblings, 4 replies; 144+ messages in thread
From: Daniel Scally @ 2020-11-30 13:31 UTC (permalink / raw)
  To: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

On platforms where ACPI is designed for use with Windows, resources
that are intended to be consumed by sensor devices are sometimes in
the _CRS of a dummy INT3472 device upon which the sensor depends. This
driver binds to the dummy acpi device (which does not represent a
physical PMIC) and maps them into GPIO lines and regulators for use by
the sensor device instead.

Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Daniel Scally <djrscally@gmail.com>
---
Changes since RFC v3:

	- Patch introduced

This patch contains the bits of this process that we're least sure about.
The sensors in scope for this work are called out as dependent (in their
DSDT entry's _DEP) on a device with _HID INT3472. These come in at least
2 kinds; those with an I2cSerialBusV2 entry (which we presume therefore
are legitimate tps68470 PMICs that need handling by those drivers - work
on that in the future). And those without an I2C device. For those without
an I2C device they instead have an array of GPIO pins defined in _CRS. So
for example, my Lenovo Miix 510's OVTI2680 sensor is dependent on one of
the _latter_ kind of INT3472 devices, with this _CRS:

Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
{
    Name (SBUF, ResourceTemplate ()
    {
        GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
	    0x00, ResourceConsumer, ,
            )
            {   // Pin list
                0x0079
            }
        GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
	    0x00, ResourceConsumer, ,
            )
            {   // Pin list
                0x007A
            }
        GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
	    0x00, ResourceConsumer, ,
            )
            {   // Pin list
                0x008F
            }
    })
    Return (SBUF) /* \_SB_.PCI0.PMI1._CRS.SBUF */
}

and the same device has a _DSM Method, which returns 32-bit ints where
the second lowest byte we noticed to match the pin numbers of the GPIO
lines:

Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
{
    If ((Arg0 == ToUUID ("79234640-9e10-4fea-a5c1-b5aa8b19756f")))
    {
        If ((Arg2 == One))
        {
            Return (0x03)
        }

        If ((Arg2 == 0x02))
        {
            Return (0x01007900)
        }

        If ((Arg2 == 0x03))
        {
            Return (0x01007A0C)
        }

        If ((Arg2 == 0x04))
        {
            Return (0x01008F01)
        }
    }

    Return (Zero)
}

We know that at least some of those pins have to be toggled active for the
sensor devices to be available in i2c, so the conclusion we came to was
that those GPIO entries assigned to the INT3472 device actually represent
GPIOs and regulators to be consumed by the sensors themselves. Tsuchiya
noticed that the lowest byte in the return values of the _DSM method
seemed to represent the type or function of the GPIO line, and we
confirmed that by testing on each surface device that GPIO lines where the
low byte in the _DSM entry for that pin was 0x0d controlled the privacy
LED of the cameras.

We're guessing as to the exact meaning of the function byte, but I
conclude they're something like this:

0x00 - probably a reset GPIO
0x01 - regulator for the sensor
0x0c - regulator for the sensor
0x0b - regulator again, but for a VCM or EEPROM
0x0d - privacy led (only one we're totally confident of since we can see
       it happen!)

After much internal debate I decided to write this as a standalone
acpi_driver. Alternative options we considered:

1. Squash all this into the cio2-bridge code, which I did originally write
but decided I didn't like.
2. Extend the existing tps68470 mfd driver...they share an ACPI ID so this
kinda makes sense, but ultimately given there is no actual physical
tps68470 in the scenario this patch handles I decided I didn't like this
either.

 MAINTAINERS                            |   7 +
 drivers/media/pci/intel/ipu3/Kconfig   |  14 +
 drivers/media/pci/intel/ipu3/Makefile  |   1 +
 drivers/media/pci/intel/ipu3/int3472.c | 381 +++++++++++++++++++++++++
 drivers/media/pci/intel/ipu3/int3472.h |  96 +++++++
 5 files changed, 499 insertions(+)
 create mode 100644 drivers/media/pci/intel/ipu3/int3472.c
 create mode 100644 drivers/media/pci/intel/ipu3/int3472.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 188559a0a610..d73471f9c2a3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8753,6 +8753,13 @@ L:	linux-crypto@vger.kernel.org
 S:	Maintained
 F:	drivers/crypto/inside-secure/
 
+INT3472 ACPI DEVICE DRIVER
+M:	Daniel Scally <djrscally@gmail.com>
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	drivers/media/pci/intel/ipu3/int3472.c
+F:	drivers/media/pci/intel/ipu3/int3472.h
+
 INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
 M:	Mimi Zohar <zohar@linux.ibm.com>
 M:	Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
index 2b3350d042be..9dd3b280f821 100644
--- a/drivers/media/pci/intel/ipu3/Kconfig
+++ b/drivers/media/pci/intel/ipu3/Kconfig
@@ -34,3 +34,17 @@ config CIO2_BRIDGE
 		- Dell 7285
 
 	  If in doubt, say N here.
+
+config INT3472
+	tristate "INT3472 Dummy ACPI Device Driver"
+	depends on VIDEO_IPU3_CIO2
+	depends on ACPI && REGULATOR && GPIOLIB
+	help
+	  This module provides an ACPI driver for INT3472 devices that do not
+	  represent an actual physical tps68470 device.
+
+	  Say Y here if your device is a detachable / hybrid laptop that comes
+	  with Windows installed by the OEM.
+	  The module will be called int3472.
+
+	  If in doubt, say N here.
diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
index 933777e6ea8a..2285947b2bd2 100644
--- a/drivers/media/pci/intel/ipu3/Makefile
+++ b/drivers/media/pci/intel/ipu3/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
+obj-$(CONFIG_INT3472) += int3472.o
 
 ipu3-cio2-y += ipu3-cio2-main.o
 ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
diff --git a/drivers/media/pci/intel/ipu3/int3472.c b/drivers/media/pci/intel/ipu3/int3472.c
new file mode 100644
index 000000000000..6b0be75f7f35
--- /dev/null
+++ b/drivers/media/pci/intel/ipu3/int3472.c
@@ -0,0 +1,381 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Author: Dan Scally <djrscally@gmail.com> */
+#include <linux/acpi.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/regulator/driver.h>
+
+#include "int3472.h"
+
+/*
+ * The regulators have to have .ops to be valid, but the only ops we actually
+ * support are .enable and .disable which are handled via .ena_gpiod. Pass an
+ * empty struct to clear the check without lying about capabilities.
+ */
+static const struct regulator_ops int3472_gpio_regulator_ops = { 0 };
+
+static int int3472_map_gpio_to_sensor(struct int3472_device *int3472,
+				      struct acpi_resource *ares, char *func)
+{
+	char *path = ares->data.gpio.resource_source.string_ptr;
+	struct gpiod_lookup table_entry;
+	struct acpi_device *adev;
+	acpi_handle handle;
+	acpi_status status;
+	int ret;
+
+	/* Make sure we don't overflow, and leave room for a terminator */
+	if (int3472->n_sensor_gpios >= INT3472_MAX_SENSOR_GPIOS) {
+		dev_warn(&int3472->sensor->dev, "Too many GPIOs mapped\n");
+		return -EINVAL;
+	}
+
+	/* Fetch ACPI handle for the GPIO chip  */
+	status = acpi_get_handle(NULL, path, &handle);
+	if (ACPI_FAILURE(status))
+		return -EINVAL;
+
+	ret = acpi_bus_get_device(handle, &adev);
+	if (ret)
+		return -ENODEV;
+
+	table_entry = (struct gpiod_lookup)GPIO_LOOKUP_IDX(acpi_dev_name(adev),
+							   ares->data.gpio.pin_table[0],
+							   func, 0, GPIO_ACTIVE_HIGH);
+
+	memcpy(&int3472->gpios.table[int3472->n_sensor_gpios], &table_entry,
+	       sizeof(table_entry));
+	int3472->n_sensor_gpios++;
+
+	return 0;
+}
+
+static struct int3472_sensor_regulator_map *
+int3472_get_sensor_supply_map(struct int3472_device *int3472)
+{
+	struct int3472_sensor_regulator_map *ret;
+	union acpi_object *obj;
+	unsigned int i;
+
+	/*
+	 * Sensor modules seem to be identified by a unique string. We use that
+	 * to make sure we pass the right device and supply names to the new
+	 * regulator's consumer_supplies
+	 */
+	obj = acpi_evaluate_dsm_typed(int3472->sensor->handle,
+				      &cio2_sensor_module_guid, 0x00,
+				      0x01, NULL, ACPI_TYPE_STRING);
+
+	if (!obj) {
+		dev_err(&int3472->sensor->dev,
+			"Failed to get sensor module string from _DSM\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	if (obj->string.type != ACPI_TYPE_STRING) {
+		dev_err(&int3472->sensor->dev,
+			"Sensor _DSM returned a non-string value\n");
+		ret = ERR_PTR(-EINVAL);
+		goto out_free_obj;
+	}
+
+	ret = ERR_PTR(-ENODEV);
+	for (i = 0; i < ARRAY_SIZE(int3472_sensor_regulator_maps); i++) {
+		if (!strcmp(int3472_sensor_regulator_maps[i].sensor_module_name,
+			    obj->string.pointer)) {
+			ret = &int3472_sensor_regulator_maps[i];
+			goto out_free_obj;
+		}
+	}
+
+out_free_obj:
+	ACPI_FREE(obj);
+	return ret;
+}
+
+static int int3472_register_regulator(struct int3472_device *int3472,
+				      struct acpi_resource *ares)
+{
+	char *path = ares->data.gpio.resource_source.string_ptr;
+	struct int3472_sensor_regulator_map *regulator_map;
+	struct regulator_init_data init_data = { };
+	struct int3472_gpio_regulator *regulator;
+	struct regulator_config cfg = { };
+	int ret;
+
+	/*
+	 * We lookup supply names from machine specific tables, based on a
+	 * unique identifier in the sensor's _DSM
+	 */
+	regulator_map = int3472_get_sensor_supply_map(int3472);
+	if (IS_ERR_OR_NULL(regulator_map)) {
+		dev_err(&int3472->sensor->dev,
+			"Found no supplies defined for this sensor\n");
+		return PTR_ERR(regulator_map);
+	}
+
+	if (int3472->n_regulators >= regulator_map->n_supplies) {
+		dev_err(&int3472->sensor->dev,
+			"All known supplies are already mapped\n");
+		return -EINVAL;
+	}
+
+	init_data.supply_regulator = NULL;
+	init_data.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
+	init_data.num_consumer_supplies = 1;
+	init_data.consumer_supplies = &regulator_map->supplies[int3472->n_regulators];
+
+	regulator = kmalloc(sizeof(*regulator), GFP_KERNEL);
+	if (!regulator)
+		return -ENOMEM;
+
+	snprintf(regulator->regulator_name, GPIO_REGULATOR_NAME_LENGTH,
+		 "gpio-regulator-%d", int3472->n_regulators);
+	snprintf(regulator->supply_name, GPIO_REGULATOR_SUPPLY_NAME_LENGTH,
+		 "supply-%d", int3472->n_regulators);
+
+	regulator->rdesc = INT3472_REGULATOR(regulator->regulator_name,
+					     regulator->supply_name,
+					     int3472->n_regulators,
+					     &int3472_gpio_regulator_ops);
+
+	regulator->gpio = acpi_get_gpiod(path, ares->data.gpio.pin_table[0]);
+	if (IS_ERR(regulator->gpio)) {
+		ret = PTR_ERR(regulator->gpio);
+		goto err_free_regulator;
+	}
+
+	cfg.dev = &int3472->adev->dev;
+	cfg.init_data = &init_data;
+	cfg.ena_gpiod = regulator->gpio;
+
+	regulator->rdev = regulator_register(&regulator->rdesc, &cfg);
+	if (IS_ERR(regulator->rdev)) {
+		ret = PTR_ERR(regulator->rdev);
+		goto err_free_gpio;
+	}
+
+	list_add(&regulator->list, &int3472->regulators);
+	int3472->n_regulators++;
+
+	return 0;
+
+err_free_gpio:
+	gpiod_put(regulator->gpio);
+err_free_regulator:
+	kfree(regulator);
+
+	return ret;
+}
+
+static int int3472_handle_gpio_resources(struct acpi_resource *ares,
+					 void *data)
+{
+	struct int3472_device *int3472 = data;
+	union acpi_object *obj;
+	int ret = 0;
+
+	if (ares->type != ACPI_RESOURCE_TYPE_GPIO ||
+	    ares->data.gpio.connection_type != ACPI_RESOURCE_GPIO_TYPE_IO)
+		return EINVAL; /* Deliberately positive */
+
+	/*
+	 * n_gpios + 2 because the index of this _DSM function is 1-based and
+	 * the first function is just a count.
+	 */
+	obj = acpi_evaluate_dsm_typed(int3472->adev->handle,
+				      &int3472_gpio_guid, 0x00,
+				      int3472->n_gpios + 2,
+				      NULL, ACPI_TYPE_INTEGER);
+
+	if (!obj) {
+		dev_warn(&int3472->adev->dev,
+			 "No _DSM entry for this GPIO pin\n");
+		return ENODEV;
+	}
+
+	switch (obj->integer.value & 0xff) { /* low byte holds type data */
+	case 0x00: /* Purpose unclear, possibly a reset GPIO pin */
+		ret = int3472_map_gpio_to_sensor(int3472, ares, "reset");
+		if (ret)
+			dev_warn(&int3472->adev->dev,
+				 "Failed to map reset pin to sensor\n");
+
+		break;
+	case 0x01: /* Power regulators (we think) */
+	case 0x0c:
+		ret = int3472_register_regulator(int3472, ares);
+		if (ret)
+			dev_warn(&int3472->adev->dev,
+				 "Failed to map regulator to sensor\n");
+
+		break;
+	case 0x0b: /* Power regulators, but to a device separate to sensor */
+		ret = int3472_register_regulator(int3472, ares);
+		if (ret)
+			dev_warn(&int3472->adev->dev,
+				 "Failed to map regulator to sensor\n");
+
+		break;
+	case 0x0d: /* Indicator LEDs */
+		ret = int3472_map_gpio_to_sensor(int3472, ares, "indicator-led");
+		if (ret)
+			dev_warn(&int3472->adev->dev,
+				 "Failed to map indicator led to sensor\n");
+
+		break;
+	default:
+		/* if we've gotten here, we're not sure what they are yet */
+		dev_warn(&int3472->adev->dev,
+			 "GPIO type 0x%llx unknown; the sensor may not work\n",
+			 (obj->integer.value & 0xff));
+		ret = EINVAL;
+	}
+
+	int3472->n_gpios++;
+	ACPI_FREE(obj);
+	return abs(ret);
+}
+
+static void int3472_parse_crs(struct int3472_device *int3472)
+{
+	struct list_head resource_list;
+
+	INIT_LIST_HEAD(&resource_list);
+
+	acpi_dev_get_resources(int3472->adev, &resource_list,
+			       int3472_handle_gpio_resources, int3472);
+
+	acpi_dev_free_resource_list(&resource_list);
+	gpiod_add_lookup_table(&int3472->gpios);
+}
+
+static int int3472_add(struct acpi_device *adev)
+{
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	struct int3472_device *int3472;
+	struct int3472_cldb cldb;
+	union acpi_object *obj;
+	acpi_status status;
+	int ret = 0;
+
+	/*
+	 * This driver is only intended to support "dummy" INT3472 devices
+	 * which appear in ACPI designed for Windows. These are distinguishable
+	 * from INT3472 entries representing an actual tps68470 PMIC through
+	 * the presence of a CLDB buffer with a particular value set.
+	 */
+	status = acpi_evaluate_object(adev->handle, "CLDB", NULL, &buffer);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	obj = buffer.pointer;
+	if (!obj) {
+		dev_err(&adev->dev, "ACPI device has no CLDB object\n");
+		return -ENODEV;
+	}
+
+	if (obj->type != ACPI_TYPE_BUFFER) {
+		dev_err(&adev->dev, "CLDB object is not an ACPI buffer\n");
+		ret = -EINVAL;
+		goto out_free_buff;
+	}
+
+	if (obj->buffer.length > sizeof(cldb)) {
+		dev_err(&adev->dev, "The CLDB buffer is too large\n");
+		ret = -EINVAL;
+		goto out_free_buff;
+	}
+
+	memcpy(&cldb, obj->buffer.pointer, obj->buffer.length);
+
+	/*
+	 * control_logic_type = 1 indicates this is a dummy INT3472 device of
+	 * the kind we're looking for. If any other value then we shouldn't try
+	 * to handle it
+	 */
+	if (cldb.control_logic_type != 1) {
+		ret = -EINVAL;
+		goto out_free_buff;
+	}
+
+	/* Space for 4 GPIOs - one more than we've seen so far plus a null */
+	int3472 = kzalloc(sizeof(*int3472) +
+			 ((INT3472_MAX_SENSOR_GPIOS + 1) * sizeof(struct gpiod_lookup)),
+			 GFP_KERNEL);
+	if (!int3472) {
+		ret = -ENOMEM;
+		goto out_free_buff;
+	}
+
+	int3472->adev = adev;
+	adev->driver_data = int3472;
+
+	int3472->sensor = acpi_dev_get_next_dep_dev(adev, NULL);
+	if (!int3472->sensor) {
+		dev_err(&adev->dev,
+			"This INT3472 entry seems to have no dependents.\n");
+		ret = -ENODEV;
+		goto out_free_int3472;
+	}
+
+	int3472->gpios.dev_id = i2c_acpi_dev_name(int3472->sensor);
+
+	INIT_LIST_HEAD(&int3472->regulators);
+
+	int3472_parse_crs(int3472);
+
+	goto out_free_buff;
+
+out_free_int3472:
+	kfree(int3472);
+out_free_buff:
+	kfree(buffer.pointer);
+	return ret;
+}
+
+static int int3472_remove(struct acpi_device *adev)
+{
+	struct int3472_gpio_regulator *reg;
+	struct int3472_device *int3472;
+
+	int3472 = acpi_driver_data(adev);
+
+	acpi_dev_put(int3472->sensor);
+	gpiod_remove_lookup_table(&int3472->gpios);
+
+	list_for_each_entry(reg, &int3472->regulators, list) {
+		gpiod_put(reg->gpio);
+		regulator_unregister(reg->rdev);
+	}
+
+	kfree(int3472);
+
+	return 0;
+}
+
+static const struct acpi_device_id int3472_device_id[] = {
+	{ "INT3472", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, int3472_device_id);
+
+static struct acpi_driver int3472_driver = {
+	.name = "int3472",
+	.ids = int3472_device_id,
+	.ops = {
+		.add = int3472_add,
+		.remove = int3472_remove,
+	},
+	.owner = THIS_MODULE,
+};
+
+module_acpi_driver(int3472_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Dan Scally <djrscally@gmail.com>");
+MODULE_DESCRIPTION("ACPI Driver for Discrete type INT3472 ACPI Devices");
diff --git a/drivers/media/pci/intel/ipu3/int3472.h b/drivers/media/pci/intel/ipu3/int3472.h
new file mode 100644
index 000000000000..6964726e8e1f
--- /dev/null
+++ b/drivers/media/pci/intel/ipu3/int3472.h
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Author: Dan Scally <djrscally@gmail.com> */
+#include <linux/regulator/machine.h>
+
+#define INT3472_MAX_SENSOR_GPIOS			3
+#define GPIO_REGULATOR_NAME_LENGTH			17
+#define GPIO_REGULATOR_SUPPLY_NAME_LENGTH		9
+
+#define INT3472_REGULATOR(_NAME, _SUPPLY, _ID, _OPS)	\
+	((const struct regulator_desc) {		\
+		.name = _NAME,				\
+		.supply_name = _SUPPLY,			\
+		.id = _ID,				\
+		.type = REGULATOR_VOLTAGE,		\
+		.ops = _OPS,				\
+		.owner = THIS_MODULE,			\
+	})
+
+const guid_t int3472_gpio_guid = GUID_INIT(0x79234640, 0x9e10, 0x4fea,
+					     0xa5, 0xc1, 0xb5, 0xaa, 0x8b,
+					     0x19, 0x75, 0x6f);
+
+const guid_t cio2_sensor_module_guid = GUID_INIT(0x822ace8f, 0x2814, 0x4174,
+						 0xa5, 0x6b, 0x5f, 0x02, 0x9f,
+						 0xe0, 0x79, 0xee);
+
+struct int3472_cldb {
+	u8 version;
+	/*
+	 * control logic type
+	 * 0: UNKNOWN
+	 * 1: DISCRETE(CRD-D)
+	 * 2: PMIC TPS68470
+	 * 3: PMIC uP6641
+	 */
+	u8 control_logic_type;
+	u8 control_logic_id;
+	u8 sensor_card_sku;
+	u8 reserved[28];
+};
+
+struct int3472_device {
+	struct acpi_device *adev;
+	struct acpi_device *sensor;
+
+	unsigned int n_gpios; /* how many GPIOs have we seen */
+
+	unsigned int n_regulators;
+	struct list_head regulators;
+
+	unsigned int n_sensor_gpios; /* how many have we mapped to sensor */
+	struct gpiod_lookup_table gpios;
+};
+
+struct int3472_gpio_regulator {
+	char regulator_name[GPIO_REGULATOR_NAME_LENGTH];
+	char supply_name[GPIO_REGULATOR_SUPPLY_NAME_LENGTH];
+	struct gpio_desc *gpio;
+	struct regulator_dev *rdev;
+	struct regulator_desc rdesc;
+	struct list_head list;
+};
+
+struct int3472_sensor_regulator_map {
+	char *sensor_module_name;
+	unsigned int n_supplies;
+	struct regulator_consumer_supply *supplies;
+};
+
+/*
+ * Here follows platform specific mapping information that we can pass to
+ * regulator_init_data when we register our regulators. They're just mapped
+ * via index, I.E. the first regulator pin that the code finds for the
+ * i2c-OVTI2680:00 device is avdd, the second is dovdd and so on.
+ */
+
+static struct regulator_consumer_supply miix_510_ov2680[] = {
+	{ "i2c-OVTI2680:00", "avdd" },
+	{ "i2c-OVTI2680:00", "dovdd" },
+};
+
+static struct regulator_consumer_supply surface_go2_ov5693[] = {
+	{ "i2c-INT33BE:00", "avdd" },
+	{ "i2c-INT33BE:00", "dovdd" },
+};
+
+static struct regulator_consumer_supply surface_book_ov5693[] = {
+	{ "i2c-INT33BE:00", "avdd" },
+	{ "i2c-INT33BE:00", "dovdd" },
+};
+
+static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
+	{ "GNDF140809R", 2, miix_510_ov2680 },
+	{ "YHCU", 2, surface_go2_ov5693 },
+	{ "MSHW0070", 2, surface_book_ov5693 },
+};
-- 
2.25.1


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

* Re: [PATCH 08/18] lib/test_printf.c: Use helper function to unwind array of software_nodes
  2020-11-30 13:31 ` [PATCH 08/18] lib/test_printf.c: Use helper function to unwind array of software_nodes Daniel Scally
@ 2020-11-30 15:54   ` Sergey Senozhatsky
  2020-11-30 16:26   ` Laurent Pinchart
  1 sibling, 0 replies; 144+ messages in thread
From: Sergey Senozhatsky @ 2020-11-30 15:54 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On (20/11/30 13:31), Daniel Scally wrote:
> 
> Use the software_node_unregister_nodes() helper function to unwind this
> array in a cleaner way.
> 
> Acked-by: Petr Mladek <pmladek@suse.com>
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>

Reviewed-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>

	-ss

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

* Re: [PATCH 01/18] property: Return true in fwnode_device_is_available for node types that do not implement this operation
  2020-11-30 13:31 ` [PATCH 01/18] property: Return true in fwnode_device_is_available for node types that do not implement this operation Daniel Scally
@ 2020-11-30 16:05   ` Laurent Pinchart
  2020-11-30 17:21   ` Andy Shevchenko
  2020-12-01  3:12   ` Bingbu Cao
  2 siblings, 0 replies; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 16:05 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Daniel,

Thank you for the patch.

On Mon, Nov 30, 2020 at 01:31:12PM +0000, Daniel Scally wrote:
> Some types of fwnode_handle do not implement the device_is_available()
> check, such as those created by software_nodes. There isn't really a
> meaningful way to check for the availability of a device that doesn't
> actually exist, so if the check isn't implemented just assume that the
> "device" is present.
> 
> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
> Changes since RFC v3:
> 
> 	patch introduced
> 
>  drivers/base/property.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/base/property.c b/drivers/base/property.c
> index 4c43d30145c6..a5ca2306796f 100644
> --- a/drivers/base/property.c
> +++ b/drivers/base/property.c
> @@ -785,9 +785,14 @@ EXPORT_SYMBOL_GPL(fwnode_handle_put);
>  /**
>   * fwnode_device_is_available - check if a device is available for use
>   * @fwnode: Pointer to the fwnode of the device.
> + *
> + * For fwnode node types that don't implement the .device_is_available()
> + * operation, this function returns true.
>   */
>  bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
>  {
> +	if (!fwnode_has_op(fwnode, device_is_available))
> +		return true;
>  	return fwnode_call_bool_op(fwnode, device_is_available);
>  }
>  EXPORT_SYMBOL_GPL(fwnode_device_is_available);

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 02/18] property: Add support for calling fwnode_graph_get_endpoint_by_id() for fwnode->secondary
  2020-11-30 13:31 ` [PATCH 02/18] property: Add support for calling fwnode_graph_get_endpoint_by_id() for fwnode->secondary Daniel Scally
@ 2020-11-30 16:08   ` Laurent Pinchart
  2020-11-30 17:29   ` Andy Shevchenko
  1 sibling, 0 replies; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 16:08 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Daniel,

Thank you for the patch.

On Mon, Nov 30, 2020 at 01:31:13PM +0000, Daniel Scally wrote:
> This function is used to find fwnode endpoints against a device. In
> some instances those endpoints are software nodes which are children of
> fwnode->secondary. Add support to fwnode_graph_get_endpoint_by_id() to
> find those endpoints by recursively calling itself passing the ptr to
> fwnode->secondary in the event no endpoint is found for the primary.
> 
> Signed-off-by: Daniel Scally <djrscally@gmail.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
> Changes since RFC v3:
> 
> 	Patch introduced. In discussion in the last submission I noted
> 	that the CIO2 device doesn't have an ACPI fwnode - that turns
> 	out to be true for _some_ devices but not others, so we need
> 	this function to check the secondary too.
> 
>  drivers/base/property.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/base/property.c b/drivers/base/property.c
> index a5ca2306796f..4ece6b086e36 100644
> --- a/drivers/base/property.c
> +++ b/drivers/base/property.c
> @@ -1162,6 +1162,10 @@ fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,
>  		best_ep_id = fwnode_ep.id;
>  	}
>  
> +	if (!best_ep && fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
> +		return fwnode_graph_get_endpoint_by_id(fwnode->secondary, port,
> +						       endpoint, flags);
> +
>  	return best_ep;
>  }
>  EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_by_id);

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 03/18] software_node: Fix failure to put() and get() references to children in software_node_get_next_child()
  2020-11-30 13:31 ` [PATCH 03/18] software_node: Fix failure to put() and get() references to children in software_node_get_next_child() Daniel Scally
@ 2020-11-30 16:10   ` Laurent Pinchart
  2020-11-30 17:30   ` Andy Shevchenko
  1 sibling, 0 replies; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 16:10 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Daniel,

Thank you for the patch.

On Mon, Nov 30, 2020 at 01:31:14PM +0000, Daniel Scally wrote:
> The software_node_get_next_child() function currently does not hold
> references to the child software_node that it finds or put the ref that
> is held against the old child - fix that.
> 
> Signed-off-by: Daniel Scally <djrscally@gmail.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
> Changes since RFC v3:
> 
> 	Put reference to previous child.
> 
>  drivers/base/swnode.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> index 010828fc785b..615a0c93e116 100644
> --- a/drivers/base/swnode.c
> +++ b/drivers/base/swnode.c
> @@ -443,14 +443,18 @@ software_node_get_next_child(const struct fwnode_handle *fwnode,
>  	struct swnode *c = to_swnode(child);
>  
>  	if (!p || list_empty(&p->children) ||
> -	    (c && list_is_last(&c->entry, &p->children)))
> +	    (c && list_is_last(&c->entry, &p->children))) {
> +		fwnode_handle_put(child);
>  		return NULL;
> +	}
>  
>  	if (c)
>  		c = list_next_entry(c, entry);
>  	else
>  		c = list_first_entry(&p->children, struct swnode, entry);
> -	return &c->fwnode;
> +
> +	fwnode_handle_put(child);
> +	return fwnode_handle_get(&c->fwnode);
>  }
>  
>  static struct fwnode_handle *

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 04/18] software_node: Enforce parent before child ordering of nodes array for software_node_register_nodes()
  2020-11-30 13:31 ` [PATCH 04/18] software_node: Enforce parent before child ordering of nodes array for software_node_register_nodes() Daniel Scally
@ 2020-11-30 16:11   ` Laurent Pinchart
  2020-11-30 16:12     ` Laurent Pinchart
  2020-11-30 17:35   ` Andy Shevchenko
  1 sibling, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 16:11 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Daniel,

Thank you for the patch.

On Mon, Nov 30, 2020 at 01:31:15PM +0000, Daniel Scally wrote:
> Registering software_nodes with the .parent member set to point to a
> currently unregistered software_node has the potential for problems,
> so enforce parent -> child ordering in arrays passed to this function.
> 
> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes since RFC v3:
> 
> 	Patch introduced
> 
>  drivers/base/swnode.c | 15 +++++++++++----
>  1 file changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> index 615a0c93e116..af7930b3679e 100644
> --- a/drivers/base/swnode.c
> +++ b/drivers/base/swnode.c
> @@ -700,14 +700,21 @@ int software_node_register_nodes(const struct software_node *nodes)
>  	int i;
>  
>  	for (i = 0; nodes[i].name; i++) {
> +		if (nodes[i].parent)
> +			if (!software_node_to_swnode(nodes[i].parent)) {
> +				ret = -EINVAL;
> +				goto err_unregister_nodes;
> +			}
> +
>  		ret = software_node_register(&nodes[i]);
> -		if (ret) {
> -			software_node_unregister_nodes(nodes);
> -			return ret;
> -		}
> +		if (ret)
> +			goto err_unregister_nodes;
>  	}
>  
>  	return 0;

I'd add a blank line here.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +err_unregister_nodes:
> +	software_node_unregister_nodes(nodes);
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(software_node_register_nodes);
>  

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 04/18] software_node: Enforce parent before child ordering of nodes array for software_node_register_nodes()
  2020-11-30 16:11   ` Laurent Pinchart
@ 2020-11-30 16:12     ` Laurent Pinchart
  2020-11-30 23:10       ` Dan Scally
  0 siblings, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 16:12 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Mon, Nov 30, 2020 at 06:11:52PM +0200, Laurent Pinchart wrote:
> Hi Daniel,
> 
> Thank you for the patch.
> 
> On Mon, Nov 30, 2020 at 01:31:15PM +0000, Daniel Scally wrote:
> > Registering software_nodes with the .parent member set to point to a
> > currently unregistered software_node has the potential for problems,
> > so enforce parent -> child ordering in arrays passed to this function.
> > 
> > Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > Signed-off-by: Daniel Scally <djrscally@gmail.com>
> > ---
> > Changes since RFC v3:
> > 
> > 	Patch introduced
> > 
> >  drivers/base/swnode.c | 15 +++++++++++----
> >  1 file changed, 11 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> > index 615a0c93e116..af7930b3679e 100644
> > --- a/drivers/base/swnode.c
> > +++ b/drivers/base/swnode.c
> > @@ -700,14 +700,21 @@ int software_node_register_nodes(const struct software_node *nodes)
> >  	int i;
> >  
> >  	for (i = 0; nodes[i].name; i++) {
> > +		if (nodes[i].parent)
> > +			if (!software_node_to_swnode(nodes[i].parent)) {
> > +				ret = -EINVAL;
> > +				goto err_unregister_nodes;
> > +			}
> > +
> >  		ret = software_node_register(&nodes[i]);
> > -		if (ret) {
> > -			software_node_unregister_nodes(nodes);
> > -			return ret;
> > -		}
> > +		if (ret)
> > +			goto err_unregister_nodes;
> >  	}
> >  
> >  	return 0;
> 
> I'd add a blank line here.
> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

I spoke a bit too soon. Could you update the documentation of the
function to explain this new requirement ?

> > +err_unregister_nodes:
> > +	software_node_unregister_nodes(nodes);
> > +	return ret;
> >  }
> >  EXPORT_SYMBOL_GPL(software_node_register_nodes);
> >  
> 
> -- 
> Regards,
> 
> Laurent Pinchart

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 05/18] software_node: Alter software_node_unregister_nodes() to unregister the array in reverse order
  2020-11-30 13:31 ` [PATCH 05/18] software_node: Alter software_node_unregister_nodes() to unregister the array in reverse order Daniel Scally
@ 2020-11-30 16:14   ` Laurent Pinchart
  2020-11-30 17:45   ` Andy Shevchenko
  1 sibling, 0 replies; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 16:14 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Daniel,

Thank you for the patch.

On Mon, Nov 30, 2020 at 01:31:16PM +0000, Daniel Scally wrote:
> Software nodes that are children of another software node should be
> unregistered before their parent. To allow easy unregistering of an array
> of software_nodes ordered parent to child, reverse the order in which
> this function unregisters software_nodes.
> 
> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
> Changes since RFC v3:
> 
> 	Switched this functionality from a new function to replacing
> 	the existing software_nodes_unregister_nodes()
> 
>  drivers/base/swnode.c | 19 ++++++++++++-------
>  1 file changed, 12 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> index af7930b3679e..d39e1c76d98d 100644
> --- a/drivers/base/swnode.c
> +++ b/drivers/base/swnode.c
> @@ -720,20 +720,25 @@ EXPORT_SYMBOL_GPL(software_node_register_nodes);
>  
>  /**
>   * software_node_unregister_nodes - Unregister an array of software nodes
> - * @nodes: Zero terminated array of software nodes to be unregistered
> + * @nodes: Zero terminated array of software nodes to be unregistered. If
> + * parent pointers are set up in any of the software nodes then the array
> + * MUST be ordered such that parents come before their children.
>   *
>   * Unregister multiple software nodes at once.
>   *
> - * NOTE: Be careful using this call if the nodes had parent pointers set up in
> - * them before registering.  If so, it is wiser to remove the nodes
> - * individually, in the correct order (child before parent) instead of relying
> - * on the sequential order of the list of nodes in the array.
> + * NOTE: If you are uncertain whether the array is ordered such that
> + * parents will be unregistered before their children, it is wiser to
> + * remove the nodes individually, in the correct order (child before
> + * parent).
>   */
>  void software_node_unregister_nodes(const struct software_node *nodes)
>  {
> -	int i;
> +	unsigned int i = 0;
> +
> +	while (nodes[i].name)
> +		i++;
>  
> -	for (i = 0; nodes[i].name; i++)
> +	while (i--)
>  		software_node_unregister(&nodes[i]);
>  }
>  EXPORT_SYMBOL_GPL(software_node_unregister_nodes);

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 06/18] software_node: amend software_node_unregister_node_group() to perform unregistration of array in reverse order to be consistent with software_node_unregister_nodes()
  2020-11-30 13:31 ` [PATCH 06/18] software_node: amend software_node_unregister_node_group() to perform unregistration of array in reverse order to be consistent with software_node_unregister_nodes() Daniel Scally
@ 2020-11-30 16:17   ` Laurent Pinchart
  2020-11-30 17:47     ` Andy Shevchenko
  2020-11-30 17:19   ` kernel test robot
  2020-12-01 18:18   ` Dan Carpenter
  2 siblings, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 16:17 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Daniel,

Thank you for the patch.

The subject line is very long. We try to keep it within a 72 characters
limit in the kernel. That can be a challenge sometimes, and expections
can be accepted, but this one is reaaaally long.

(The same comment holds for other patches in the series)

On Mon, Nov 30, 2020 at 01:31:17PM +0000, Daniel Scally wrote:
> To maintain consistency with software_node_unregister_nodes(), reverse
> the order in which the software_node_unregister_node_group() function
> unregisters nodes.
> 
> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>

I"d squash this with the previous patch to avoid introducing an
inconsistency.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
> Changes since v3:
> 
> 	Patch introduced
> 
>  drivers/base/swnode.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> index d39e1c76d98d..9bd0bb77ad5b 100644
> --- a/drivers/base/swnode.c
> +++ b/drivers/base/swnode.c
> @@ -782,7 +782,10 @@ void software_node_unregister_node_group(const struct software_node **node_group
>  	if (!node_group)
>  		return;
>  
> -	for (i = 0; node_group[i]; i++)
> +	while (node_group[i]->name)
> +		i++;
> +
> +	while (i--)
>  		software_node_unregister(node_group[i]);
>  }
>  EXPORT_SYMBOL_GPL(software_node_unregister_node_group);

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 13:31 ` [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device Daniel Scally
@ 2020-11-30 16:17   ` Jean-Michel Hautbois
  2020-11-30 23:20     ` Dan Scally
  2020-11-30 16:29   ` Kieran Bingham
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 144+ messages in thread
From: Jean-Michel Hautbois @ 2020-11-30 16:17 UTC (permalink / raw)
  To: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

Hi Daniel,

Thanks for the patch !

On 30/11/2020 14:31, Daniel Scally wrote:
> On platforms where ACPI is designed for use with Windows, resources
> that are intended to be consumed by sensor devices are sometimes in
> the _CRS of a dummy INT3472 device upon which the sensor depends. This
> driver binds to the dummy acpi device (which does not represent a
> physical PMIC) and maps them into GPIO lines and regulators for use by
> the sensor device instead.
> 
> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes since RFC v3:
> 
> 	- Patch introduced
> 
> This patch contains the bits of this process that we're least sure about.
> The sensors in scope for this work are called out as dependent (in their
> DSDT entry's _DEP) on a device with _HID INT3472. These come in at least
> 2 kinds; those with an I2cSerialBusV2 entry (which we presume therefore
> are legitimate tps68470 PMICs that need handling by those drivers - work
> on that in the future). And those without an I2C device. For those without
> an I2C device they instead have an array of GPIO pins defined in _CRS. So
> for example, my Lenovo Miix 510's OVTI2680 sensor is dependent on one of
> the _latter_ kind of INT3472 devices, with this _CRS:
> 
> Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
> {
>     Name (SBUF, ResourceTemplate ()
>     {
>         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> 	    0x00, ResourceConsumer, ,
>             )
>             {   // Pin list
>                 0x0079
>             }
>         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> 	    0x00, ResourceConsumer, ,
>             )
>             {   // Pin list
>                 0x007A
>             }
>         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> 	    0x00, ResourceConsumer, ,
>             )
>             {   // Pin list
>                 0x008F
>             }
>     })
>     Return (SBUF) /* \_SB_.PCI0.PMI1._CRS.SBUF */
> }
> 
> and the same device has a _DSM Method, which returns 32-bit ints where
> the second lowest byte we noticed to match the pin numbers of the GPIO
> lines:
> 
> Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
> {
>     If ((Arg0 == ToUUID ("79234640-9e10-4fea-a5c1-b5aa8b19756f")))
>     {
>         If ((Arg2 == One))
>         {
>             Return (0x03)
>         }
> 
>         If ((Arg2 == 0x02))
>         {
>             Return (0x01007900)
>         }
> 
>         If ((Arg2 == 0x03))
>         {
>             Return (0x01007A0C)
>         }
> 
>         If ((Arg2 == 0x04))
>         {
>             Return (0x01008F01)
>         }
>     }
> 
>     Return (Zero)
> }
> 
> We know that at least some of those pins have to be toggled active for the
> sensor devices to be available in i2c, so the conclusion we came to was
> that those GPIO entries assigned to the INT3472 device actually represent
> GPIOs and regulators to be consumed by the sensors themselves. Tsuchiya
> noticed that the lowest byte in the return values of the _DSM method
> seemed to represent the type or function of the GPIO line, and we
> confirmed that by testing on each surface device that GPIO lines where the
> low byte in the _DSM entry for that pin was 0x0d controlled the privacy
> LED of the cameras.
> 
> We're guessing as to the exact meaning of the function byte, but I
> conclude they're something like this:
> 
> 0x00 - probably a reset GPIO
> 0x01 - regulator for the sensor
> 0x0c - regulator for the sensor
> 0x0b - regulator again, but for a VCM or EEPROM

Is it possible that the ad5823 would be here, and controled by this bit ?

> 0x0d - privacy led (only one we're totally confident of since we can see
>        it happen!)
> 
> After much internal debate I decided to write this as a standalone
> acpi_driver. Alternative options we considered:
> 
> 1. Squash all this into the cio2-bridge code, which I did originally write
> but decided I didn't like.
> 2. Extend the existing tps68470 mfd driver...they share an ACPI ID so this
> kinda makes sense, but ultimately given there is no actual physical
> tps68470 in the scenario this patch handles I decided I didn't like this
> either.
> 
>  MAINTAINERS                            |   7 +
>  drivers/media/pci/intel/ipu3/Kconfig   |  14 +
>  drivers/media/pci/intel/ipu3/Makefile  |   1 +
>  drivers/media/pci/intel/ipu3/int3472.c | 381 +++++++++++++++++++++++++
>  drivers/media/pci/intel/ipu3/int3472.h |  96 +++++++
>  5 files changed, 499 insertions(+)
>  create mode 100644 drivers/media/pci/intel/ipu3/int3472.c
>  create mode 100644 drivers/media/pci/intel/ipu3/int3472.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 188559a0a610..d73471f9c2a3 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8753,6 +8753,13 @@ L:	linux-crypto@vger.kernel.org
>  S:	Maintained
>  F:	drivers/crypto/inside-secure/
>  
> +INT3472 ACPI DEVICE DRIVER
> +M:	Daniel Scally <djrscally@gmail.com>
> +L:	linux-media@vger.kernel.org
> +S:	Maintained
> +F:	drivers/media/pci/intel/ipu3/int3472.c
> +F:	drivers/media/pci/intel/ipu3/int3472.h
> +
>  INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
>  M:	Mimi Zohar <zohar@linux.ibm.com>
>  M:	Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
> diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
> index 2b3350d042be..9dd3b280f821 100644
> --- a/drivers/media/pci/intel/ipu3/Kconfig
> +++ b/drivers/media/pci/intel/ipu3/Kconfig
> @@ -34,3 +34,17 @@ config CIO2_BRIDGE
>  		- Dell 7285
>  
>  	  If in doubt, say N here.
> +
> +config INT3472
> +	tristate "INT3472 Dummy ACPI Device Driver"
> +	depends on VIDEO_IPU3_CIO2
> +	depends on ACPI && REGULATOR && GPIOLIB
> +	help
> +	  This module provides an ACPI driver for INT3472 devices that do not
> +	  represent an actual physical tps68470 device.
> +
> +	  Say Y here if your device is a detachable / hybrid laptop that comes
> +	  with Windows installed by the OEM.
> +	  The module will be called int3472.
> +
> +	  If in doubt, say N here.

Is there any issue if the tps68470 driver is also selected and probed ?

> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
> index 933777e6ea8a..2285947b2bd2 100644
> --- a/drivers/media/pci/intel/ipu3/Makefile
> +++ b/drivers/media/pci/intel/ipu3/Makefile
> @@ -1,5 +1,6 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
> +obj-$(CONFIG_INT3472) += int3472.o
>  
>  ipu3-cio2-y += ipu3-cio2-main.o
>  ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
> diff --git a/drivers/media/pci/intel/ipu3/int3472.c b/drivers/media/pci/intel/ipu3/int3472.c
> new file mode 100644
> index 000000000000..6b0be75f7f35
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu3/int3472.c
> @@ -0,0 +1,381 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Author: Dan Scally <djrscally@gmail.com> */
> +#include <linux/acpi.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/gpio/machine.h>
> +#include <linux/i2c.h>
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/module.h>
> +#include <linux/regulator/driver.h>
> +
> +#include "int3472.h"
> +
> +/*
> + * The regulators have to have .ops to be valid, but the only ops we actually
> + * support are .enable and .disable which are handled via .ena_gpiod. Pass an
> + * empty struct to clear the check without lying about capabilities.
> + */
> +static const struct regulator_ops int3472_gpio_regulator_ops = { 0 };
> +
> +static int int3472_map_gpio_to_sensor(struct int3472_device *int3472,
> +				      struct acpi_resource *ares, char *func)
> +{
> +	char *path = ares->data.gpio.resource_source.string_ptr;
> +	struct gpiod_lookup table_entry;
> +	struct acpi_device *adev;
> +	acpi_handle handle;
> +	acpi_status status;
> +	int ret;
> +
> +	/* Make sure we don't overflow, and leave room for a terminator */
> +	if (int3472->n_sensor_gpios >= INT3472_MAX_SENSOR_GPIOS) {
> +		dev_warn(&int3472->sensor->dev, "Too many GPIOs mapped\n");
> +		return -EINVAL;
> +	}
> +
> +	/* Fetch ACPI handle for the GPIO chip  */
> +	status = acpi_get_handle(NULL, path, &handle);
> +	if (ACPI_FAILURE(status))
> +		return -EINVAL;
> +
> +	ret = acpi_bus_get_device(handle, &adev);
> +	if (ret)
> +		return -ENODEV;
> +
> +	table_entry = (struct gpiod_lookup)GPIO_LOOKUP_IDX(acpi_dev_name(adev),
> +							   ares->data.gpio.pin_table[0],
> +							   func, 0, GPIO_ACTIVE_HIGH);
> +
> +	memcpy(&int3472->gpios.table[int3472->n_sensor_gpios], &table_entry,
> +	       sizeof(table_entry));
> +	int3472->n_sensor_gpios++;
> +
> +	return 0;
> +}
> +
> +static struct int3472_sensor_regulator_map *
> +int3472_get_sensor_supply_map(struct int3472_device *int3472)
> +{
> +	struct int3472_sensor_regulator_map *ret;
> +	union acpi_object *obj;
> +	unsigned int i;
> +
> +	/*
> +	 * Sensor modules seem to be identified by a unique string. We use that
> +	 * to make sure we pass the right device and supply names to the new
> +	 * regulator's consumer_supplies
> +	 */
> +	obj = acpi_evaluate_dsm_typed(int3472->sensor->handle,
> +				      &cio2_sensor_module_guid, 0x00,
> +				      0x01, NULL, ACPI_TYPE_STRING);
> +
> +	if (!obj) {
> +		dev_err(&int3472->sensor->dev,
> +			"Failed to get sensor module string from _DSM\n");
> +		return ERR_PTR(-ENODEV);
> +	}
> +
> +	if (obj->string.type != ACPI_TYPE_STRING) {
> +		dev_err(&int3472->sensor->dev,
> +			"Sensor _DSM returned a non-string value\n");
> +		ret = ERR_PTR(-EINVAL);
> +		goto out_free_obj;
> +	}
> +
> +	ret = ERR_PTR(-ENODEV);
> +	for (i = 0; i < ARRAY_SIZE(int3472_sensor_regulator_maps); i++) {
> +		if (!strcmp(int3472_sensor_regulator_maps[i].sensor_module_name,
> +			    obj->string.pointer)) {
> +			ret = &int3472_sensor_regulator_maps[i];
> +			goto out_free_obj;
> +		}
> +	}
> +
> +out_free_obj:
> +	ACPI_FREE(obj);
> +	return ret;
> +}
> +
> +static int int3472_register_regulator(struct int3472_device *int3472,
> +				      struct acpi_resource *ares)
> +{
> +	char *path = ares->data.gpio.resource_source.string_ptr;
> +	struct int3472_sensor_regulator_map *regulator_map;
> +	struct regulator_init_data init_data = { };
> +	struct int3472_gpio_regulator *regulator;
> +	struct regulator_config cfg = { };
> +	int ret;
> +
> +	/*
> +	 * We lookup supply names from machine specific tables, based on a
> +	 * unique identifier in the sensor's _DSM
> +	 */
> +	regulator_map = int3472_get_sensor_supply_map(int3472);
> +	if (IS_ERR_OR_NULL(regulator_map)) {
> +		dev_err(&int3472->sensor->dev,
> +			"Found no supplies defined for this sensor\n");
> +		return PTR_ERR(regulator_map);
> +	}
> +
> +	if (int3472->n_regulators >= regulator_map->n_supplies) {
> +		dev_err(&int3472->sensor->dev,
> +			"All known supplies are already mapped\n");
> +		return -EINVAL;
> +	}
> +
> +	init_data.supply_regulator = NULL;
> +	init_data.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
> +	init_data.num_consumer_supplies = 1;
> +	init_data.consumer_supplies = &regulator_map->supplies[int3472->n_regulators];
> +
> +	regulator = kmalloc(sizeof(*regulator), GFP_KERNEL);
> +	if (!regulator)
> +		return -ENOMEM;
> +
> +	snprintf(regulator->regulator_name, GPIO_REGULATOR_NAME_LENGTH,
> +		 "gpio-regulator-%d", int3472->n_regulators);
> +	snprintf(regulator->supply_name, GPIO_REGULATOR_SUPPLY_NAME_LENGTH,
> +		 "supply-%d", int3472->n_regulators);
> +
> +	regulator->rdesc = INT3472_REGULATOR(regulator->regulator_name,
> +					     regulator->supply_name,
> +					     int3472->n_regulators,
> +					     &int3472_gpio_regulator_ops);
> +
> +	regulator->gpio = acpi_get_gpiod(path, ares->data.gpio.pin_table[0]);
> +	if (IS_ERR(regulator->gpio)) {
> +		ret = PTR_ERR(regulator->gpio);
> +		goto err_free_regulator;
> +	}
> +
> +	cfg.dev = &int3472->adev->dev;
> +	cfg.init_data = &init_data;
> +	cfg.ena_gpiod = regulator->gpio;
> +
> +	regulator->rdev = regulator_register(&regulator->rdesc, &cfg);
> +	if (IS_ERR(regulator->rdev)) {
> +		ret = PTR_ERR(regulator->rdev);
> +		goto err_free_gpio;
> +	}
> +
> +	list_add(&regulator->list, &int3472->regulators);
> +	int3472->n_regulators++;
> +
> +	return 0;
> +
> +err_free_gpio:
> +	gpiod_put(regulator->gpio);
> +err_free_regulator:
> +	kfree(regulator);
> +
> +	return ret;
> +}
> +
> +static int int3472_handle_gpio_resources(struct acpi_resource *ares,
> +					 void *data)
> +{
> +	struct int3472_device *int3472 = data;
> +	union acpi_object *obj;
> +	int ret = 0;
> +
> +	if (ares->type != ACPI_RESOURCE_TYPE_GPIO ||
> +	    ares->data.gpio.connection_type != ACPI_RESOURCE_GPIO_TYPE_IO)
> +		return EINVAL; /* Deliberately positive */
> +
> +	/*
> +	 * n_gpios + 2 because the index of this _DSM function is 1-based and
> +	 * the first function is just a count.
> +	 */
> +	obj = acpi_evaluate_dsm_typed(int3472->adev->handle,
> +				      &int3472_gpio_guid, 0x00,
> +				      int3472->n_gpios + 2,
> +				      NULL, ACPI_TYPE_INTEGER);
> +
> +	if (!obj) {
> +		dev_warn(&int3472->adev->dev,
> +			 "No _DSM entry for this GPIO pin\n");
> +		return ENODEV;
> +	}
> +
> +	switch (obj->integer.value & 0xff) { /* low byte holds type data */
> +	case 0x00: /* Purpose unclear, possibly a reset GPIO pin */
> +		ret = int3472_map_gpio_to_sensor(int3472, ares, "reset");
> +		if (ret)
> +			dev_warn(&int3472->adev->dev,
> +				 "Failed to map reset pin to sensor\n");
> +
> +		break;
> +	case 0x01: /* Power regulators (we think) */
> +	case 0x0c:
> +		ret = int3472_register_regulator(int3472, ares);
> +		if (ret)
> +			dev_warn(&int3472->adev->dev,
> +				 "Failed to map regulator to sensor\n");
> +
> +		break;
> +	case 0x0b: /* Power regulators, but to a device separate to sensor */
> +		ret = int3472_register_regulator(int3472, ares);
> +		if (ret)
> +			dev_warn(&int3472->adev->dev,
> +				 "Failed to map regulator to sensor\n");
> +
> +		break;
> +	case 0x0d: /* Indicator LEDs */
> +		ret = int3472_map_gpio_to_sensor(int3472, ares, "indicator-led");
> +		if (ret)
> +			dev_warn(&int3472->adev->dev,
> +				 "Failed to map indicator led to sensor\n");
> +
> +		break;
> +	default:
> +		/* if we've gotten here, we're not sure what they are yet */
> +		dev_warn(&int3472->adev->dev,
> +			 "GPIO type 0x%llx unknown; the sensor may not work\n",
> +			 (obj->integer.value & 0xff));
> +		ret = EINVAL;
> +	}
> +
> +	int3472->n_gpios++;
> +	ACPI_FREE(obj);
> +	return abs(ret);
> +}
> +
> +static void int3472_parse_crs(struct int3472_device *int3472)
> +{
> +	struct list_head resource_list;
> +
> +	INIT_LIST_HEAD(&resource_list);
> +
> +	acpi_dev_get_resources(int3472->adev, &resource_list,
> +			       int3472_handle_gpio_resources, int3472);
> +
> +	acpi_dev_free_resource_list(&resource_list);
> +	gpiod_add_lookup_table(&int3472->gpios);
> +}
> +
> +static int int3472_add(struct acpi_device *adev)
> +{
> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> +	struct int3472_device *int3472;
> +	struct int3472_cldb cldb;
> +	union acpi_object *obj;
> +	acpi_status status;
> +	int ret = 0;
> +
> +	/*
> +	 * This driver is only intended to support "dummy" INT3472 devices
> +	 * which appear in ACPI designed for Windows. These are distinguishable
> +	 * from INT3472 entries representing an actual tps68470 PMIC through
> +	 * the presence of a CLDB buffer with a particular value set.
> +	 */
> +	status = acpi_evaluate_object(adev->handle, "CLDB", NULL, &buffer);
> +	if (ACPI_FAILURE(status))
> +		return -ENODEV;
> +
> +	obj = buffer.pointer;
> +	if (!obj) {
> +		dev_err(&adev->dev, "ACPI device has no CLDB object\n");
> +		return -ENODEV;
> +	}
> +
> +	if (obj->type != ACPI_TYPE_BUFFER) {
> +		dev_err(&adev->dev, "CLDB object is not an ACPI buffer\n");
> +		ret = -EINVAL;
> +		goto out_free_buff;
> +	}
> +
> +	if (obj->buffer.length > sizeof(cldb)) {
> +		dev_err(&adev->dev, "The CLDB buffer is too large\n");
> +		ret = -EINVAL;
> +		goto out_free_buff;
> +	}
> +
> +	memcpy(&cldb, obj->buffer.pointer, obj->buffer.length);
> +
> +	/*
> +	 * control_logic_type = 1 indicates this is a dummy INT3472 device of
> +	 * the kind we're looking for. If any other value then we shouldn't try
> +	 * to handle it
> +	 */
> +	if (cldb.control_logic_type != 1) {
> +		ret = -EINVAL;
> +		goto out_free_buff;
> +	}
> +
> +	/* Space for 4 GPIOs - one more than we've seen so far plus a null */
> +	int3472 = kzalloc(sizeof(*int3472) +
> +			 ((INT3472_MAX_SENSOR_GPIOS + 1) * sizeof(struct gpiod_lookup)),
> +			 GFP_KERNEL);
> +	if (!int3472) {
> +		ret = -ENOMEM;
> +		goto out_free_buff;
> +	}
> +
> +	int3472->adev = adev;
> +	adev->driver_data = int3472;
> +
> +	int3472->sensor = acpi_dev_get_next_dep_dev(adev, NULL);
> +	if (!int3472->sensor) {
> +		dev_err(&adev->dev,
> +			"This INT3472 entry seems to have no dependents.\n");
> +		ret = -ENODEV;
> +		goto out_free_int3472;
> +	}
> +
> +	int3472->gpios.dev_id = i2c_acpi_dev_name(int3472->sensor);
> +
> +	INIT_LIST_HEAD(&int3472->regulators);
> +
> +	int3472_parse_crs(int3472);
> +
> +	goto out_free_buff;
> +
> +out_free_int3472:
> +	kfree(int3472);
> +out_free_buff:
> +	kfree(buffer.pointer);
> +	return ret;
> +}
> +
> +static int int3472_remove(struct acpi_device *adev)
> +{
> +	struct int3472_gpio_regulator *reg;
> +	struct int3472_device *int3472;
> +
> +	int3472 = acpi_driver_data(adev);
> +
> +	acpi_dev_put(int3472->sensor);
> +	gpiod_remove_lookup_table(&int3472->gpios);
> +
> +	list_for_each_entry(reg, &int3472->regulators, list) {
> +		gpiod_put(reg->gpio);
> +		regulator_unregister(reg->rdev);
> +	}
> +
> +	kfree(int3472);
> +
> +	return 0;
> +}
> +
> +static const struct acpi_device_id int3472_device_id[] = {
> +	{ "INT3472", 0 },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(acpi, int3472_device_id);
> +
> +static struct acpi_driver int3472_driver = {
> +	.name = "int3472",
> +	.ids = int3472_device_id,
> +	.ops = {
> +		.add = int3472_add,
> +		.remove = int3472_remove,
> +	},
> +	.owner = THIS_MODULE,
> +};
> +
> +module_acpi_driver(int3472_driver);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Dan Scally <djrscally@gmail.com>");
> +MODULE_DESCRIPTION("ACPI Driver for Discrete type INT3472 ACPI Devices");
> diff --git a/drivers/media/pci/intel/ipu3/int3472.h b/drivers/media/pci/intel/ipu3/int3472.h
> new file mode 100644
> index 000000000000..6964726e8e1f
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu3/int3472.h
> @@ -0,0 +1,96 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Author: Dan Scally <djrscally@gmail.com> */
> +#include <linux/regulator/machine.h>
> +
> +#define INT3472_MAX_SENSOR_GPIOS			3
> +#define GPIO_REGULATOR_NAME_LENGTH			17
> +#define GPIO_REGULATOR_SUPPLY_NAME_LENGTH		9
> +
> +#define INT3472_REGULATOR(_NAME, _SUPPLY, _ID, _OPS)	\
> +	((const struct regulator_desc) {		\
> +		.name = _NAME,				\
> +		.supply_name = _SUPPLY,			\
> +		.id = _ID,				\
> +		.type = REGULATOR_VOLTAGE,		\
> +		.ops = _OPS,				\
> +		.owner = THIS_MODULE,			\
> +	})
> +
> +const guid_t int3472_gpio_guid = GUID_INIT(0x79234640, 0x9e10, 0x4fea,
> +					     0xa5, 0xc1, 0xb5, 0xaa, 0x8b,
> +					     0x19, 0x75, 0x6f);
> +
> +const guid_t cio2_sensor_module_guid = GUID_INIT(0x822ace8f, 0x2814, 0x4174,
> +						 0xa5, 0x6b, 0x5f, 0x02, 0x9f,
> +						 0xe0, 0x79, 0xee);
> +
> +struct int3472_cldb {
> +	u8 version;
> +	/*
> +	 * control logic type
> +	 * 0: UNKNOWN
> +	 * 1: DISCRETE(CRD-D)
> +	 * 2: PMIC TPS68470
> +	 * 3: PMIC uP6641
> +	 */
> +	u8 control_logic_type;
> +	u8 control_logic_id;
> +	u8 sensor_card_sku;
> +	u8 reserved[28];
> +};
> +
> +struct int3472_device {
> +	struct acpi_device *adev;
> +	struct acpi_device *sensor;
> +
> +	unsigned int n_gpios; /* how many GPIOs have we seen */
> +
> +	unsigned int n_regulators;
> +	struct list_head regulators;
> +
> +	unsigned int n_sensor_gpios; /* how many have we mapped to sensor */
> +	struct gpiod_lookup_table gpios;
> +};
> +
> +struct int3472_gpio_regulator {
> +	char regulator_name[GPIO_REGULATOR_NAME_LENGTH];
> +	char supply_name[GPIO_REGULATOR_SUPPLY_NAME_LENGTH];
> +	struct gpio_desc *gpio;
> +	struct regulator_dev *rdev;
> +	struct regulator_desc rdesc;
> +	struct list_head list;
> +};
> +
> +struct int3472_sensor_regulator_map {
> +	char *sensor_module_name;
> +	unsigned int n_supplies;
> +	struct regulator_consumer_supply *supplies;
> +};
> +
> +/*
> + * Here follows platform specific mapping information that we can pass to
> + * regulator_init_data when we register our regulators. They're just mapped
> + * via index, I.E. the first regulator pin that the code finds for the
> + * i2c-OVTI2680:00 device is avdd, the second is dovdd and so on.
> + */
> +
> +static struct regulator_consumer_supply miix_510_ov2680[] = {
> +	{ "i2c-OVTI2680:00", "avdd" },
> +	{ "i2c-OVTI2680:00", "dovdd" },
> +};
> +
> +static struct regulator_consumer_supply surface_go2_ov5693[] = {
> +	{ "i2c-INT33BE:00", "avdd" },
> +	{ "i2c-INT33BE:00", "dovdd" },
> +};
> +
> +static struct regulator_consumer_supply surface_book_ov5693[] = {
> +	{ "i2c-INT33BE:00", "avdd" },
> +	{ "i2c-INT33BE:00", "dovdd" },
> +};
> +
> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
> +	{ "GNDF140809R", 2, miix_510_ov2680 },
> +	{ "YHCU", 2, surface_go2_ov5693 },
> +	{ "MSHW0070", 2, surface_book_ov5693 },
> +};
> 

Thanks,
JM

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

* Re: [PATCH 07/18] software_node: Add support for fwnode_graph*() family of functions
  2020-11-30 13:31 ` [PATCH 07/18] software_node: Add support for fwnode_graph*() family of functions Daniel Scally
@ 2020-11-30 16:25   ` Laurent Pinchart
  2020-11-30 23:34     ` Dan Scally
  0 siblings, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 16:25 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Daniel and Heikki,

Thank you for the patch.

On Mon, Nov 30, 2020 at 01:31:18PM +0000, Daniel Scally wrote:
> From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> 
> From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> 

There seems to be one From: line too many. You can drop the one in the
commit message, git-format-patch will add it automatically.

> This implements the remaining .graph_* callbacks in the
> fwnode operations vector for the software nodes. That makes

s/vector/structure/ ?

> the fwnode_graph*() functions available in the drivers also
> when software nodes are used.
> 
> The implementation tries to mimic the "OF graph" as much as
> possible, but there is no support for the "reg" device
> property. The ports will need to have the index in their
> name which starts with "port" (for example "port0", "port1",
> ...) and endpoints will use the index of the software node
> that is given to them during creation. The port nodes can
> also be grouped under a specially named "ports" subnode,
> just like in DT, if necessary.

I'm not very familiar with swnodes, but could we name ports port@n
instead of portn to mimic OF nodes ?

> The remote-endpoints are reference properties under the
> endpoint nodes that are named "remote-endpoint".
> 
> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Co-developed-by: Daniel Scally <djrscally@gmail.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> changes since RFC v3:
> 	- Simplified software_node_get_next_endpoint() a little
> 	- Squared away references in software_node_get_next_endpoint()
> 	and swnode_graph_find_next_port(), since they were affected by
> 	the change to the earlier patch that had *get_next_child() also
> 	put the previous reference.
> 	- Dropped Andy's R-b, since the code changed.
> changes in RFC v3:
> 	- removed software_node_device_is_available
> 	- moved the change to software_node_get_next_child to a separate
> 	patch
> 	- switched to use fwnode_handle_put() in graph_get_next_endpoint()
> 	instead of software_node_put()
> 
> changes in RFC v2:
> 	- added software_node_device_is_available
> 	- altered software_node_get_next_child to get references
> 	- altered software_node_get_next_endpoint to release references
> 	to ports and avoid passing invalid combinations of swnodes to
> 	software_node_get_next_child
> 	- altered swnode_graph_find_next_port to release port rather than
> 	old
> 
>  drivers/base/swnode.c | 110 +++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 109 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> index 9bd0bb77ad5b..0c7a8d6b9ea8 100644
> --- a/drivers/base/swnode.c
> +++ b/drivers/base/swnode.c
> @@ -540,6 +540,110 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
>  	return 0;
>  }
>  
> +static struct fwnode_handle *
> +swnode_graph_find_next_port(const struct fwnode_handle *parent,
> +			    struct fwnode_handle *port)
> +{
> +	struct fwnode_handle *old = port;
> +
> +	while ((port = software_node_get_next_child(parent, old))) {
> +		if (!strncmp(to_swnode(port)->node->name, "port", 4))
> +			return port;
> +		old = port;
> +	}
> +
> +	return NULL;
> +}
> +
> +static struct fwnode_handle *
> +software_node_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
> +				      struct fwnode_handle *endpoint)
> +{
> +	struct swnode *swnode = to_swnode(fwnode);
> +	struct fwnode_handle *old = endpoint;
> +	struct fwnode_handle *parent;
> +	struct fwnode_handle *port;
> +
> +	if (!swnode)
> +		return NULL;
> +
> +	if (endpoint) {
> +		port = software_node_get_parent(endpoint);
> +		parent = software_node_get_parent(port);
> +	} else {
> +		parent = software_node_get_named_child_node(fwnode, "ports");
> +		if (!parent)
> +			parent = software_node_get(&swnode->fwnode);
> +
> +		port = swnode_graph_find_next_port(parent, NULL);
> +	}
> +
> +	for (; port; port = swnode_graph_find_next_port(parent, port)) {
> +		endpoint = software_node_get_next_child(port, old);
> +		if (endpoint) {
> +			fwnode_handle_put(port);
> +			break;
> +		}
> +
> +		/* No more endpoints for that port, so stop passing old */
> +		old = NULL;
> +	}
> +
> +	fwnode_handle_put(parent);
> +
> +	return endpoint;
> +}
> +
> +static struct fwnode_handle *
> +software_node_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
> +{
> +	struct swnode *swnode = to_swnode(fwnode);
> +	const struct software_node_ref_args *ref;
> +	const struct property_entry *prop;
> +
> +	if (!swnode)
> +		return NULL;
> +
> +	prop = property_entry_get(swnode->node->properties, "remote-endpoint");
> +	if (!prop || prop->type != DEV_PROP_REF || prop->is_inline)
> +		return NULL;
> +
> +	ref = prop->pointer;
> +
> +	return software_node_get(software_node_fwnode(ref[0].node));
> +}
> +
> +static struct fwnode_handle *
> +software_node_graph_get_port_parent(struct fwnode_handle *fwnode)
> +{
> +	struct swnode *swnode = to_swnode(fwnode);
> +	struct fwnode_handle *parent;
> +
> +	if (!strcmp(swnode->parent->node->name, "ports"))
> +		parent = &swnode->parent->parent->fwnode;
> +	else
> +		parent = &swnode->parent->fwnode;
> +
> +	return software_node_get(parent);
> +}
> +
> +static int
> +software_node_graph_parse_endpoint(const struct fwnode_handle *fwnode,
> +				   struct fwnode_endpoint *endpoint)
> +{
> +	struct swnode *swnode = to_swnode(fwnode);
> +	int ret;
> +
> +	ret = kstrtou32(swnode->parent->node->name + 4, 10, &endpoint->port);

If we use port@, s/4/5/. But I suppose we also want to support the case
where a single port is used, with its name set to "port" ? The logic
would then need to be a tad more complex. Not sure if the consistency is
worth the additional complexity, up to you.

> +	if (ret)
> +		return ret;
> +
> +	endpoint->id = swnode->id;
> +	endpoint->local_fwnode = fwnode;
> +
> +	return 0;
> +}
> +
>  static const struct fwnode_operations software_node_ops = {
>  	.get = software_node_get,
>  	.put = software_node_put,
> @@ -551,7 +655,11 @@ static const struct fwnode_operations software_node_ops = {
>  	.get_parent = software_node_get_parent,
>  	.get_next_child_node = software_node_get_next_child,
>  	.get_named_child_node = software_node_get_named_child_node,
> -	.get_reference_args = software_node_get_reference_args
> +	.get_reference_args = software_node_get_reference_args,
> +	.graph_get_next_endpoint = software_node_graph_get_next_endpoint,
> +	.graph_get_remote_endpoint = software_node_graph_get_remote_endpoint,
> +	.graph_get_port_parent = software_node_graph_get_port_parent,
> +	.graph_parse_endpoint = software_node_graph_parse_endpoint,
>  };
>  
>  /* -------------------------------------------------------------------------- */

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 08/18] lib/test_printf.c: Use helper function to unwind array of software_nodes
  2020-11-30 13:31 ` [PATCH 08/18] lib/test_printf.c: Use helper function to unwind array of software_nodes Daniel Scally
  2020-11-30 15:54   ` Sergey Senozhatsky
@ 2020-11-30 16:26   ` Laurent Pinchart
  1 sibling, 0 replies; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 16:26 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Daniel,

Thank you for the patch.

On Mon, Nov 30, 2020 at 01:31:19PM +0000, Daniel Scally wrote:
> Use the software_node_unregister_nodes() helper function to unwind this
> array in a cleaner way.
> 
> Acked-by: Petr Mladek <pmladek@suse.com>
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
> Changes since RFC v3:
> 
> 	Changed the called function name - didn't drop the tags since it's
> 	such a trivial change, hope that's alright!
> 
>  lib/test_printf.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/lib/test_printf.c b/lib/test_printf.c
> index 7ac87f18a10f..7d60f24240a4 100644
> --- a/lib/test_printf.c
> +++ b/lib/test_printf.c
> @@ -644,9 +644,7 @@ static void __init fwnode_pointer(void)
>  	test(second_name, "%pfwP", software_node_fwnode(&softnodes[1]));
>  	test(third_name, "%pfwP", software_node_fwnode(&softnodes[2]));
>  
> -	software_node_unregister(&softnodes[2]);
> -	software_node_unregister(&softnodes[1]);
> -	software_node_unregister(&softnodes[0]);
> +	software_node_unregister_nodes(softnodes);
>  }
>  
>  static void __init

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 11/18] media: v4l2-core: v4l2-async: Check possible match in match_fwnode based on sd->fwnode->secondary
  2020-11-30 13:31 ` [PATCH 11/18] media: v4l2-core: v4l2-async: Check possible match in match_fwnode based on sd->fwnode->secondary Daniel Scally
@ 2020-11-30 16:27   ` Laurent Pinchart
  2020-11-30 17:55   ` Andy Shevchenko
  1 sibling, 0 replies; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 16:27 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Daniel,

Thank you for the patch.

On Mon, Nov 30, 2020 at 01:31:22PM +0000, Daniel Scally wrote:
> Where the fwnode graph is comprised of software_nodes, these will be
> assigned as the secondary to dev->fwnode. Check the v4l2_subdev's fwnode
> for a secondary and attempt to match against it during match_fwnode() to
> accommodate that possibility.
> 
> Signed-off-by: Daniel Scally <djrscally@gmail.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> ---
> Changes since RFC v3:
> 
> 	- None
> 
>  drivers/media/v4l2-core/v4l2-async.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index e3ab003a6c85..6486dbde784f 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -87,6 +87,14 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier,
>  	if (sd->fwnode == asd->match.fwnode)
>  		return true;
>  
> +	/*
> +	 * Check the same situation for any possible secondary assigned to the
> +	 * subdev's fwnode
> +	 */
> +	if ((!IS_ERR_OR_NULL(sd->fwnode->secondary)) &&
> +	    sd->fwnode->secondary == asd->match.fwnode)
> +		return true;
> +
>  	/*
>  	 * Otherwise, check if the sd fwnode and the asd fwnode refer to an
>  	 * endpoint or a device. If they're of the same type, there's no match.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 13:31 ` [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device Daniel Scally
  2020-11-30 16:17   ` Jean-Michel Hautbois
@ 2020-11-30 16:29   ` Kieran Bingham
  2020-11-30 17:21     ` Laurent Pinchart
  2020-11-30 20:07   ` Andy Shevchenko
  2020-11-30 20:52   ` Sakari Ailus
  3 siblings, 1 reply; 144+ messages in thread
From: Kieran Bingham @ 2020-11-30 16:29 UTC (permalink / raw)
  To: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux, jacopo+renesas,
	laurent.pinchart+renesas, jorhand, kitakar, heikki.krogerus,
	Laurent Pinchart

Hi Daniel,

On 30/11/2020 13:31, Daniel Scally wrote:
> On platforms where ACPI is designed for use with Windows, resources
> that are intended to be consumed by sensor devices are sometimes in
> the _CRS of a dummy INT3472 device upon which the sensor depends. This
> driver binds to the dummy acpi device (which does not represent a
> physical PMIC) and maps them into GPIO lines and regulators for use by
> the sensor device instead.
> 
> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes since RFC v3:
> 
> 	- Patch introduced
> 
> This patch contains the bits of this process that we're least sure about.
> The sensors in scope for this work are called out as dependent (in their
> DSDT entry's _DEP) on a device with _HID INT3472. These come in at least
> 2 kinds; those with an I2cSerialBusV2 entry (which we presume therefore
> are legitimate tps68470 PMICs that need handling by those drivers - work
> on that in the future). And those without an I2C device. For those without
> an I2C device they instead have an array of GPIO pins defined in _CRS. So
> for example, my Lenovo Miix 510's OVTI2680 sensor is dependent on one of
> the _latter_ kind of INT3472 devices, with this _CRS:
> 
> Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
> {
>     Name (SBUF, ResourceTemplate ()
>     {
>         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> 	    0x00, ResourceConsumer, ,
>             )
>             {   // Pin list
>                 0x0079
>             }
>         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> 	    0x00, ResourceConsumer, ,
>             )
>             {   // Pin list
>                 0x007A
>             }
>         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> 	    0x00, ResourceConsumer, ,
>             )
>             {   // Pin list
>                 0x008F
>             }
>     })
>     Return (SBUF) /* \_SB_.PCI0.PMI1._CRS.SBUF */
> }
> 
> and the same device has a _DSM Method, which returns 32-bit ints where
> the second lowest byte we noticed to match the pin numbers of the GPIO
> lines:
> 
> Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
> {
>     If ((Arg0 == ToUUID ("79234640-9e10-4fea-a5c1-b5aa8b19756f")))
>     {
>         If ((Arg2 == One))
>         {
>             Return (0x03)
>         }
> 
>         If ((Arg2 == 0x02))
>         {
>             Return (0x01007900)
>         }
> 
>         If ((Arg2 == 0x03))
>         {
>             Return (0x01007A0C)
>         }
> 
>         If ((Arg2 == 0x04))
>         {
>             Return (0x01008F01)
>         }
>     }
> 
>     Return (Zero)
> }
> 
> We know that at least some of those pins have to be toggled active for the
> sensor devices to be available in i2c, so the conclusion we came to was
> that those GPIO entries assigned to the INT3472 device actually represent
> GPIOs and regulators to be consumed by the sensors themselves. Tsuchiya
> noticed that the lowest byte in the return values of the _DSM method
> seemed to represent the type or function of the GPIO line, and we
> confirmed that by testing on each surface device that GPIO lines where the
> low byte in the _DSM entry for that pin was 0x0d controlled the privacy
> LED of the cameras.
> 
> We're guessing as to the exact meaning of the function byte, but I
> conclude they're something like this:
> 
> 0x00 - probably a reset GPIO
> 0x01 - regulator for the sensor
> 0x0c - regulator for the sensor
> 0x0b - regulator again, but for a VCM or EEPROM
> 0x0d - privacy led (only one we're totally confident of since we can see
>        it happen!)
> 
> After much internal debate I decided to write this as a standalone
> acpi_driver. Alternative options we considered:
> 
> 1. Squash all this into the cio2-bridge code, which I did originally write
> but decided I didn't like.
> 2. Extend the existing tps68470 mfd driver...they share an ACPI ID so this
> kinda makes sense, but ultimately given there is no actual physical
> tps68470 in the scenario this patch handles I decided I didn't like this
> either.
> 

I would agree, keeping this in a unit file on it's own makes sense to me.

I'm a bit worried about what happens if the tps68470 is also compiled
in... Does the right device get mapped in the event that there are also
actual devices already supported by the tps68470 mfd driver on the
device as well?



>  MAINTAINERS                            |   7 +
>  drivers/media/pci/intel/ipu3/Kconfig   |  14 +
>  drivers/media/pci/intel/ipu3/Makefile  |   1 +
>  drivers/media/pci/intel/ipu3/int3472.c | 381 +++++++++++++++++++++++++
>  drivers/media/pci/intel/ipu3/int3472.h |  96 +++++++
>  5 files changed, 499 insertions(+)
>  create mode 100644 drivers/media/pci/intel/ipu3/int3472.c
>  create mode 100644 drivers/media/pci/intel/ipu3/int3472.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 188559a0a610..d73471f9c2a3 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8753,6 +8753,13 @@ L:	linux-crypto@vger.kernel.org
>  S:	Maintained
>  F:	drivers/crypto/inside-secure/
>  
> +INT3472 ACPI DEVICE DRIVER
> +M:	Daniel Scally <djrscally@gmail.com>
> +L:	linux-media@vger.kernel.org
> +S:	Maintained
> +F:	drivers/media/pci/intel/ipu3/int3472.c
> +F:	drivers/media/pci/intel/ipu3/int3472.h
> +
>  INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
>  M:	Mimi Zohar <zohar@linux.ibm.com>
>  M:	Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
> diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
> index 2b3350d042be..9dd3b280f821 100644
> --- a/drivers/media/pci/intel/ipu3/Kconfig
> +++ b/drivers/media/pci/intel/ipu3/Kconfig
> @@ -34,3 +34,17 @@ config CIO2_BRIDGE
>  		- Dell 7285
>  
>  	  If in doubt, say N here.
> +
> +config INT3472
> +	tristate "INT3472 Dummy ACPI Device Driver"
> +	depends on VIDEO_IPU3_CIO2
> +	depends on ACPI && REGULATOR && GPIOLIB
> +	help
> +	  This module provides an ACPI driver for INT3472 devices that do not
> +	  represent an actual physical tps68470 device.
> +
> +	  Say Y here if your device is a detachable / hybrid laptop that comes
> +	  with Windows installed by the OEM.
> +	  The module will be called int3472.
> +
> +	  If in doubt, say N here.
> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
> index 933777e6ea8a..2285947b2bd2 100644
> --- a/drivers/media/pci/intel/ipu3/Makefile
> +++ b/drivers/media/pci/intel/ipu3/Makefile
> @@ -1,5 +1,6 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
> +obj-$(CONFIG_INT3472) += int3472.o
>  
>  ipu3-cio2-y += ipu3-cio2-main.o
>  ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
> diff --git a/drivers/media/pci/intel/ipu3/int3472.c b/drivers/media/pci/intel/ipu3/int3472.c
> new file mode 100644
> index 000000000000..6b0be75f7f35
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu3/int3472.c
> @@ -0,0 +1,381 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Author: Dan Scally <djrscally@gmail.com> */
> +#include <linux/acpi.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/gpio/machine.h>
> +#include <linux/i2c.h>
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/module.h>
> +#include <linux/regulator/driver.h>
> +
> +#include "int3472.h"
> +
> +/*
> + * The regulators have to have .ops to be valid, but the only ops we actually
> + * support are .enable and .disable which are handled via .ena_gpiod. Pass an
> + * empty struct to clear the check without lying about capabilities.
> + */
> +static const struct regulator_ops int3472_gpio_regulator_ops = { 0 };
> +
> +static int int3472_map_gpio_to_sensor(struct int3472_device *int3472,
> +				      struct acpi_resource *ares, char *func)
> +{
> +	char *path = ares->data.gpio.resource_source.string_ptr;
> +	struct gpiod_lookup table_entry;
> +	struct acpi_device *adev;
> +	acpi_handle handle;
> +	acpi_status status;
> +	int ret;
> +
> +	/* Make sure we don't overflow, and leave room for a terminator */
> +	if (int3472->n_sensor_gpios >= INT3472_MAX_SENSOR_GPIOS) {
> +		dev_warn(&int3472->sensor->dev, "Too many GPIOs mapped\n");
> +		return -EINVAL;
> +	}
> +
> +	/* Fetch ACPI handle for the GPIO chip  */
> +	status = acpi_get_handle(NULL, path, &handle);
> +	if (ACPI_FAILURE(status))
> +		return -EINVAL;
> +
> +	ret = acpi_bus_get_device(handle, &adev);
> +	if (ret)
> +		return -ENODEV;
> +
> +	table_entry = (struct gpiod_lookup)GPIO_LOOKUP_IDX(acpi_dev_name(adev),
> +							   ares->data.gpio.pin_table[0],
> +							   func, 0, GPIO_ACTIVE_HIGH);
> +
> +	memcpy(&int3472->gpios.table[int3472->n_sensor_gpios], &table_entry,
> +	       sizeof(table_entry));
> +	int3472->n_sensor_gpios++;
> +
> +	return 0;
> +}
> +
> +static struct int3472_sensor_regulator_map *
> +int3472_get_sensor_supply_map(struct int3472_device *int3472)
> +{
> +	struct int3472_sensor_regulator_map *ret;
> +	union acpi_object *obj;
> +	unsigned int i;
> +
> +	/*
> +	 * Sensor modules seem to be identified by a unique string. We use that
> +	 * to make sure we pass the right device and supply names to the new
> +	 * regulator's consumer_supplies
> +	 */
> +	obj = acpi_evaluate_dsm_typed(int3472->sensor->handle,
> +				      &cio2_sensor_module_guid, 0x00,
> +				      0x01, NULL, ACPI_TYPE_STRING);
> +
> +	if (!obj) {
> +		dev_err(&int3472->sensor->dev,
> +			"Failed to get sensor module string from _DSM\n");
> +		return ERR_PTR(-ENODEV);
> +	}
> +
> +	if (obj->string.type != ACPI_TYPE_STRING) {
> +		dev_err(&int3472->sensor->dev,
> +			"Sensor _DSM returned a non-string value\n");
> +		ret = ERR_PTR(-EINVAL);
> +		goto out_free_obj;
> +	}
> +
> +	ret = ERR_PTR(-ENODEV);
> +	for (i = 0; i < ARRAY_SIZE(int3472_sensor_regulator_maps); i++) {
> +		if (!strcmp(int3472_sensor_regulator_maps[i].sensor_module_name,
> +			    obj->string.pointer)) {
> +			ret = &int3472_sensor_regulator_maps[i];
> +			goto out_free_obj;
> +		}
> +	}
> +
> +out_free_obj:
> +	ACPI_FREE(obj);
> +	return ret;
> +}
> +
> +static int int3472_register_regulator(struct int3472_device *int3472,
> +				      struct acpi_resource *ares)
> +{
> +	char *path = ares->data.gpio.resource_source.string_ptr;
> +	struct int3472_sensor_regulator_map *regulator_map;
> +	struct regulator_init_data init_data = { };
> +	struct int3472_gpio_regulator *regulator;
> +	struct regulator_config cfg = { };
> +	int ret;
> +
> +	/*
> +	 * We lookup supply names from machine specific tables, based on a
> +	 * unique identifier in the sensor's _DSM
> +	 */
> +	regulator_map = int3472_get_sensor_supply_map(int3472);
> +	if (IS_ERR_OR_NULL(regulator_map)) {
> +		dev_err(&int3472->sensor->dev,
> +			"Found no supplies defined for this sensor\n");
> +		return PTR_ERR(regulator_map);
> +	}
> +
> +	if (int3472->n_regulators >= regulator_map->n_supplies) {
> +		dev_err(&int3472->sensor->dev,
> +			"All known supplies are already mapped\n");
> +		return -EINVAL;
> +	}
> +
> +	init_data.supply_regulator = NULL;
> +	init_data.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
> +	init_data.num_consumer_supplies = 1;
> +	init_data.consumer_supplies = &regulator_map->supplies[int3472->n_regulators];
> +
> +	regulator = kmalloc(sizeof(*regulator), GFP_KERNEL);
> +	if (!regulator)
> +		return -ENOMEM;
> +
> +	snprintf(regulator->regulator_name, GPIO_REGULATOR_NAME_LENGTH,
> +		 "gpio-regulator-%d", int3472->n_regulators);
> +	snprintf(regulator->supply_name, GPIO_REGULATOR_SUPPLY_NAME_LENGTH,
> +		 "supply-%d", int3472->n_regulators);
> +
> +	regulator->rdesc = INT3472_REGULATOR(regulator->regulator_name,
> +					     regulator->supply_name,
> +					     int3472->n_regulators,
> +					     &int3472_gpio_regulator_ops);
> +
> +	regulator->gpio = acpi_get_gpiod(path, ares->data.gpio.pin_table[0]);
> +	if (IS_ERR(regulator->gpio)) {
> +		ret = PTR_ERR(regulator->gpio);
> +		goto err_free_regulator;
> +	}
> +
> +	cfg.dev = &int3472->adev->dev;
> +	cfg.init_data = &init_data;
> +	cfg.ena_gpiod = regulator->gpio;
> +
> +	regulator->rdev = regulator_register(&regulator->rdesc, &cfg);
> +	if (IS_ERR(regulator->rdev)) {
> +		ret = PTR_ERR(regulator->rdev);
> +		goto err_free_gpio;
> +	}
> +
> +	list_add(&regulator->list, &int3472->regulators);
> +	int3472->n_regulators++;
> +
> +	return 0;
> +
> +err_free_gpio:
> +	gpiod_put(regulator->gpio);
> +err_free_regulator:
> +	kfree(regulator);
> +
> +	return ret;
> +}
> +
> +static int int3472_handle_gpio_resources(struct acpi_resource *ares,
> +					 void *data)
> +{
> +	struct int3472_device *int3472 = data;
> +	union acpi_object *obj;
> +	int ret = 0;
> +
> +	if (ares->type != ACPI_RESOURCE_TYPE_GPIO ||
> +	    ares->data.gpio.connection_type != ACPI_RESOURCE_GPIO_TYPE_IO)
> +		return EINVAL; /* Deliberately positive */
> +
> +	/*
> +	 * n_gpios + 2 because the index of this _DSM function is 1-based and
> +	 * the first function is just a count.
> +	 */
> +	obj = acpi_evaluate_dsm_typed(int3472->adev->handle,
> +				      &int3472_gpio_guid, 0x00,
> +				      int3472->n_gpios + 2,
> +				      NULL, ACPI_TYPE_INTEGER);
> +
> +	if (!obj) {
> +		dev_warn(&int3472->adev->dev,
> +			 "No _DSM entry for this GPIO pin\n");
> +		return ENODEV;
> +	}
> +
> +	switch (obj->integer.value & 0xff) { /* low byte holds type data */
> +	case 0x00: /* Purpose unclear, possibly a reset GPIO pin */
> +		ret = int3472_map_gpio_to_sensor(int3472, ares, "reset");
> +		if (ret)
> +			dev_warn(&int3472->adev->dev,
> +				 "Failed to map reset pin to sensor\n");
> +
> +		break;
> +	case 0x01: /* Power regulators (we think) */
> +	case 0x0c:
A little annoying that 0x0c is before 0x0b ... but I see this is sharing
with 0x01, so I think this can stay like this.

It might be nice to wrap the values in some descriptive #defines though,
but I'm not sure what we'd call them, and if we're not yet sure on their
purposes - perhaps the raw values are better for now. We'll see I guess.



> +		ret = int3472_register_regulator(int3472, ares);
> +		if (ret)
> +			dev_warn(&int3472->adev->dev,
> +				 "Failed to map regulator to sensor\n");
> +
> +		break;
> +	case 0x0b: /* Power regulators, but to a device separate to sensor */
> +		ret = int3472_register_regulator(int3472, ares);
> +		if (ret)
> +			dev_warn(&int3472->adev->dev,
> +				 "Failed to map regulator to sensor\n");
> +
> +		break;
> +	case 0x0d: /* Indicator LEDs */
> +		ret = int3472_map_gpio_to_sensor(int3472, ares, "indicator-led");
> +		if (ret)
> +			dev_warn(&int3472->adev->dev,
> +				 "Failed to map indicator led to sensor\n");
> +
> +		break;
> +	default:
> +		/* if we've gotten here, we're not sure what they are yet */
> +		dev_warn(&int3472->adev->dev,
> +			 "GPIO type 0x%llx unknown; the sensor may not work\n",
> +			 (obj->integer.value & 0xff));
> +		ret = EINVAL;
> +	}
> +
> +	int3472->n_gpios++;
> +	ACPI_FREE(obj);
> +	return abs(ret);
> +}
> +
> +static void int3472_parse_crs(struct int3472_device *int3472)
> +{
> +	struct list_head resource_list;
> +
> +	INIT_LIST_HEAD(&resource_list);
> +
> +	acpi_dev_get_resources(int3472->adev, &resource_list,
> +			       int3472_handle_gpio_resources, int3472);
> +
> +	acpi_dev_free_resource_list(&resource_list);
> +	gpiod_add_lookup_table(&int3472->gpios);
> +}
> +
> +static int int3472_add(struct acpi_device *adev)
> +{
> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> +	struct int3472_device *int3472;
> +	struct int3472_cldb cldb;
> +	union acpi_object *obj;
> +	acpi_status status;
> +	int ret = 0;
> +
> +	/*
> +	 * This driver is only intended to support "dummy" INT3472 devices
> +	 * which appear in ACPI designed for Windows. These are distinguishable
> +	 * from INT3472 entries representing an actual tps68470 PMIC through
> +	 * the presence of a CLDB buffer with a particular value set.
> +	 */
> +	status = acpi_evaluate_object(adev->handle, "CLDB", NULL, &buffer);
> +	if (ACPI_FAILURE(status))
> +		return -ENODEV;
> +
> +	obj = buffer.pointer;
> +	if (!obj) {
> +		dev_err(&adev->dev, "ACPI device has no CLDB object\n");
> +		return -ENODEV;
> +	}
> +
> +	if (obj->type != ACPI_TYPE_BUFFER) {
> +		dev_err(&adev->dev, "CLDB object is not an ACPI buffer\n");
> +		ret = -EINVAL;
> +		goto out_free_buff;
> +	}
> +
> +	if (obj->buffer.length > sizeof(cldb)) {
> +		dev_err(&adev->dev, "The CLDB buffer is too large\n");
> +		ret = -EINVAL;
> +		goto out_free_buff;
> +	}
> +
> +	memcpy(&cldb, obj->buffer.pointer, obj->buffer.length);
> +
> +	/*
> +	 * control_logic_type = 1 indicates this is a dummy INT3472 device of
> +	 * the kind we're looking for. If any other value then we shouldn't try
> +	 * to handle it
> +	 */
> +	if (cldb.control_logic_type != 1) {
> +		ret = -EINVAL;
> +		goto out_free_buff;
> +	}
> +
> +	/* Space for 4 GPIOs - one more than we've seen so far plus a null */
> +	int3472 = kzalloc(sizeof(*int3472) +
> +			 ((INT3472_MAX_SENSOR_GPIOS + 1) * sizeof(struct gpiod_lookup)),
> +			 GFP_KERNEL);
> +	if (!int3472) {
> +		ret = -ENOMEM;
> +		goto out_free_buff;
> +	}
> +
> +	int3472->adev = adev;
> +	adev->driver_data = int3472;
> +
> +	int3472->sensor = acpi_dev_get_next_dep_dev(adev, NULL);
> +	if (!int3472->sensor) {
> +		dev_err(&adev->dev,
> +			"This INT3472 entry seems to have no dependents.\n");
> +		ret = -ENODEV;
> +		goto out_free_int3472;
> +	}
> +
> +	int3472->gpios.dev_id = i2c_acpi_dev_name(int3472->sensor);
> +
> +	INIT_LIST_HEAD(&int3472->regulators);
> +
> +	int3472_parse_crs(int3472);
> +
> +	goto out_free_buff;
> +
> +out_free_int3472:
> +	kfree(int3472);
> +out_free_buff:
> +	kfree(buffer.pointer);
> +	return ret;
> +}
> +
> +static int int3472_remove(struct acpi_device *adev)
> +{
> +	struct int3472_gpio_regulator *reg;
> +	struct int3472_device *int3472;
> +
> +	int3472 = acpi_driver_data(adev);
> +
> +	acpi_dev_put(int3472->sensor);
> +	gpiod_remove_lookup_table(&int3472->gpios);
> +
> +	list_for_each_entry(reg, &int3472->regulators, list) {
> +		gpiod_put(reg->gpio);
> +		regulator_unregister(reg->rdev);
> +	}
> +
> +	kfree(int3472);
> +
> +	return 0;
> +}
> +
> +static const struct acpi_device_id int3472_device_id[] = {
> +	{ "INT3472", 0 },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(acpi, int3472_device_id);
> +
> +static struct acpi_driver int3472_driver = {
> +	.name = "int3472",
> +	.ids = int3472_device_id,
> +	.ops = {
> +		.add = int3472_add,
> +		.remove = int3472_remove,
> +	},
> +	.owner = THIS_MODULE,
> +};
> +
> +module_acpi_driver(int3472_driver);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Dan Scally <djrscally@gmail.com>");
> +MODULE_DESCRIPTION("ACPI Driver for Discrete type INT3472 ACPI Devices");
> diff --git a/drivers/media/pci/intel/ipu3/int3472.h b/drivers/media/pci/intel/ipu3/int3472.h
> new file mode 100644
> index 000000000000..6964726e8e1f
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu3/int3472.h
> @@ -0,0 +1,96 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Author: Dan Scally <djrscally@gmail.com> */
> +#include <linux/regulator/machine.h>
> +
> +#define INT3472_MAX_SENSOR_GPIOS			3
> +#define GPIO_REGULATOR_NAME_LENGTH			17
> +#define GPIO_REGULATOR_SUPPLY_NAME_LENGTH		9
> +
> +#define INT3472_REGULATOR(_NAME, _SUPPLY, _ID, _OPS)	\
> +	((const struct regulator_desc) {		\
> +		.name = _NAME,				\
> +		.supply_name = _SUPPLY,			\
> +		.id = _ID,				\
> +		.type = REGULATOR_VOLTAGE,		\
> +		.ops = _OPS,				\
> +		.owner = THIS_MODULE,			\
> +	})
> +
> +const guid_t int3472_gpio_guid = GUID_INIT(0x79234640, 0x9e10, 0x4fea,
> +					     0xa5, 0xc1, 0xb5, 0xaa, 0x8b,
> +					     0x19, 0x75, 0x6f);
> +
> +const guid_t cio2_sensor_module_guid = GUID_INIT(0x822ace8f, 0x2814, 0x4174,
> +						 0xa5, 0x6b, 0x5f, 0x02, 0x9f,
> +						 0xe0, 0x79, 0xee);
> +
> +struct int3472_cldb {
> +	u8 version;
> +	/*
> +	 * control logic type
> +	 * 0: UNKNOWN
> +	 * 1: DISCRETE(CRD-D)
> +	 * 2: PMIC TPS68470
> +	 * 3: PMIC uP6641
> +	 */
> +	u8 control_logic_type;
> +	u8 control_logic_id;
> +	u8 sensor_card_sku;
> +	u8 reserved[28];
> +};
> +
> +struct int3472_device {
> +	struct acpi_device *adev;
> +	struct acpi_device *sensor;
> +
> +	unsigned int n_gpios; /* how many GPIOs have we seen */
> +
> +	unsigned int n_regulators;
> +	struct list_head regulators;
> +
> +	unsigned int n_sensor_gpios; /* how many have we mapped to sensor */
> +	struct gpiod_lookup_table gpios;
> +};
> +
> +struct int3472_gpio_regulator {
> +	char regulator_name[GPIO_REGULATOR_NAME_LENGTH];
> +	char supply_name[GPIO_REGULATOR_SUPPLY_NAME_LENGTH];
> +	struct gpio_desc *gpio;
> +	struct regulator_dev *rdev;
> +	struct regulator_desc rdesc;
> +	struct list_head list;
> +};
> +
> +struct int3472_sensor_regulator_map {
> +	char *sensor_module_name;
> +	unsigned int n_supplies;
> +	struct regulator_consumer_supply *supplies;
> +};
> +


I think the data tables below can be moved to the .c file, and also
marked as static const.

> +/*
> + * Here follows platform specific mapping information that we can pass to
> + * regulator_init_data when we register our regulators. They're just mapped
> + * via index, I.E. the first regulator pin that the code finds for the
> + * i2c-OVTI2680:00 device is avdd, the second is dovdd and so on.
> + */
> +
> +static struct regulator_consumer_supply miix_510_ov2680[] = {
> +	{ "i2c-OVTI2680:00", "avdd" },
> +	{ "i2c-OVTI2680:00", "dovdd" },
> +};
> +
> +static struct regulator_consumer_supply surface_go2_ov5693[] = {
> +	{ "i2c-INT33BE:00", "avdd" },
> +	{ "i2c-INT33BE:00", "dovdd" },
> +};
> +
> +static struct regulator_consumer_supply surface_book_ov5693[] = {
> +	{ "i2c-INT33BE:00", "avdd" },
> +	{ "i2c-INT33BE:00", "dovdd" },
> +};

Should we de-duplicate repeated identical entries?

for instance, if we 'know' the surface range all uses the same
configuration, or at least a reduced set of configuration we could point
to a single definition for the each set, rather than a specific one for
each device perhaps?

--
Kieran



> +
> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
> +	{ "GNDF140809R", 2, miix_510_ov2680 },
> +	{ "YHCU", 2, surface_go2_ov5693 },
> +	{ "MSHW0070", 2, surface_book_ov5693 },
> +};
> 


-- 
Regards
--
Kieran

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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-30 13:31 ` [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
@ 2020-11-30 16:45   ` kernel test robot
  2020-11-30 17:09   ` Laurent Pinchart
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 144+ messages in thread
From: kernel test robot @ 2020-11-30 16:45 UTC (permalink / raw)
  To: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel
  Cc: kbuild-all, rjw, lenb, gregkh, mika.westerberg

[-- Attachment #1: Type: text/plain, Size: 2069 bytes --]

Hi Daniel,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on driver-core/driver-core-testing pm/linux-next v5.10-rc6 next-20201130]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Daniel-Scally/Add-functionality-to-ipu3-cio2-driver-allowing-software_node-connections-to-sensors-on-platforms-designed-for-Windows/20201130-214014
base:   git://linuxtv.org/media_tree.git master
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/05cb91d6b6272c4516b21b0ecd23a6ff8d861aae
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Daniel-Scally/Add-functionality-to-ipu3-cio2-driver-allowing-software_node-connections-to-sensors-on-platforms-designed-for-Windows/20201130-214014
        git checkout 05cb91d6b6272c4516b21b0ecd23a6ff8d861aae
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=ia64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/media/pci/intel/ipu3/cio2-bridge.c:213:5: warning: no previous prototype for 'cio2_bridge_init' [-Wmissing-prototypes]
     213 | int cio2_bridge_init(struct pci_dev *cio2)
         |     ^~~~~~~~~~~~~~~~

vim +/cio2_bridge_init +213 drivers/media/pci/intel/ipu3/cio2-bridge.c

   212	
 > 213	int cio2_bridge_init(struct pci_dev *cio2)

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 62745 bytes --]

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

* Re: [PATCH 17/18] gpio: gpiolib-acpi: Export acpi_get_gpiod()
  2020-11-30 13:31 ` [PATCH 17/18] gpio: gpiolib-acpi: Export acpi_get_gpiod() Daniel Scally
@ 2020-11-30 17:02   ` kernel test robot
  2020-11-30 18:04   ` kernel test robot
  2020-11-30 19:20   ` Andy Shevchenko
  2 siblings, 0 replies; 144+ messages in thread
From: kernel test robot @ 2020-11-30 17:02 UTC (permalink / raw)
  To: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel
  Cc: kbuild-all, rjw, lenb, gregkh, mika.westerberg

[-- Attachment #1: Type: text/plain, Size: 11994 bytes --]

Hi Daniel,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on driver-core/driver-core-testing pm/linux-next v5.10-rc6 next-20201130]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Daniel-Scally/Add-functionality-to-ipu3-cio2-driver-allowing-software_node-connections-to-sensors-on-platforms-designed-for-Windows/20201130-214014
base:   git://linuxtv.org/media_tree.git master
config: s390-randconfig-p001-20201130 (attached as .config)
compiler: s390-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/eb1854ac694a8e59c0ea703e46fe2ee7e3118b42
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Daniel-Scally/Add-functionality-to-ipu3-cio2-driver-allowing-software_node-connections-to-sensors-on-platforms-designed-for-Windows/20201130-214014
        git checkout eb1854ac694a8e59c0ea703e46fe2ee7e3118b42
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=s390 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   s390-linux-ld: kernel/sysctl.o: in function `acpi_get_gpiod':
>> sysctl.c:(.text+0x2bb8): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: kernel/irq/irqdomain.o: in function `acpi_get_gpiod':
   irqdomain.c:(.text+0x378): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: kernel/dma/mapping.o: in function `acpi_get_gpiod':
   mapping.c:(.text+0xb0): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/gpio/gpiolib.o: in function `acpi_get_gpiod':
   gpiolib.c:(.text+0x1c00): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/gpio/gpio-pca953x.o: in function `acpi_get_gpiod':
   gpio-pca953x.c:(.text+0x29e0): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/gpio/gpio-pca9570.o: in function `acpi_get_gpiod':
   gpio-pca9570.c:(.text+0x338): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/gpio/gpio-pcf857x.o: in function `acpi_get_gpiod':
   gpio-pcf857x.c:(.text+0xcb0): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/gpio/gpio-tpic2810.o: in function `acpi_get_gpiod':
   gpio-tpic2810.c:(.text+0x418): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/pwm/core.o: in function `acpi_get_gpiod':
   core.c:(.text+0x660): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/pwm/pwm-pca9685.o: in function `acpi_get_gpiod':
   pwm-pca9685.c:(.text+0x10d8): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/dma/dmaengine.o: in function `acpi_get_gpiod':
   dmaengine.c:(.text+0x1f30): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/dma/dw/platform.o: in function `acpi_get_gpiod':
   platform.c:(.text+0x420): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/dma/qcom/hidma.o: in function `acpi_get_gpiod':
   hidma.c:(.text+0x28e8): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/88pg86x.o: in function `acpi_get_gpiod':
   88pg86x.c:(.text+0x198): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/ad5398.o: in function `acpi_get_gpiod':
   ad5398.c:(.text+0x780): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/da9210-regulator.o: in function `acpi_get_gpiod':
   da9210-regulator.c:(.text+0x628): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/isl6271a-regulator.o: in function `acpi_get_gpiod':
   isl6271a-regulator.c:(.text+0x3b8): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/isl9305.o: in function `acpi_get_gpiod':
   isl9305.c:(.text+0x1a0): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/lp872x.o: in function `acpi_get_gpiod':
   lp872x.c:(.text+0x11c0): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/lp8755.o: in function `acpi_get_gpiod':
   lp8755.c:(.text+0x1148): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/ltc3589.o: in function `acpi_get_gpiod':
   ltc3589.c:(.text+0x8c8): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/max8649.o: in function `acpi_get_gpiod':
   max8649.c:(.text+0x7a0): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/max8660.o: in function `acpi_get_gpiod':
   max8660.c:(.text+0xe28): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/max77826-regulator.o: in function `acpi_get_gpiod':
   max77826-regulator.c:(.text+0x230): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/mp8859.o: in function `acpi_get_gpiod':
   mp8859.c:(.text+0x2e0): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/mt6311-regulator.o: in function `acpi_get_gpiod':
   mt6311-regulator.c:(.text+0x248): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/pca9450-regulator.o: in function `acpi_get_gpiod':
   pca9450-regulator.c:(.text+0x790): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/pfuze100-regulator.o: in function `acpi_get_gpiod':
   pfuze100-regulator.c:(.text+0xaa8): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/pv88060-regulator.o: in function `acpi_get_gpiod':
   pv88060-regulator.c:(.text+0x870): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/pv88080-regulator.o: in function `acpi_get_gpiod':
   pv88080-regulator.c:(.text+0xb38): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/pv88090-regulator.o: in function `acpi_get_gpiod':
   pv88090-regulator.c:(.text+0x960): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/rt4801-regulator.o: in function `acpi_get_gpiod':
   rt4801-regulator.c:(.text+0x6a0): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/rtmv20-regulator.o: in function `acpi_get_gpiod':
   rtmv20-regulator.c:(.text+0xb20): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/slg51000-regulator.o: in function `acpi_get_gpiod':
   slg51000-regulator.c:(.text+0xb28): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/tps62360-regulator.o: in function `acpi_get_gpiod':
   tps62360-regulator.c:(.text+0xe68): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/regulator/tps65132-regulator.o: in function `acpi_get_gpiod':
   tps65132-regulator.c:(.text+0x728): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/base/core.o: in function `acpi_get_gpiod':
   core.c:(.text+0x27f8): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/base/platform.o: in function `acpi_get_gpiod':
   platform.c:(.text+0x798): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/base/cpu.o: in function `acpi_get_gpiod':
   cpu.c:(.text+0x8c8): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/base/property.o: in function `acpi_get_gpiod':
   property.c:(.text+0x2f8): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/base/cacheinfo.o: in function `acpi_get_gpiod':
   cacheinfo.c:(.text+0xca8): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/base/regmap/regmap-i2c.o: in function `acpi_get_gpiod':
   regmap-i2c.c:(.text+0xcb0): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/misc/ad525x_dpot-i2c.o: in function `acpi_get_gpiod':
   ad525x_dpot-i2c.c:(.text+0x278): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/misc/bh1770glc.o: in function `acpi_get_gpiod':
   bh1770glc.c:(.text+0x28a8): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/misc/apds990x.o: in function `acpi_get_gpiod':
   apds990x.c:(.text+0x23a8): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/misc/isl29003.o: in function `acpi_get_gpiod':
   isl29003.c:(.text+0xad8): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/misc/isl29020.o: in function `acpi_get_gpiod':
   isl29020.c:(.text+0x5e8): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/misc/tsl2550.o: in function `acpi_get_gpiod':
   tsl2550.c:(.text+0x9d8): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/misc/ds1682.o: in function `acpi_get_gpiod':
   ds1682.c:(.text+0x578): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/misc/hmc6352.o: in function `acpi_get_gpiod':
   hmc6352.c:(.text+0x568): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here
   s390-linux-ld: drivers/misc/eeprom/eeprom.o: in function `acpi_get_gpiod':
   eeprom.c:(.text+0x7a0): multiple definition of `acpi_get_gpiod'; init/main.o:main.c:(.text+0x0): first defined here

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 16049 bytes --]

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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-30 13:31 ` [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
  2020-11-30 16:45   ` kernel test robot
@ 2020-11-30 17:09   ` Laurent Pinchart
  2020-11-30 18:14     ` Andy Shevchenko
  2020-12-01 22:08     ` Dan Scally
  2020-11-30 20:27   ` kernel test robot
  2020-11-30 20:35   ` Sakari Ailus
  3 siblings, 2 replies; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 17:09 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Daniel,

Thank you for the patch.

On Mon, Nov 30, 2020 at 01:31:24PM +0000, Daniel Scally wrote:
> Currently on platforms designed for Windows, connections between CIO2 and
> sensors are not properly defined in DSDT. This patch extends the ipu3-cio2
> driver to compensate by building software_node connections, parsing the
> connection properties from the sensor's SSDB buffer.
> 
> Suggested-by: Jordan Hand <jorhand@linux.microsoft.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes since RFC v3:
> 
> 	- Removed almost all global variables, dynamically allocated
> 	the cio2_bridge structure, plus a bunch of associated changes
> 	like 
> 	- Added a new function to ipu3-cio2-main.c to check for an 
> 	existing fwnode_graph before calling cio2_bridge_init()
> 	- Prefixed cio2_bridge_ to any variables and functions that
> 	lacked it
> 	- Assigned the new fwnode directly to the sensor's ACPI device
> 	fwnode as secondary. This removes the requirement to delay until
> 	the I2C devices are instantiated before ipu3-cio2 can probe, but
> 	it has a side effect, which is that those devices then grab a ref
> 	to the new software_node. This effectively prevents us from
> 	unloading the driver, because we can't free the memory that they
> 	live in whilst the device holds a reference to them. The work
> 	around at the moment is to _not_ unregister the software_nodes
> 	when ipu3-cio2 is unloaded; this becomes a one-time 'patch', that
> 	is simply skipped if the module is reloaded.
> 	- Moved the sensor's SSDB struct to be a member of cio2_sensor
> 	- Replaced ints with unsigned ints where appropriate
> 	- Iterated over all ACPI devices of a matching _HID rather than
> 	just the first to ensure we handle a device with multiple sensors
> 	of the same model.
> 
>  MAINTAINERS                                   |   1 +
>  drivers/media/pci/intel/ipu3/Kconfig          |  18 ++
>  drivers/media/pci/intel/ipu3/Makefile         |   1 +
>  drivers/media/pci/intel/ipu3/cio2-bridge.c    | 260 ++++++++++++++++++
>  drivers/media/pci/intel/ipu3/cio2-bridge.h    | 108 ++++++++
>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  27 ++
>  drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   6 +
>  7 files changed, 421 insertions(+)
>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9702b886d6a4..188559a0a610 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8927,6 +8927,7 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
>  M:	Yong Zhi <yong.zhi@intel.com>
>  M:	Sakari Ailus <sakari.ailus@linux.intel.com>
>  M:	Bingbu Cao <bingbu.cao@intel.com>
> +M:	Dan Scally <djrscally@gmail.com>
>  R:	Tianshu Qiu <tian.shu.qiu@intel.com>
>  L:	linux-media@vger.kernel.org
>  S:	Maintained
> diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
> index 82d7f17e6a02..2b3350d042be 100644
> --- a/drivers/media/pci/intel/ipu3/Kconfig
> +++ b/drivers/media/pci/intel/ipu3/Kconfig
> @@ -16,3 +16,21 @@ config VIDEO_IPU3_CIO2
>  	  Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2
>  	  connected camera.
>  	  The module will be called ipu3-cio2.
> +
> +config CIO2_BRIDGE
> +	bool "IPU3 CIO2 Sensors Bridge"
> +	depends on VIDEO_IPU3_CIO2
> +	help
> +	  This extension provides an API for the ipu3-cio2 driver to create
> +	  connections to cameras that are hidden in SSDB buffer in ACPI. It
> +	  can be used to enable support for cameras in detachable / hybrid
> +	  devices that ship with Windows.
> +
> +	  Say Y here if your device is a detachable / hybrid laptop that comes
> +	  with Windows installed by the OEM, for example:
> +
> +	  	- Microsoft Surface models (except Surface Pro 3)
> +		- The Lenovo Miix line (for example the 510, 520, 710 and 720)
> +		- Dell 7285
> +
> +	  If in doubt, say N here.
> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
> index 429d516452e4..933777e6ea8a 100644
> --- a/drivers/media/pci/intel/ipu3/Makefile
> +++ b/drivers/media/pci/intel/ipu3/Makefile
> @@ -2,3 +2,4 @@
>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
>  
>  ipu3-cio2-y += ipu3-cio2-main.o
> +ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> new file mode 100644
> index 000000000000..fd3f8ba07274
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> @@ -0,0 +1,260 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Author: Dan Scally <djrscally@gmail.com> */

Could you please add a blank line here ?

> +#include <linux/acpi.h>
> +#include <linux/device.h>
> +#include <linux/i2c.h>

Is this header needed ?

> +#include <linux/kernel.h>
> +#include <linux/module.h>

And this one ?

> +#include <linux/pci.h>
> +#include <linux/property.h>
> +#include <media/v4l2-subdev.h>

And this one ?

> +
> +#include "cio2-bridge.h"
> +
> +/*
> + * Extend this array with ACPI Hardware ID's of devices known to be working.
> + * Do not add a HID for a sensor that is not actually supported.
> + */
> +static const char * const cio2_supported_devices[] = {

Maybe cio2_supported_sensors ?

> +	"INT33BE",
> +	"OVTI2680",
> +};
> +
> +static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id,
> +					void *data, u32 size)
> +{
> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> +	union acpi_object *obj;
> +	acpi_status status;
> +	int ret;
> +
> +	status = acpi_evaluate_object(adev->handle, id, NULL, &buffer);
> +	if (ACPI_FAILURE(status))
> +		return -ENODEV;
> +
> +	obj = buffer.pointer;
> +	if (!obj) {
> +		dev_err(&adev->dev, "Couldn't locate ACPI buffer\n");
> +		return -ENODEV;
> +	}
> +
> +	if (obj->type != ACPI_TYPE_BUFFER) {
> +		dev_err(&adev->dev, "Not an ACPI buffer\n");
> +		ret = -ENODEV;
> +		goto out_free_buff;
> +	}
> +
> +	if (obj->buffer.length > size) {
> +		dev_err(&adev->dev, "Given buffer is too small\n");
> +		ret = -EINVAL;
> +		goto out_free_buff;
> +	}
> +
> +	memcpy(data, obj->buffer.pointer, obj->buffer.length);
> +	ret = obj->buffer.length;
> +
> +out_free_buff:
> +	kfree(buffer.pointer);
> +	return ret;
> +}
> +
> +static void cio2_bridge_init_property_names(struct cio2_sensor *sensor)
> +{
> +	strcpy(sensor->prop_names.clock_frequency, "clock-frequency");
> +	strcpy(sensor->prop_names.rotation, "rotation");
> +	strcpy(sensor->prop_names.bus_type, "bus-type");
> +	strcpy(sensor->prop_names.data_lanes, "data-lanes");
> +	strcpy(sensor->prop_names.remote_endpoint, "remote-endpoint");

This is a bit fragile, as there's no len check. How about the following
?
static const struct cio2_property_names prop_names = {
	.clock_frequency = "clock-frequency",
	.rotation = "rotation",
	.bus_type = "bus-type",
	.data_lanes = "data-lanes",
	.remote_endpoint = "remote-endpoint",
};

static void cio2_bridge_init_property_names(struct cio2_sensor *sensor)
{
	sensor->prop_names = prop_names;
}

This shoudl generate a compilation warning if the string is too long.

You could even inline that line in
cio2_bridge_create_fwnode_properties().

> +}
> +
> +static void cio2_bridge_create_fwnode_properties(struct cio2_sensor *sensor)
> +{
> +	unsigned int i;
> +
> +	cio2_bridge_init_property_names(sensor);
> +
> +	for (i = 0; i < 4; i++)
> +		sensor->data_lanes[i] = i + 1;

Is there no provision in the SSDB for data lane remapping ?

> +
> +	/*
> +	 * Can't use PROPERTY_ENTRY_REF because it creates a new variable to
> +	 * point to, which doesn't survive the function.
> +	 */
> +	sensor->local_ref[0] = (struct software_node_ref_args){
> +		.node = &sensor->swnodes[SWNODE_CIO2_ENDPOINT]
> +		};

I'd remove one tab here. Or just write

	sensor->local_ref[0].node = &sensor->swnodes[SWNODE_CIO2_ENDPOINT];

> +	sensor->remote_ref[0] = (struct software_node_ref_args){
> +		.node = &sensor->swnodes[SWNODE_SENSOR_ENDPOINT]
> +		};
> +
> +	sensor->dev_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.clock_frequency,
> +						       sensor->ssdb.mclkspeed);
> +	sensor->dev_properties[1] = PROPERTY_ENTRY_U8(sensor->prop_names.rotation,
> +						      sensor->ssdb.degree);
> +
> +	sensor->ep_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.bus_type, 5);
> +	sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes,
> +								sensor->data_lanes,
> +								sensor->ssdb.lanes);
> +	sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint,
> +							    sensor->local_ref);
> +
> +	sensor->cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes,
> +								  sensor->data_lanes,
> +								  sensor->ssdb.lanes);
> +	sensor->cio2_properties[1] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint,
> +							      sensor->remote_ref);
> +}
> +
> +static void cio2_bridge_init_swnode_names(struct cio2_sensor *sensor)
> +{
> +	snprintf(sensor->node_names.remote_port, 6, "port%u", sensor->ssdb.link);
> +	strcpy(sensor->node_names.port, "port0");
> +	strcpy(sensor->node_names.endpoint, "endpoint0");
> +}
> +
> +static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge,
> +						  struct cio2_sensor *sensor)
> +{
> +	struct software_node *nodes = sensor->swnodes;
> +
> +	cio2_bridge_init_swnode_names(sensor);
> +
> +	nodes[SWNODE_SENSOR_HID] = NODE_SENSOR(sensor->name,
> +					       sensor->dev_properties);
> +	nodes[SWNODE_SENSOR_PORT] = NODE_PORT(sensor->node_names.port,
> +					      &nodes[SWNODE_SENSOR_HID]);
> +	nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint,
> +						      &nodes[SWNODE_SENSOR_PORT],
> +						      sensor->ep_properties);
> +	nodes[SWNODE_CIO2_PORT] = NODE_PORT(sensor->node_names.remote_port,
> +					    &bridge->cio2_hid_node);
> +	nodes[SWNODE_CIO2_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint,
> +						    &nodes[SWNODE_CIO2_PORT],
> +						    sensor->cio2_properties);
> +}
> +
> +static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge)
> +{
> +	struct cio2_sensor *sensor;
> +	unsigned int i;
> +
> +	for (i = 0; i < bridge->n_sensors; i++) {
> +		sensor = &bridge->sensors[i];
> +		software_node_unregister_nodes(sensor->swnodes);
> +		acpi_dev_put(sensor->adev);
> +	}
> +}
> +
> +static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge)
> +{
> +	struct fwnode_handle *fwnode;
> +	struct cio2_sensor *sensor;
> +	struct acpi_device *adev;
> +	unsigned int i;
> +	int ret = 0;
> +
> +	for (i = 0; i < ARRAY_SIZE(cio2_supported_devices); i++) {
> +		const char *this_device = cio2_supported_devices[i];

s/this_device/name/ (or sensor_name, ...) ?

> +
> +		for_each_acpi_dev_match(adev, this_device, NULL, -1) {
> +			if (!adev || !(adev->status.present && adev->status.enabled))

			if (!adev || !adev->status.present || !adev->status.enabled))

may be a bit more readable. Does for_each_acpi_dev_match() return NULL
devices though ? If no, you could drop the !adev check. You may also be
able to drop the !present check, as I don't think ACPI allows !present
&& enabled.

> +				continue;
> +
> +			sensor = &bridge->sensors[bridge->n_sensors];
> +			sensor->adev = adev;
> +			strscpy(sensor->name, this_device, sizeof(sensor->name));
> +
> +			ret = cio2_bridge_read_acpi_buffer(adev, "SSDB",
> +							   &sensor->ssdb,
> +							   sizeof(sensor->ssdb));
> +			if (ret < 0)
> +				goto err_put_adev;
> +
> +			if (sensor->ssdb.lanes > 4) {
> +				dev_err(&adev->dev,
> +					"Number of lanes in SSDB is invalid\n");
> +				goto err_put_adev;
> +			}
> +
> +			cio2_bridge_create_fwnode_properties(sensor);
> +			cio2_bridge_create_connection_swnodes(bridge, sensor);
> +
> +			ret = software_node_register_nodes(sensor->swnodes);
> +			if (ret)
> +				goto err_put_adev;
> +
> +			fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR_HID]);
> +			if (!fwnode) {
> +				ret = -ENODEV;
> +				goto err_free_swnodes;
> +			}
> +
> +			adev->fwnode.secondary = fwnode;
> +
> +			dev_info(&bridge->cio2->dev,
> +				 "Found supported sensor %s\n",
> +				 acpi_dev_name(adev));
> +
> +			bridge->n_sensors++;

We probably want a check here to avoid overflowing bridge->sensors. The
other option is to make bridge->sensors a struct list_head and allocate
sensors dynamically.

> +		}
> +	}
> +
> +	return ret;
> +
> +err_free_swnodes:
> +	software_node_unregister_nodes(sensor->swnodes);
> +err_put_adev:
> +	acpi_dev_put(sensor->adev);
> +
> +	return ret;
> +}
> +
> +int cio2_bridge_init(struct pci_dev *cio2)
> +{
> +	struct device *dev = &cio2->dev;
> +	struct fwnode_handle *fwnode;
> +	struct cio2_bridge *bridge;
> +	int ret;
> +
> +	bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
> +	if (!bridge)
> +		return -ENOMEM;
> +
> +	strscpy(bridge->cio2_node_name, CIO2_HID, sizeof(bridge->cio2_node_name));
> +	bridge->cio2_hid_node = (const struct software_node){ bridge->cio2_node_name };

Maybe just

	bridge->cio2_hid_node.name = bridge->cio2_node_name;

as the rest is already zeroed by the kzalloc() call ?

> +	bridge->cio2 = pci_dev_get(cio2);

As the cio2 pointer is only used to print a message in
cio2_bridge_connect_sensors(), do we need to store it in the bridge
structure, and take a reference to the device ?

> +
> +	ret = software_node_register(&bridge->cio2_hid_node);
> +	if (ret < 0) {
> +		dev_err(dev, "Failed to register the CIO2 HID node\n");
> +		goto err_put_cio2;
> +	}
> +
> +	ret = cio2_bridge_connect_sensors(bridge);
> +	if (ret || bridge->n_sensors == 0)
> +		goto err_unregister_cio2;
> +
> +	dev_info(dev, "Connected %d cameras\n", bridge->n_sensors);
> +
> +	fwnode = software_node_fwnode(&bridge->cio2_hid_node);
> +	if (!fwnode) {
> +		dev_err(dev, "Error getting fwnode from cio2 software_node\n");
> +		ret = -ENODEV;
> +		goto err_unregister_sensors;

Can this happen ?

> +	}
> +
> +	set_secondary_fwnode(dev, fwnode);
> +
> +	return 0;
> +
> +err_unregister_sensors:
> +	cio2_bridge_unregister_sensors(bridge);
> +err_unregister_cio2:
> +	software_node_unregister(&bridge->cio2_hid_node);
> +err_put_cio2:
> +	pci_dev_put(bridge->cio2);
> +
> +	kfree(bridge);
> +	return ret;
> +}
> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h
> new file mode 100644
> index 000000000000..96f5c8a12be0
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h

This file is only included by cio2-bridge.c, so you could inline it
there. Up to you.

> @@ -0,0 +1,108 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Author: Dan Scally <djrscally@gmail.com> */
> +#ifndef __CIO2_BRIDGE_H
> +#define __CIO2_BRIDGE_H
> +
> +#include <linux/property.h>
> +
> +#define CIO2_HID				"INT343E"
> +#define CIO2_NUM_PORTS			  4

There are a few rogue spaces before '4'.

> +
> +#define NODE_SENSOR(_HID, _PROPS)		\
> +	((const struct software_node) {		\
> +		.name = _HID,			\
> +		.properties = _PROPS,		\
> +	})
> +
> +#define NODE_PORT(_PORT, _SENSOR_NODE)		\
> +	((const struct software_node) {		\
> +		_PORT,				\
> +		_SENSOR_NODE,			\
> +	})
> +
> +#define NODE_ENDPOINT(_EP, _PORT, _PROPS)	\
> +	((const struct software_node) {		\
> +		_EP,				\
> +		_PORT,				\
> +		_PROPS,				\
> +	})
> +
> +enum cio2_sensor_swnodes {
> +	SWNODE_SENSOR_HID,
> +	SWNODE_SENSOR_PORT,
> +	SWNODE_SENSOR_ENDPOINT,
> +	SWNODE_CIO2_PORT,
> +	SWNODE_CIO2_ENDPOINT,
> +	NR_OF_SENSOR_SWNODES
> +};
> +
> +/* Data representation as it is in ACPI SSDB buffer */
> +struct cio2_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 cio2_property_names {
> +	char clock_frequency[16];
> +	char rotation[9];
> +	char bus_type[9];
> +	char data_lanes[11];
> +	char remote_endpoint[16];
> +};
> +
> +struct cio2_node_names {
> +	char port[6];
> +	char endpoint[10];
> +	char remote_port[6];
> +};
> +
> +struct cio2_sensor {
> +	char name[ACPI_ID_LEN];
> +	struct acpi_device *adev;
> +
> +	struct software_node swnodes[6];
> +	struct cio2_node_names node_names;
> +
> +	u32 data_lanes[4];
> +	struct cio2_sensor_ssdb ssdb;
> +	struct cio2_property_names prop_names;
> +	struct property_entry ep_properties[4];
> +	struct property_entry dev_properties[3];
> +	struct property_entry cio2_properties[3];
> +	struct software_node_ref_args local_ref[1];
> +	struct software_node_ref_args remote_ref[1];
> +};
> +
> +struct cio2_bridge {
> +	struct pci_dev *cio2;
> +	char cio2_node_name[ACPI_ID_LEN];
> +	struct software_node cio2_hid_node;
> +	unsigned int n_sensors;
> +	struct cio2_sensor sensors[CIO2_NUM_PORTS];
> +};
> +
> +#endif
> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> index 36e354ecf71e..0d69b593e9f0 100644
> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> @@ -1702,6 +1702,22 @@ static void cio2_queues_exit(struct cio2_device *cio2)
>  		cio2_queue_exit(cio2, &cio2->queue[i]);
>  }
>  
> +static bool cio2_check_fwnode_graph(struct fwnode_handle *fwnode)
> +{
> +	struct fwnode_handle *endpoint;
> +
> +	if (IS_ERR_OR_NULL(fwnode))
> +		return false;
> +
> +	endpoint = fwnode_graph_get_next_endpoint(fwnode, NULL);
> +	if (endpoint) {
> +		fwnode_handle_put(endpoint);
> +		return true;
> +	}
> +
> +	return cio2_check_fwnode_graph(fwnode->secondary);

If we have a fwnode->secondary and this check fails there's something
seriously wrong, I wonder if we should print an error message.

Overall this is nice. I think the next version will get my ack :-)

> +}
> +
>  /**************** PCI interface ****************/
>  
>  static int cio2_pci_probe(struct pci_dev *pci_dev,
> @@ -1715,6 +1731,17 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
>  		return -ENOMEM;
>  	cio2->pci_dev = pci_dev;
>  
> +	/*
> +	 * On some platforms no connections to sensors are defined in firmware,
> +	 * if the device has no endpoints then we can try to build those as
> +	 * software_nodes parsed from SSDB.
> +	 */
> +	if (!cio2_check_fwnode_graph(dev_fwnode(&pci_dev->dev))) {
> +		r = cio2_bridge_init(pci_dev);
> +		if (r)
> +			return r;
> +	}
> +
>  	r = pcim_enable_device(pci_dev);
>  	if (r) {
>  		dev_err(&pci_dev->dev, "failed to enable device (%d)\n", r);
> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.h b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
> index ccf0b85ae36f..520a27c9cdad 100644
> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.h
> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
> @@ -437,4 +437,10 @@ static inline struct cio2_queue *vb2q_to_cio2_queue(struct vb2_queue *vq)
>  	return container_of(vq, struct cio2_queue, vbq);
>  }
>  
> +#if IS_ENABLED(CONFIG_CIO2_BRIDGE)
> +int cio2_bridge_init(struct pci_dev *cio2);
> +#else
> +int cio2_bridge_init(struct pci_dev *cio2) { return 0; }
> +#endif
> +
>  #endif

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 15/18] i2c: i2c-core-acpi: Add i2c_acpi_dev_name()
  2020-11-30 13:31 ` [PATCH 15/18] i2c: i2c-core-acpi: Add i2c_acpi_dev_name() Daniel Scally
@ 2020-11-30 17:11   ` Laurent Pinchart
  2020-12-02 22:44     ` Dan Scally
  0 siblings, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 17:11 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Daniel,

Thank you for the patch.

On Mon, Nov 30, 2020 at 01:31:26PM +0000, Daniel Scally wrote:
> Some places in the kernel allow users to map resources to a device
> using device name (for example, gpiod_lookup_table). Currently
> this involves waiting for the i2c_client to have been registered so we
> can use dev_name(&client->dev). Adding this function means that we can
> achieve the same thing without having to wait to the i2c device.
> 
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes since RFC v3:
> 
> 	- Patch introduced
> 
>  drivers/i2c/i2c-core-acpi.c | 14 ++++++++++++++
>  include/linux/i2c.h         |  5 +++++
>  2 files changed, 19 insertions(+)
> 
> diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
> index 37c510d9347a..d3a653eac79e 100644
> --- a/drivers/i2c/i2c-core-acpi.c
> +++ b/drivers/i2c/i2c-core-acpi.c
> @@ -497,6 +497,20 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
>  }
>  EXPORT_SYMBOL_GPL(i2c_acpi_new_device);
>  
> +/**
> + * i2c_acpi_dev_name - Construct i2c device name for devs sourced from ACPI
> + * @adev:     ACPI device to construct the name for
> + *
> + * Prefixes "i2c-" to the ACPI device name, for use in i2c_dev_set_name() and
> + * also anywhere else in the kernel that needs to refer to an i2c device by
> + * name but before they have been instantiated.

The documentation should state that the caller must free the return
value.

> + */
> +char *i2c_acpi_dev_name(struct acpi_device *adev)
> +{
> +	return kasprintf(GFP_KERNEL, "i2c-%s", acpi_dev_name(adev));
> +}
> +EXPORT_SYMBOL_GPL(i2c_acpi_dev_name);
> +
>  #ifdef CONFIG_ACPI_I2C_OPREGION
>  static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
>  		u8 cmd, u8 *data, u8 data_len)
> diff --git a/include/linux/i2c.h b/include/linux/i2c.h
> index 56622658b215..ab0e505b2ca6 100644
> --- a/include/linux/i2c.h
> +++ b/include/linux/i2c.h
> @@ -995,6 +995,7 @@ bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
>  u32 i2c_acpi_find_bus_speed(struct device *dev);
>  struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
>  				       struct i2c_board_info *info);
> +char *i2c_acpi_dev_name(struct acpi_device *adev);
>  struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle);
>  #else
>  static inline bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
> @@ -1011,6 +1012,10 @@ static inline struct i2c_client *i2c_acpi_new_device(struct device *dev,
>  {
>  	return ERR_PTR(-ENODEV);
>  }
> +static inline char *i2c_acpi_dev_name(struct acpi_device *adev)
> +{
> +	return NULL;
> +}
>  static inline struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle)
>  {
>  	return NULL;

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 16/18] i2c: i2c-core-base: Use the new i2c_acpi_dev_name() in i2c_set_dev_name()
  2020-11-30 13:31 ` [PATCH 16/18] i2c: i2c-core-base: Use the new i2c_acpi_dev_name() in i2c_set_dev_name() Daniel Scally
@ 2020-11-30 17:12   ` Laurent Pinchart
  2020-11-30 19:18     ` Andy Shevchenko
  2020-12-01 23:50     ` Dan Scally
  0 siblings, 2 replies; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 17:12 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Daniel,

Thank you for the patch.

On Mon, Nov 30, 2020 at 01:31:27PM +0000, Daniel Scally wrote:
> From: Dan Scally <djrscally@gmail.com>
> 
> To make sure the new i2c_acpi_dev_name() always reflects the name of i2c
> devices sourced from ACPI, use it in i2c_set_dev_name().
> 
> Signed-off-by: Dan Scally <djrscally@gmail.com>

I'd squash this with 15/18, which would make it clear there's a memory
leak :-)

> ---
> Changes since RFC v3:
> 
> 	- Patch introduced
> 
>  drivers/i2c/i2c-core-base.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
> index 573b5da145d1..a6d4ceb01077 100644
> --- a/drivers/i2c/i2c-core-base.c
> +++ b/drivers/i2c/i2c-core-base.c
> @@ -814,7 +814,7 @@ static void i2c_dev_set_name(struct i2c_adapter *adap,
>  	}
>  
>  	if (adev) {
> -		dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev));
> +		dev_set_name(&client->dev, i2c_acpi_dev_name(adev));
>  		return;
>  	}
>  

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 06/18] software_node: amend software_node_unregister_node_group() to perform unregistration of array in reverse order to be consistent with software_node_unregister_nodes()
  2020-11-30 13:31 ` [PATCH 06/18] software_node: amend software_node_unregister_node_group() to perform unregistration of array in reverse order to be consistent with software_node_unregister_nodes() Daniel Scally
  2020-11-30 16:17   ` Laurent Pinchart
@ 2020-11-30 17:19   ` kernel test robot
  2020-12-01 18:18   ` Dan Carpenter
  2 siblings, 0 replies; 144+ messages in thread
From: kernel test robot @ 2020-11-30 17:19 UTC (permalink / raw)
  To: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel
  Cc: kbuild-all, clang-built-linux, rjw, lenb, gregkh, mika.westerberg

[-- Attachment #1: Type: text/plain, Size: 2994 bytes --]

Hi Daniel,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on driver-core/driver-core-testing pm/linux-next v5.10-rc6 next-20201130]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Daniel-Scally/Add-functionality-to-ipu3-cio2-driver-allowing-software_node-connections-to-sensors-on-platforms-designed-for-Windows/20201130-214014
base:   git://linuxtv.org/media_tree.git master
config: powerpc-randconfig-r031-20201130 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project dfcf1acf13226be0f599a7ab6b395b66dc9545d6)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install powerpc cross compiling tool for clang build
        # apt-get install binutils-powerpc-linux-gnu
        # https://github.com/0day-ci/linux/commit/7c7577c82672f0a0775ac1ad85358e2dc17b2c91
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Daniel-Scally/Add-functionality-to-ipu3-cio2-driver-allowing-software_node-connections-to-sensors-on-platforms-designed-for-Windows/20201130-214014
        git checkout 7c7577c82672f0a0775ac1ad85358e2dc17b2c91
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=powerpc 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/base/swnode.c:785:20: warning: variable 'i' is uninitialized when used here [-Wuninitialized]
           while (node_group[i]->name)
                             ^
   drivers/base/swnode.c:780:16: note: initialize the variable 'i' to silence this warning
           unsigned int i;
                         ^
                          = 0
   1 warning generated.

vim +/i +785 drivers/base/swnode.c

   771	
   772	/**
   773	 * software_node_unregister_node_group - Unregister a group of software nodes
   774	 * @node_group: NULL terminated array of software node pointers to be unregistered
   775	 *
   776	 * Unregister multiple software nodes at once.
   777	 */
   778	void software_node_unregister_node_group(const struct software_node **node_group)
   779	{
   780		unsigned int i;
   781	
   782		if (!node_group)
   783			return;
   784	
 > 785		while (node_group[i]->name)
   786			i++;
   787	
   788		while (i--)
   789			software_node_unregister(node_group[i]);
   790	}
   791	EXPORT_SYMBOL_GPL(software_node_unregister_node_group);
   792	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 26623 bytes --]

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 16:29   ` Kieran Bingham
@ 2020-11-30 17:21     ` Laurent Pinchart
  0 siblings, 0 replies; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 17:21 UTC (permalink / raw)
  To: Kieran Bingham
  Cc: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	andriy.shevchenko, linus.walleij, bgolaszewski, wsa, yong.zhi,
	sakari.ailus, bingbu.cao, tian.shu.qiu, mchehab, robert.moore,
	erik.kaneda, pmladek, rostedt, sergey.senozhatsky, linux,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

Hello,

On Mon, Nov 30, 2020 at 04:29:04PM +0000, Kieran Bingham wrote:
> On 30/11/2020 13:31, Daniel Scally wrote:
> > On platforms where ACPI is designed for use with Windows, resources
> > that are intended to be consumed by sensor devices are sometimes in
> > the _CRS of a dummy INT3472 device upon which the sensor depends. This
> > driver binds to the dummy acpi device (which does not represent a
> > physical PMIC) and maps them into GPIO lines and regulators for use by
> > the sensor device instead.
> > 
> > Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > Signed-off-by: Daniel Scally <djrscally@gmail.com>
> > ---
> > Changes since RFC v3:
> > 
> > 	- Patch introduced
> > 
> > This patch contains the bits of this process that we're least sure about.
> > The sensors in scope for this work are called out as dependent (in their
> > DSDT entry's _DEP) on a device with _HID INT3472. These come in at least
> > 2 kinds; those with an I2cSerialBusV2 entry (which we presume therefore
> > are legitimate tps68470 PMICs that need handling by those drivers - work
> > on that in the future). And those without an I2C device. For those without
> > an I2C device they instead have an array of GPIO pins defined in _CRS.

Those are called "discrete regulators", and can also be identified by
the type reported in the CLDB. They're not regulators, just ACPI device
objects that group a set of GPIOs and a referenced from the consumers of
those GPIOs. I'll refrain here from sharing my opinion on the ACPI
design...

> > So
> > for example, my Lenovo Miix 510's OVTI2680 sensor is dependent on one of
> > the _latter_ kind of INT3472 devices, with this _CRS:
> > 
> > Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
> > {
> >     Name (SBUF, ResourceTemplate ()
> >     {
> >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > 	    0x00, ResourceConsumer, ,
> >             )
> >             {   // Pin list
> >                 0x0079
> >             }
> >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > 	    0x00, ResourceConsumer, ,
> >             )
> >             {   // Pin list
> >                 0x007A
> >             }
> >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > 	    0x00, ResourceConsumer, ,
> >             )
> >             {   // Pin list
> >                 0x008F
> >             }
> >     })
> >     Return (SBUF) /* \_SB_.PCI0.PMI1._CRS.SBUF */
> > }
> > 
> > and the same device has a _DSM Method, which returns 32-bit ints where
> > the second lowest byte we noticed to match the pin numbers of the GPIO
> > lines:
> > 
> > Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
> > {
> >     If ((Arg0 == ToUUID ("79234640-9e10-4fea-a5c1-b5aa8b19756f")))
> >     {
> >         If ((Arg2 == One))
> >         {
> >             Return (0x03)
> >         }
> > 
> >         If ((Arg2 == 0x02))
> >         {
> >             Return (0x01007900)
> >         }
> > 
> >         If ((Arg2 == 0x03))
> >         {
> >             Return (0x01007A0C)
> >         }
> > 
> >         If ((Arg2 == 0x04))
> >         {
> >             Return (0x01008F01)
> >         }
> >     }
> > 
> >     Return (Zero)
> > }
> > 
> > We know that at least some of those pins have to be toggled active for the
> > sensor devices to be available in i2c, so the conclusion we came to was
> > that those GPIO entries assigned to the INT3472 device actually represent
> > GPIOs and regulators to be consumed by the sensors themselves. Tsuchiya
> > noticed that the lowest byte in the return values of the _DSM method
> > seemed to represent the type or function of the GPIO line, and we
> > confirmed that by testing on each surface device that GPIO lines where the
> > low byte in the _DSM entry for that pin was 0x0d controlled the privacy
> > LED of the cameras.
> > 
> > We're guessing as to the exact meaning of the function byte, but I
> > conclude they're something like this:
> > 
> > 0x00 - probably a reset GPIO
> > 0x01 - regulator for the sensor

I think 0x01 is probably a power down GPIO.

> > 0x0c - regulator for the sensor
> > 0x0b - regulator again, but for a VCM or EEPROM
> > 0x0d - privacy led (only one we're totally confident of since we can see
> >        it happen!)
> > 
> > After much internal debate I decided to write this as a standalone
> > acpi_driver. Alternative options we considered:
> > 
> > 1. Squash all this into the cio2-bridge code, which I did originally write
> > but decided I didn't like.
> > 2. Extend the existing tps68470 mfd driver...they share an ACPI ID so this
> > kinda makes sense, but ultimately given there is no actual physical
> > tps68470 in the scenario this patch handles I decided I didn't like this
> > either.
> 
> I would agree, keeping this in a unit file on it's own makes sense to me.
> 
> I'm a bit worried about what happens if the tps68470 is also compiled
> in... Does the right device get mapped in the event that there are also
> actual devices already supported by the tps68470 mfd driver on the
> device as well?

That's my main concern here, two drivers for the same device won't play
well together. We'll need to at least teach the tps68470 driver to
ignore the "discrete regulators".

I however believe this would be better handled in the cio2-bridge
driver, given that the ACPI device object doesn't represent an actual
device.

> >  MAINTAINERS                            |   7 +
> >  drivers/media/pci/intel/ipu3/Kconfig   |  14 +
> >  drivers/media/pci/intel/ipu3/Makefile  |   1 +
> >  drivers/media/pci/intel/ipu3/int3472.c | 381 +++++++++++++++++++++++++
> >  drivers/media/pci/intel/ipu3/int3472.h |  96 +++++++
> >  5 files changed, 499 insertions(+)
> >  create mode 100644 drivers/media/pci/intel/ipu3/int3472.c
> >  create mode 100644 drivers/media/pci/intel/ipu3/int3472.h
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 188559a0a610..d73471f9c2a3 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -8753,6 +8753,13 @@ L:	linux-crypto@vger.kernel.org
> >  S:	Maintained
> >  F:	drivers/crypto/inside-secure/
> >  
> > +INT3472 ACPI DEVICE DRIVER
> > +M:	Daniel Scally <djrscally@gmail.com>
> > +L:	linux-media@vger.kernel.org
> > +S:	Maintained
> > +F:	drivers/media/pci/intel/ipu3/int3472.c
> > +F:	drivers/media/pci/intel/ipu3/int3472.h
> > +
> >  INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
> >  M:	Mimi Zohar <zohar@linux.ibm.com>
> >  M:	Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
> > diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
> > index 2b3350d042be..9dd3b280f821 100644
> > --- a/drivers/media/pci/intel/ipu3/Kconfig
> > +++ b/drivers/media/pci/intel/ipu3/Kconfig
> > @@ -34,3 +34,17 @@ config CIO2_BRIDGE
> >  		- Dell 7285
> >  
> >  	  If in doubt, say N here.
> > +
> > +config INT3472
> > +	tristate "INT3472 Dummy ACPI Device Driver"
> > +	depends on VIDEO_IPU3_CIO2
> > +	depends on ACPI && REGULATOR && GPIOLIB
> > +	help
> > +	  This module provides an ACPI driver for INT3472 devices that do not
> > +	  represent an actual physical tps68470 device.
> > +
> > +	  Say Y here if your device is a detachable / hybrid laptop that comes
> > +	  with Windows installed by the OEM.
> > +	  The module will be called int3472.
> > +
> > +	  If in doubt, say N here.
> > diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
> > index 933777e6ea8a..2285947b2bd2 100644
> > --- a/drivers/media/pci/intel/ipu3/Makefile
> > +++ b/drivers/media/pci/intel/ipu3/Makefile
> > @@ -1,5 +1,6 @@
> >  # SPDX-License-Identifier: GPL-2.0-only
> >  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
> > +obj-$(CONFIG_INT3472) += int3472.o
> >  
> >  ipu3-cio2-y += ipu3-cio2-main.o
> >  ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
> > diff --git a/drivers/media/pci/intel/ipu3/int3472.c b/drivers/media/pci/intel/ipu3/int3472.c
> > new file mode 100644
> > index 000000000000..6b0be75f7f35
> > --- /dev/null
> > +++ b/drivers/media/pci/intel/ipu3/int3472.c
> > @@ -0,0 +1,381 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/* Author: Dan Scally <djrscally@gmail.com> */
> > +#include <linux/acpi.h>
> > +#include <linux/gpio/consumer.h>
> > +#include <linux/gpio/machine.h>
> > +#include <linux/i2c.h>
> > +#include <linux/kernel.h>
> > +#include <linux/list.h>
> > +#include <linux/module.h>
> > +#include <linux/regulator/driver.h>
> > +
> > +#include "int3472.h"
> > +
> > +/*
> > + * The regulators have to have .ops to be valid, but the only ops we actually
> > + * support are .enable and .disable which are handled via .ena_gpiod. Pass an
> > + * empty struct to clear the check without lying about capabilities.
> > + */
> > +static const struct regulator_ops int3472_gpio_regulator_ops = { 0 };
> > +
> > +static int int3472_map_gpio_to_sensor(struct int3472_device *int3472,
> > +				      struct acpi_resource *ares, char *func)
> > +{
> > +	char *path = ares->data.gpio.resource_source.string_ptr;
> > +	struct gpiod_lookup table_entry;
> > +	struct acpi_device *adev;
> > +	acpi_handle handle;
> > +	acpi_status status;
> > +	int ret;
> > +
> > +	/* Make sure we don't overflow, and leave room for a terminator */
> > +	if (int3472->n_sensor_gpios >= INT3472_MAX_SENSOR_GPIOS) {
> > +		dev_warn(&int3472->sensor->dev, "Too many GPIOs mapped\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* Fetch ACPI handle for the GPIO chip  */
> > +	status = acpi_get_handle(NULL, path, &handle);
> > +	if (ACPI_FAILURE(status))
> > +		return -EINVAL;
> > +
> > +	ret = acpi_bus_get_device(handle, &adev);
> > +	if (ret)
> > +		return -ENODEV;
> > +
> > +	table_entry = (struct gpiod_lookup)GPIO_LOOKUP_IDX(acpi_dev_name(adev),
> > +							   ares->data.gpio.pin_table[0],
> > +							   func, 0, GPIO_ACTIVE_HIGH);
> > +
> > +	memcpy(&int3472->gpios.table[int3472->n_sensor_gpios], &table_entry,
> > +	       sizeof(table_entry));
> > +	int3472->n_sensor_gpios++;
> > +
> > +	return 0;
> > +}
> > +
> > +static struct int3472_sensor_regulator_map *
> > +int3472_get_sensor_supply_map(struct int3472_device *int3472)
> > +{
> > +	struct int3472_sensor_regulator_map *ret;
> > +	union acpi_object *obj;
> > +	unsigned int i;
> > +
> > +	/*
> > +	 * Sensor modules seem to be identified by a unique string. We use that
> > +	 * to make sure we pass the right device and supply names to the new
> > +	 * regulator's consumer_supplies
> > +	 */
> > +	obj = acpi_evaluate_dsm_typed(int3472->sensor->handle,
> > +				      &cio2_sensor_module_guid, 0x00,
> > +				      0x01, NULL, ACPI_TYPE_STRING);
> > +
> > +	if (!obj) {
> > +		dev_err(&int3472->sensor->dev,
> > +			"Failed to get sensor module string from _DSM\n");
> > +		return ERR_PTR(-ENODEV);
> > +	}
> > +
> > +	if (obj->string.type != ACPI_TYPE_STRING) {
> > +		dev_err(&int3472->sensor->dev,
> > +			"Sensor _DSM returned a non-string value\n");
> > +		ret = ERR_PTR(-EINVAL);
> > +		goto out_free_obj;
> > +	}
> > +
> > +	ret = ERR_PTR(-ENODEV);
> > +	for (i = 0; i < ARRAY_SIZE(int3472_sensor_regulator_maps); i++) {
> > +		if (!strcmp(int3472_sensor_regulator_maps[i].sensor_module_name,
> > +			    obj->string.pointer)) {
> > +			ret = &int3472_sensor_regulator_maps[i];
> > +			goto out_free_obj;
> > +		}
> > +	}
> > +
> > +out_free_obj:
> > +	ACPI_FREE(obj);
> > +	return ret;
> > +}
> > +
> > +static int int3472_register_regulator(struct int3472_device *int3472,
> > +				      struct acpi_resource *ares)
> > +{
> > +	char *path = ares->data.gpio.resource_source.string_ptr;
> > +	struct int3472_sensor_regulator_map *regulator_map;
> > +	struct regulator_init_data init_data = { };
> > +	struct int3472_gpio_regulator *regulator;
> > +	struct regulator_config cfg = { };
> > +	int ret;
> > +
> > +	/*
> > +	 * We lookup supply names from machine specific tables, based on a
> > +	 * unique identifier in the sensor's _DSM
> > +	 */
> > +	regulator_map = int3472_get_sensor_supply_map(int3472);
> > +	if (IS_ERR_OR_NULL(regulator_map)) {
> > +		dev_err(&int3472->sensor->dev,
> > +			"Found no supplies defined for this sensor\n");
> > +		return PTR_ERR(regulator_map);
> > +	}
> > +
> > +	if (int3472->n_regulators >= regulator_map->n_supplies) {
> > +		dev_err(&int3472->sensor->dev,
> > +			"All known supplies are already mapped\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	init_data.supply_regulator = NULL;
> > +	init_data.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
> > +	init_data.num_consumer_supplies = 1;
> > +	init_data.consumer_supplies = &regulator_map->supplies[int3472->n_regulators];
> > +
> > +	regulator = kmalloc(sizeof(*regulator), GFP_KERNEL);
> > +	if (!regulator)
> > +		return -ENOMEM;
> > +
> > +	snprintf(regulator->regulator_name, GPIO_REGULATOR_NAME_LENGTH,
> > +		 "gpio-regulator-%d", int3472->n_regulators);
> > +	snprintf(regulator->supply_name, GPIO_REGULATOR_SUPPLY_NAME_LENGTH,
> > +		 "supply-%d", int3472->n_regulators);
> > +
> > +	regulator->rdesc = INT3472_REGULATOR(regulator->regulator_name,
> > +					     regulator->supply_name,
> > +					     int3472->n_regulators,
> > +					     &int3472_gpio_regulator_ops);
> > +
> > +	regulator->gpio = acpi_get_gpiod(path, ares->data.gpio.pin_table[0]);
> > +	if (IS_ERR(regulator->gpio)) {
> > +		ret = PTR_ERR(regulator->gpio);
> > +		goto err_free_regulator;
> > +	}
> > +
> > +	cfg.dev = &int3472->adev->dev;
> > +	cfg.init_data = &init_data;
> > +	cfg.ena_gpiod = regulator->gpio;
> > +
> > +	regulator->rdev = regulator_register(&regulator->rdesc, &cfg);
> > +	if (IS_ERR(regulator->rdev)) {
> > +		ret = PTR_ERR(regulator->rdev);
> > +		goto err_free_gpio;
> > +	}
> > +
> > +	list_add(&regulator->list, &int3472->regulators);
> > +	int3472->n_regulators++;
> > +
> > +	return 0;
> > +
> > +err_free_gpio:
> > +	gpiod_put(regulator->gpio);
> > +err_free_regulator:
> > +	kfree(regulator);
> > +
> > +	return ret;
> > +}
> > +
> > +static int int3472_handle_gpio_resources(struct acpi_resource *ares,
> > +					 void *data)
> > +{
> > +	struct int3472_device *int3472 = data;
> > +	union acpi_object *obj;
> > +	int ret = 0;
> > +
> > +	if (ares->type != ACPI_RESOURCE_TYPE_GPIO ||
> > +	    ares->data.gpio.connection_type != ACPI_RESOURCE_GPIO_TYPE_IO)
> > +		return EINVAL; /* Deliberately positive */
> > +
> > +	/*
> > +	 * n_gpios + 2 because the index of this _DSM function is 1-based and
> > +	 * the first function is just a count.
> > +	 */
> > +	obj = acpi_evaluate_dsm_typed(int3472->adev->handle,
> > +				      &int3472_gpio_guid, 0x00,
> > +				      int3472->n_gpios + 2,
> > +				      NULL, ACPI_TYPE_INTEGER);
> > +
> > +	if (!obj) {
> > +		dev_warn(&int3472->adev->dev,
> > +			 "No _DSM entry for this GPIO pin\n");
> > +		return ENODEV;
> > +	}
> > +
> > +	switch (obj->integer.value & 0xff) { /* low byte holds type data */
> > +	case 0x00: /* Purpose unclear, possibly a reset GPIO pin */
> > +		ret = int3472_map_gpio_to_sensor(int3472, ares, "reset");
> > +		if (ret)
> > +			dev_warn(&int3472->adev->dev,
> > +				 "Failed to map reset pin to sensor\n");
> > +
> > +		break;
> > +	case 0x01: /* Power regulators (we think) */
> > +	case 0x0c:
> 
> A little annoying that 0x0c is before 0x0b ... but I see this is sharing
> with 0x01, so I think this can stay like this.
> 
> It might be nice to wrap the values in some descriptive #defines though,
> but I'm not sure what we'd call them, and if we're not yet sure on their
> purposes - perhaps the raw values are better for now. We'll see I guess.
> 
> > +		ret = int3472_register_regulator(int3472, ares);
> > +		if (ret)
> > +			dev_warn(&int3472->adev->dev,
> > +				 "Failed to map regulator to sensor\n");
> > +
> > +		break;
> > +	case 0x0b: /* Power regulators, but to a device separate to sensor */
> > +		ret = int3472_register_regulator(int3472, ares);
> > +		if (ret)
> > +			dev_warn(&int3472->adev->dev,
> > +				 "Failed to map regulator to sensor\n");
> > +
> > +		break;
> > +	case 0x0d: /* Indicator LEDs */
> > +		ret = int3472_map_gpio_to_sensor(int3472, ares, "indicator-led");
> > +		if (ret)
> > +			dev_warn(&int3472->adev->dev,
> > +				 "Failed to map indicator led to sensor\n");
> > +
> > +		break;
> > +	default:
> > +		/* if we've gotten here, we're not sure what they are yet */
> > +		dev_warn(&int3472->adev->dev,
> > +			 "GPIO type 0x%llx unknown; the sensor may not work\n",
> > +			 (obj->integer.value & 0xff));
> > +		ret = EINVAL;
> > +	}
> > +
> > +	int3472->n_gpios++;
> > +	ACPI_FREE(obj);
> > +	return abs(ret);
> > +}
> > +
> > +static void int3472_parse_crs(struct int3472_device *int3472)
> > +{
> > +	struct list_head resource_list;
> > +
> > +	INIT_LIST_HEAD(&resource_list);
> > +
> > +	acpi_dev_get_resources(int3472->adev, &resource_list,
> > +			       int3472_handle_gpio_resources, int3472);
> > +
> > +	acpi_dev_free_resource_list(&resource_list);
> > +	gpiod_add_lookup_table(&int3472->gpios);
> > +}
> > +
> > +static int int3472_add(struct acpi_device *adev)
> > +{
> > +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> > +	struct int3472_device *int3472;
> > +	struct int3472_cldb cldb;
> > +	union acpi_object *obj;
> > +	acpi_status status;
> > +	int ret = 0;
> > +
> > +	/*
> > +	 * This driver is only intended to support "dummy" INT3472 devices
> > +	 * which appear in ACPI designed for Windows. These are distinguishable
> > +	 * from INT3472 entries representing an actual tps68470 PMIC through
> > +	 * the presence of a CLDB buffer with a particular value set.
> > +	 */
> > +	status = acpi_evaluate_object(adev->handle, "CLDB", NULL, &buffer);
> > +	if (ACPI_FAILURE(status))
> > +		return -ENODEV;
> > +
> > +	obj = buffer.pointer;
> > +	if (!obj) {
> > +		dev_err(&adev->dev, "ACPI device has no CLDB object\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	if (obj->type != ACPI_TYPE_BUFFER) {
> > +		dev_err(&adev->dev, "CLDB object is not an ACPI buffer\n");
> > +		ret = -EINVAL;
> > +		goto out_free_buff;
> > +	}
> > +
> > +	if (obj->buffer.length > sizeof(cldb)) {
> > +		dev_err(&adev->dev, "The CLDB buffer is too large\n");
> > +		ret = -EINVAL;
> > +		goto out_free_buff;
> > +	}
> > +
> > +	memcpy(&cldb, obj->buffer.pointer, obj->buffer.length);
> > +
> > +	/*
> > +	 * control_logic_type = 1 indicates this is a dummy INT3472 device of
> > +	 * the kind we're looking for. If any other value then we shouldn't try
> > +	 * to handle it
> > +	 */
> > +	if (cldb.control_logic_type != 1) {
> > +		ret = -EINVAL;
> > +		goto out_free_buff;
> > +	}
> > +
> > +	/* Space for 4 GPIOs - one more than we've seen so far plus a null */
> > +	int3472 = kzalloc(sizeof(*int3472) +
> > +			 ((INT3472_MAX_SENSOR_GPIOS + 1) * sizeof(struct gpiod_lookup)),
> > +			 GFP_KERNEL);
> > +	if (!int3472) {
> > +		ret = -ENOMEM;
> > +		goto out_free_buff;
> > +	}
> > +
> > +	int3472->adev = adev;
> > +	adev->driver_data = int3472;
> > +
> > +	int3472->sensor = acpi_dev_get_next_dep_dev(adev, NULL);
> > +	if (!int3472->sensor) {
> > +		dev_err(&adev->dev,
> > +			"This INT3472 entry seems to have no dependents.\n");
> > +		ret = -ENODEV;
> > +		goto out_free_int3472;
> > +	}
> > +
> > +	int3472->gpios.dev_id = i2c_acpi_dev_name(int3472->sensor);
> > +
> > +	INIT_LIST_HEAD(&int3472->regulators);
> > +
> > +	int3472_parse_crs(int3472);
> > +
> > +	goto out_free_buff;
> > +
> > +out_free_int3472:
> > +	kfree(int3472);
> > +out_free_buff:
> > +	kfree(buffer.pointer);
> > +	return ret;
> > +}
> > +
> > +static int int3472_remove(struct acpi_device *adev)
> > +{
> > +	struct int3472_gpio_regulator *reg;
> > +	struct int3472_device *int3472;
> > +
> > +	int3472 = acpi_driver_data(adev);
> > +
> > +	acpi_dev_put(int3472->sensor);
> > +	gpiod_remove_lookup_table(&int3472->gpios);
> > +
> > +	list_for_each_entry(reg, &int3472->regulators, list) {
> > +		gpiod_put(reg->gpio);
> > +		regulator_unregister(reg->rdev);
> > +	}
> > +
> > +	kfree(int3472);
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct acpi_device_id int3472_device_id[] = {
> > +	{ "INT3472", 0 },
> > +	{ },
> > +};
> > +MODULE_DEVICE_TABLE(acpi, int3472_device_id);
> > +
> > +static struct acpi_driver int3472_driver = {
> > +	.name = "int3472",
> > +	.ids = int3472_device_id,
> > +	.ops = {
> > +		.add = int3472_add,
> > +		.remove = int3472_remove,
> > +	},
> > +	.owner = THIS_MODULE,
> > +};
> > +
> > +module_acpi_driver(int3472_driver);
> > +
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_AUTHOR("Dan Scally <djrscally@gmail.com>");
> > +MODULE_DESCRIPTION("ACPI Driver for Discrete type INT3472 ACPI Devices");
> > diff --git a/drivers/media/pci/intel/ipu3/int3472.h b/drivers/media/pci/intel/ipu3/int3472.h
> > new file mode 100644
> > index 000000000000..6964726e8e1f
> > --- /dev/null
> > +++ b/drivers/media/pci/intel/ipu3/int3472.h
> > @@ -0,0 +1,96 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/* Author: Dan Scally <djrscally@gmail.com> */
> > +#include <linux/regulator/machine.h>
> > +
> > +#define INT3472_MAX_SENSOR_GPIOS			3
> > +#define GPIO_REGULATOR_NAME_LENGTH			17
> > +#define GPIO_REGULATOR_SUPPLY_NAME_LENGTH		9
> > +
> > +#define INT3472_REGULATOR(_NAME, _SUPPLY, _ID, _OPS)	\
> > +	((const struct regulator_desc) {		\
> > +		.name = _NAME,				\
> > +		.supply_name = _SUPPLY,			\
> > +		.id = _ID,				\
> > +		.type = REGULATOR_VOLTAGE,		\
> > +		.ops = _OPS,				\
> > +		.owner = THIS_MODULE,			\
> > +	})
> > +
> > +const guid_t int3472_gpio_guid = GUID_INIT(0x79234640, 0x9e10, 0x4fea,
> > +					     0xa5, 0xc1, 0xb5, 0xaa, 0x8b,
> > +					     0x19, 0x75, 0x6f);
> > +
> > +const guid_t cio2_sensor_module_guid = GUID_INIT(0x822ace8f, 0x2814, 0x4174,
> > +						 0xa5, 0x6b, 0x5f, 0x02, 0x9f,
> > +						 0xe0, 0x79, 0xee);
> > +
> > +struct int3472_cldb {
> > +	u8 version;
> > +	/*
> > +	 * control logic type
> > +	 * 0: UNKNOWN
> > +	 * 1: DISCRETE(CRD-D)
> > +	 * 2: PMIC TPS68470
> > +	 * 3: PMIC uP6641
> > +	 */
> > +	u8 control_logic_type;
> > +	u8 control_logic_id;
> > +	u8 sensor_card_sku;
> > +	u8 reserved[28];
> > +};
> > +
> > +struct int3472_device {
> > +	struct acpi_device *adev;
> > +	struct acpi_device *sensor;
> > +
> > +	unsigned int n_gpios; /* how many GPIOs have we seen */
> > +
> > +	unsigned int n_regulators;
> > +	struct list_head regulators;
> > +
> > +	unsigned int n_sensor_gpios; /* how many have we mapped to sensor */
> > +	struct gpiod_lookup_table gpios;
> > +};
> > +
> > +struct int3472_gpio_regulator {
> > +	char regulator_name[GPIO_REGULATOR_NAME_LENGTH];
> > +	char supply_name[GPIO_REGULATOR_SUPPLY_NAME_LENGTH];
> > +	struct gpio_desc *gpio;
> > +	struct regulator_dev *rdev;
> > +	struct regulator_desc rdesc;
> > +	struct list_head list;
> > +};
> > +
> > +struct int3472_sensor_regulator_map {
> > +	char *sensor_module_name;
> > +	unsigned int n_supplies;
> > +	struct regulator_consumer_supply *supplies;
> > +};
> > +
> 
> I think the data tables below can be moved to the .c file, and also
> marked as static const.
> 
> > +/*
> > + * Here follows platform specific mapping information that we can pass to
> > + * regulator_init_data when we register our regulators. They're just mapped
> > + * via index, I.E. the first regulator pin that the code finds for the
> > + * i2c-OVTI2680:00 device is avdd, the second is dovdd and so on.
> > + */
> > +
> > +static struct regulator_consumer_supply miix_510_ov2680[] = {
> > +	{ "i2c-OVTI2680:00", "avdd" },
> > +	{ "i2c-OVTI2680:00", "dovdd" },
> > +};
> > +
> > +static struct regulator_consumer_supply surface_go2_ov5693[] = {
> > +	{ "i2c-INT33BE:00", "avdd" },
> > +	{ "i2c-INT33BE:00", "dovdd" },
> > +};
> > +
> > +static struct regulator_consumer_supply surface_book_ov5693[] = {
> > +	{ "i2c-INT33BE:00", "avdd" },
> > +	{ "i2c-INT33BE:00", "dovdd" },
> > +};
> 
> Should we de-duplicate repeated identical entries?
> 
> for instance, if we 'know' the surface range all uses the same
> configuration, or at least a reduced set of configuration we could point
> to a single definition for the each set, rather than a specific one for
> each device perhaps?
> 
> > +
> > +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
> > +	{ "GNDF140809R", 2, miix_510_ov2680 },
> > +	{ "YHCU", 2, surface_go2_ov5693 },
> > +	{ "MSHW0070", 2, surface_book_ov5693 },
> > +};

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 01/18] property: Return true in fwnode_device_is_available for node types that do not implement this operation
  2020-11-30 13:31 ` [PATCH 01/18] property: Return true in fwnode_device_is_available for node types that do not implement this operation Daniel Scally
  2020-11-30 16:05   ` Laurent Pinchart
@ 2020-11-30 17:21   ` Andy Shevchenko
  2020-12-01  3:12   ` Bingbu Cao
  2 siblings, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 17:21 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus, Laurent Pinchart

On Mon, Nov 30, 2020 at 01:31:12PM +0000, Daniel Scally wrote:
> Some types of fwnode_handle do not implement the device_is_available()
> check, such as those created by software_nodes. There isn't really a
> meaningful way to check for the availability of a device that doesn't
> actually exist, so if the check isn't implemented just assume that the
> "device" is present.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes since RFC v3:
> 
> 	patch introduced
> 
>  drivers/base/property.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/base/property.c b/drivers/base/property.c
> index 4c43d30145c6..a5ca2306796f 100644
> --- a/drivers/base/property.c
> +++ b/drivers/base/property.c
> @@ -785,9 +785,14 @@ EXPORT_SYMBOL_GPL(fwnode_handle_put);
>  /**
>   * fwnode_device_is_available - check if a device is available for use
>   * @fwnode: Pointer to the fwnode of the device.
> + *
> + * For fwnode node types that don't implement the .device_is_available()
> + * operation, this function returns true.
>   */
>  bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
>  {
> +	if (!fwnode_has_op(fwnode, device_is_available))
> +		return true;
>  	return fwnode_call_bool_op(fwnode, device_is_available);
>  }
>  EXPORT_SYMBOL_GPL(fwnode_device_is_available);
> -- 
> 2.25.1
> 

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 02/18] property: Add support for calling fwnode_graph_get_endpoint_by_id() for fwnode->secondary
  2020-11-30 17:29   ` Andy Shevchenko
@ 2020-11-30 17:28     ` Laurent Pinchart
  2020-11-30 17:53       ` Andy Shevchenko
  2020-12-02 10:13     ` Dan Scally
  1 sibling, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 17:28 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Mon, Nov 30, 2020 at 07:29:00PM +0200, Andy Shevchenko wrote:
> On Mon, Nov 30, 2020 at 01:31:13PM +0000, Daniel Scally wrote:
> > This function is used to find fwnode endpoints against a device. In
> > some instances those endpoints are software nodes which are children of
> > fwnode->secondary. Add support to fwnode_graph_get_endpoint_by_id() to
> > find those endpoints by recursively calling itself passing the ptr to
> > fwnode->secondary in the event no endpoint is found for the primary.
> 
> One nit below, after addressing:
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> 
> ...
> 
> > +	if (!best_ep && fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
> > +		return fwnode_graph_get_endpoint_by_id(fwnode->secondary, port,
> > +						       endpoint, flags);
> 
> >  	return best_ep;
> 
> Can we, please, do
> 
> 	if (best_ep)
> 		return best_ep;
> 
> 	if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
> 		return fwnode_graph_get_endpoint_by_id(fwnode->secondary, port,
> 						       endpoint, flags);
> 
> 	return NULL;
> 
> ?
> 
> This 'if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary))' becomes kinda
> idiomatic to the cases when we need to proceed primary followed by the
> secondary in cases where it's not already done.

We could also move the !fwnode check to the beginning of the function.

> >  }
> >  EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_by_id);

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 02/18] property: Add support for calling fwnode_graph_get_endpoint_by_id() for fwnode->secondary
  2020-11-30 13:31 ` [PATCH 02/18] property: Add support for calling fwnode_graph_get_endpoint_by_id() for fwnode->secondary Daniel Scally
  2020-11-30 16:08   ` Laurent Pinchart
@ 2020-11-30 17:29   ` Andy Shevchenko
  2020-11-30 17:28     ` Laurent Pinchart
  2020-12-02 10:13     ` Dan Scally
  1 sibling, 2 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 17:29 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

On Mon, Nov 30, 2020 at 01:31:13PM +0000, Daniel Scally wrote:
> This function is used to find fwnode endpoints against a device. In
> some instances those endpoints are software nodes which are children of
> fwnode->secondary. Add support to fwnode_graph_get_endpoint_by_id() to
> find those endpoints by recursively calling itself passing the ptr to
> fwnode->secondary in the event no endpoint is found for the primary.

One nit below, after addressing:
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

...

> +	if (!best_ep && fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
> +		return fwnode_graph_get_endpoint_by_id(fwnode->secondary, port,
> +						       endpoint, flags);

>  	return best_ep;

Can we, please, do

	if (best_ep)
		return best_ep;

	if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
		return fwnode_graph_get_endpoint_by_id(fwnode->secondary, port,
						       endpoint, flags);

	return NULL;

?

This 'if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary))' becomes kinda
idiomatic to the cases when we need to proceed primary followed by the
secondary in cases where it's not already done.

>  }
>  EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_by_id);

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 03/18] software_node: Fix failure to put() and get() references to children in software_node_get_next_child()
  2020-11-30 13:31 ` [PATCH 03/18] software_node: Fix failure to put() and get() references to children in software_node_get_next_child() Daniel Scally
  2020-11-30 16:10   ` Laurent Pinchart
@ 2020-11-30 17:30   ` Andy Shevchenko
  1 sibling, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 17:30 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

On Mon, Nov 30, 2020 at 01:31:14PM +0000, Daniel Scally wrote:
> The software_node_get_next_child() function currently does not hold
> references to the child software_node that it finds or put the ref that
> is held against the old child - fix that.

Fixes tag and make it first in the series?
In any case,

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes since RFC v3:
> 
> 	Put reference to previous child.
> 
>  drivers/base/swnode.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> index 010828fc785b..615a0c93e116 100644
> --- a/drivers/base/swnode.c
> +++ b/drivers/base/swnode.c
> @@ -443,14 +443,18 @@ software_node_get_next_child(const struct fwnode_handle *fwnode,
>  	struct swnode *c = to_swnode(child);
>  
>  	if (!p || list_empty(&p->children) ||
> -	    (c && list_is_last(&c->entry, &p->children)))
> +	    (c && list_is_last(&c->entry, &p->children))) {
> +		fwnode_handle_put(child);
>  		return NULL;
> +	}
>  
>  	if (c)
>  		c = list_next_entry(c, entry);
>  	else
>  		c = list_first_entry(&p->children, struct swnode, entry);
> -	return &c->fwnode;
> +
> +	fwnode_handle_put(child);
> +	return fwnode_handle_get(&c->fwnode);
>  }
>  
>  static struct fwnode_handle *
> -- 
> 2.25.1
> 

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 04/18] software_node: Enforce parent before child ordering of nodes array for software_node_register_nodes()
  2020-11-30 13:31 ` [PATCH 04/18] software_node: Enforce parent before child ordering of nodes array for software_node_register_nodes() Daniel Scally
  2020-11-30 16:11   ` Laurent Pinchart
@ 2020-11-30 17:35   ` Andy Shevchenko
  2020-11-30 17:37     ` Andy Shevchenko
  1 sibling, 1 reply; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 17:35 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

On Mon, Nov 30, 2020 at 01:31:15PM +0000, Daniel Scally wrote:
> Registering software_nodes with the .parent member set to point to a
> currently unregistered software_node has the potential for problems,
> so enforce parent -> child ordering in arrays passed to this function.

I agree with Laurent.

...

>  	for (i = 0; nodes[i].name; i++) {
> +		if (nodes[i].parent)
> +			if (!software_node_to_swnode(nodes[i].parent)) {
> +				ret = -EINVAL;
> +				goto err_unregister_nodes;
> +			}
> +

Besides that can we pack these conditionals together?

		if (nodes[i].parent && !software_node_to_swnode(nodes[i].parent)) {


Do we have sane ordering in software_node_unregister_nodes()?

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 04/18] software_node: Enforce parent before child ordering of nodes array for software_node_register_nodes()
  2020-11-30 17:35   ` Andy Shevchenko
@ 2020-11-30 17:37     ` Andy Shevchenko
  0 siblings, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 17:37 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

On Mon, Nov 30, 2020 at 07:35:30PM +0200, Andy Shevchenko wrote:
> On Mon, Nov 30, 2020 at 01:31:15PM +0000, Daniel Scally wrote:

...

> >  	for (i = 0; nodes[i].name; i++) {
> > +		if (nodes[i].parent)
> > +			if (!software_node_to_swnode(nodes[i].parent)) {
> > +				ret = -EINVAL;
> > +				goto err_unregister_nodes;
> > +			}
> > +
> 
> Besides that can we pack these conditionals together?
> 
> 		if (nodes[i].parent && !software_node_to_swnode(nodes[i].parent)) {

For being it shorter you may use temporary variable:

		software_node *parent;

		parent = nodes[i].parent;
		if (parent && !software_node_to_swnode(parent)) {

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 05/18] software_node: Alter software_node_unregister_nodes() to unregister the array in reverse order
  2020-11-30 13:31 ` [PATCH 05/18] software_node: Alter software_node_unregister_nodes() to unregister the array in reverse order Daniel Scally
  2020-11-30 16:14   ` Laurent Pinchart
@ 2020-11-30 17:45   ` Andy Shevchenko
  2020-12-01 23:36     ` Dan Scally
  1 sibling, 1 reply; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 17:45 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

On Mon, Nov 30, 2020 at 01:31:16PM +0000, Daniel Scally wrote:
> Software nodes that are children of another software node should be
> unregistered before their parent. To allow easy unregistering of an array
> of software_nodes ordered parent to child, reverse the order in which
> this function unregisters software_nodes.

Should be folded in the previous patch. Otherwise we will have a history point
where register() behaves differently to unregister().

...

> + * @nodes: Zero terminated array of software nodes to be unregistered. If
> + * parent pointers are set up in any of the software nodes then the array
> + * MUST be ordered such that parents come before their children.

Please, leave field description short. Rather add another note to the
Description below.

>   *
>   * Unregister multiple software nodes at once.
>   *
> - * NOTE: Be careful using this call if the nodes had parent pointers set up in
> - * them before registering.  If so, it is wiser to remove the nodes
> - * individually, in the correct order (child before parent) instead of relying
> - * on the sequential order of the list of nodes in the array.
> + * NOTE: If you are uncertain whether the array is ordered such that
> + * parents will be unregistered before their children, it is wiser to
> + * remove the nodes individually, in the correct order (child before
> + * parent).
>   */

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 06/18] software_node: amend software_node_unregister_node_group() to perform unregistration of array in reverse order to be consistent with software_node_unregister_nodes()
  2020-11-30 16:17   ` Laurent Pinchart
@ 2020-11-30 17:47     ` Andy Shevchenko
  2020-12-02 10:04       ` Dan Scally
  0 siblings, 1 reply; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 17:47 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Mon, Nov 30, 2020 at 06:17:16PM +0200, Laurent Pinchart wrote:
> Hi Daniel,
> 
> Thank you for the patch.
> 
> The subject line is very long. We try to keep it within a 72 characters
> limit in the kernel. That can be a challenge sometimes, and expections
> can be accepted, but this one is reaaaally long.
> 
> (The same comment holds for other patches in the series)

+1.

> On Mon, Nov 30, 2020 at 01:31:17PM +0000, Daniel Scally wrote:
> > To maintain consistency with software_node_unregister_nodes(), reverse
> > the order in which the software_node_unregister_node_group() function
> > unregisters nodes.
> > 
> > Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > Signed-off-by: Daniel Scally <djrscally@gmail.com>
> 
> I"d squash this with the previous patch to avoid introducing an
> inconsistency.

It's different to previous. It touches not complementary API, but different
one. However, I would follow your comment about documenting the behaviour of
these two APIs as well…

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 02/18] property: Add support for calling fwnode_graph_get_endpoint_by_id() for fwnode->secondary
  2020-11-30 17:28     ` Laurent Pinchart
@ 2020-11-30 17:53       ` Andy Shevchenko
  2020-11-30 18:41         ` Laurent Pinchart
  0 siblings, 1 reply; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 17:53 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Mon, Nov 30, 2020 at 07:28:57PM +0200, Laurent Pinchart wrote:
> On Mon, Nov 30, 2020 at 07:29:00PM +0200, Andy Shevchenko wrote:
> > On Mon, Nov 30, 2020 at 01:31:13PM +0000, Daniel Scally wrote:

...

> > > +	if (!best_ep && fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
> > > +		return fwnode_graph_get_endpoint_by_id(fwnode->secondary, port,
> > > +						       endpoint, flags);
> > 
> > >  	return best_ep;
> > 
> > Can we, please, do
> > 
> > 	if (best_ep)
> > 		return best_ep;
> > 
> > 	if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
> > 		return fwnode_graph_get_endpoint_by_id(fwnode->secondary, port,
> > 						       endpoint, flags);
> > 
> > 	return NULL;
> > 
> > ?
> > 
> > This 'if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary))' becomes kinda
> > idiomatic to the cases when we need to proceed primary followed by the
> > secondary in cases where it's not already done.
> 
> We could also move the !fwnode check to the beginning of the function.

It's already there (1). What did I miss?

1) via fwnode_graph_get_next_endpoint() -> fwnode_call_ptr_op()

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 11/18] media: v4l2-core: v4l2-async: Check possible match in match_fwnode based on sd->fwnode->secondary
  2020-11-30 13:31 ` [PATCH 11/18] media: v4l2-core: v4l2-async: Check possible match in match_fwnode based on sd->fwnode->secondary Daniel Scally
  2020-11-30 16:27   ` Laurent Pinchart
@ 2020-11-30 17:55   ` Andy Shevchenko
  1 sibling, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 17:55 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

On Mon, Nov 30, 2020 at 01:31:22PM +0000, Daniel Scally wrote:
> Where the fwnode graph is comprised of software_nodes, these will be
> assigned as the secondary to dev->fwnode. Check the v4l2_subdev's fwnode
> for a secondary and attempt to match against it during match_fwnode() to
> accommodate that possibility.

One nit below.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes since RFC v3:
> 
> 	- None
> 
>  drivers/media/v4l2-core/v4l2-async.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
> index e3ab003a6c85..6486dbde784f 100644
> --- a/drivers/media/v4l2-core/v4l2-async.c
> +++ b/drivers/media/v4l2-core/v4l2-async.c
> @@ -87,6 +87,14 @@ static bool match_fwnode(struct v4l2_async_notifier *notifier,
>  	if (sd->fwnode == asd->match.fwnode)
>  		return true;
>  
> +	/*
> +	 * Check the same situation for any possible secondary assigned to the
> +	 * subdev's fwnode
> +	 */

> +	if ((!IS_ERR_OR_NULL(sd->fwnode->secondary)) &&

Too many parentheses.

> +	    sd->fwnode->secondary == asd->match.fwnode)
> +		return true;
> +
>  	/*
>  	 * Otherwise, check if the sd fwnode and the asd fwnode refer to an
>  	 * endpoint or a device. If they're of the same type, there's no match.
> -- 
> 2.25.1
> 

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 12/18] acpi: Add acpi_dev_get_next_match_dev() and macro to iterate through acpi_devices matching a given _HID
  2020-11-30 13:31 ` [PATCH 12/18] acpi: Add acpi_dev_get_next_match_dev() and macro to iterate through acpi_devices matching a given _HID Daniel Scally
@ 2020-11-30 17:58   ` Andy Shevchenko
  0 siblings, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 17:58 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

On Mon, Nov 30, 2020 at 01:31:23PM +0000, Daniel Scally wrote:
> To ensure we handle situations in which multiple sensors of the same
> model (and therefore _HID) are present in a system, we need to be able
> to iterate over devices matching a known _HID but unknown _UID and _HRV
>  - add acpi_dev_get_next_match_dev() to accommodate that possibility and
> change acpi_dev_get_first_match_dev() to simply call the new function
> with a NULL starting point. Add an iterator macro for convenience.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes since RFC v3:
> 
> 	- Patch introduced
> 
>  drivers/acpi/utils.c    | 30 ++++++++++++++++++++++++++----
>  include/acpi/acpi_bus.h |  7 +++++++
>  2 files changed, 33 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
> index d5411a166685..c177165c8db2 100644
> --- a/drivers/acpi/utils.c
> +++ b/drivers/acpi/utils.c
> @@ -843,12 +843,13 @@ bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
>  EXPORT_SYMBOL(acpi_dev_present);
>  
>  /**
> - * acpi_dev_get_first_match_dev - Return the first match of ACPI device
> + * acpi_dev_get_next_match_dev - Return the next match of ACPI device
> + * @adev: Pointer to the previous acpi_device matching this hid, uid and hrv
>   * @hid: Hardware ID of the device.
>   * @uid: Unique ID of the device, pass NULL to not check _UID
>   * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
>   *
> - * Return the first match of ACPI device if a matching device was present
> + * Return the next match of ACPI device if another matching device was present
>   * at the moment of invocation, or NULL otherwise.
>   *
>   * The caller is responsible to call put_device() on the returned device.
> @@ -856,8 +857,9 @@ EXPORT_SYMBOL(acpi_dev_present);
>   * See additional information in acpi_dev_present() as well.
>   */
>  struct acpi_device *
> -acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
> +acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv)
>  {
> +	struct device *start = adev ? &adev->dev : NULL;
>  	struct acpi_dev_match_info match = {};
>  	struct device *dev;
>  
> @@ -865,9 +867,29 @@ acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
>  	match.uid = uid;
>  	match.hrv = hrv;
>  
> -	dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
> +	dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
>  	return dev ? to_acpi_device(dev) : NULL;
>  }
> +EXPORT_SYMBOL(acpi_dev_get_next_match_dev);
> +
> +/**
> + * acpi_dev_get_first_match_dev - Return the first match of ACPI device
> + * @hid: Hardware ID of the device.
> + * @uid: Unique ID of the device, pass NULL to not check _UID
> + * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
> + *
> + * Return the first match of ACPI device if a matching device was present
> + * at the moment of invocation, or NULL otherwise.
> + *
> + * The caller is responsible to call put_device() on the returned device.
> + *
> + * See additional information in acpi_dev_present() as well.
> + */
> +struct acpi_device *
> +acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
> +{
> +	return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
> +}
>  EXPORT_SYMBOL(acpi_dev_get_first_match_dev);
>  
>  /*
> diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
> index a3abcc4b7d9f..0a028ba967d3 100644
> --- a/include/acpi/acpi_bus.h
> +++ b/include/acpi/acpi_bus.h
> @@ -688,9 +688,16 @@ static inline bool acpi_device_can_poweroff(struct acpi_device *adev)
>  
>  bool acpi_dev_hid_uid_match(struct acpi_device *adev, const char *hid2, const char *uid2);
>  
> +struct acpi_device *
> +acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv);
>  struct acpi_device *
>  acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv);
>  
> +#define for_each_acpi_dev_match(adev, hid, uid, hrv)			\
> +	for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv);	\
> +	     adev;							\
> +	     adev = acpi_dev_get_next_match_dev(adev, hid, uid, hrv))
> +
>  static inline void acpi_dev_put(struct acpi_device *adev)
>  {
>  	put_device(&adev->dev);
> -- 
> 2.25.1
> 

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 17/18] gpio: gpiolib-acpi: Export acpi_get_gpiod()
  2020-11-30 13:31 ` [PATCH 17/18] gpio: gpiolib-acpi: Export acpi_get_gpiod() Daniel Scally
  2020-11-30 17:02   ` kernel test robot
@ 2020-11-30 18:04   ` kernel test robot
  2020-11-30 19:20   ` Andy Shevchenko
  2 siblings, 0 replies; 144+ messages in thread
From: kernel test robot @ 2020-11-30 18:04 UTC (permalink / raw)
  To: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel
  Cc: kbuild-all, rjw, lenb, gregkh, mika.westerberg

[-- Attachment #1: Type: text/plain, Size: 29196 bytes --]

Hi Daniel,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linuxtv-media/master]
[also build test ERROR on driver-core/driver-core-testing pm/linux-next v5.10-rc6 next-20201130]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Daniel-Scally/Add-functionality-to-ipu3-cio2-driver-allowing-software_node-connections-to-sensors-on-platforms-designed-for-Windows/20201130-214014
base:   git://linuxtv.org/media_tree.git master
config: ia64-defconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/eb1854ac694a8e59c0ea703e46fe2ee7e3118b42
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Daniel-Scally/Add-functionality-to-ipu3-cio2-driver-allowing-software_node-connections-to-sensors-on-platforms-designed-for-Windows/20201130-214014
        git checkout eb1854ac694a8e59c0ea703e46fe2ee7e3118b42
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=ia64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   ia64-linux-ld: drivers/usb/core/hub.o: in function `acpi_get_gpiod':
>> (.text+0x3060): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
   ia64-linux-ld: drivers/usb/core/hcd.o: in function `acpi_get_gpiod':
   (.text+0x7480): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
   ia64-linux-ld: drivers/usb/core/message.o: in function `acpi_get_gpiod':
   (.text+0x3f20): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
   ia64-linux-ld: drivers/usb/core/driver.o: in function `acpi_get_gpiod':
   (.text+0x1c00): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
   ia64-linux-ld: drivers/usb/core/config.o: in function `acpi_get_gpiod':
   config.c:(.text+0x3420): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
   ia64-linux-ld: drivers/usb/core/file.o: in function `acpi_get_gpiod':
   (.text+0xe00): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
   ia64-linux-ld: drivers/usb/core/sysfs.o: in function `acpi_get_gpiod':
   sysfs.c:(.text+0x28c0): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
   ia64-linux-ld: drivers/usb/core/endpoint.o: in function `acpi_get_gpiod':
   endpoint.c:(.text+0x7a0): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
   ia64-linux-ld: drivers/usb/core/devio.o: in function `acpi_get_gpiod':
   devio.c:(.text+0xcae0): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
   ia64-linux-ld: drivers/usb/core/notify.o: in function `acpi_get_gpiod':
   (.text+0xc0): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
   ia64-linux-ld: drivers/usb/core/generic.o: in function `acpi_get_gpiod':
   (.text+0xa60): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
   ia64-linux-ld: drivers/usb/core/quirks.o: in function `acpi_get_gpiod':
   quirks.c:(.text+0xac0): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
   ia64-linux-ld: drivers/usb/core/devices.o: in function `acpi_get_gpiod':
   devices.c:(.text+0x1ca0): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
   ia64-linux-ld: drivers/usb/core/port.o: in function `acpi_get_gpiod':
   port.c:(.text+0xcc0): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
   ia64-linux-ld: drivers/usb/core/hcd-pci.o: in function `acpi_get_gpiod':
   (.text+0x1240): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
   ia64-linux-ld: drivers/usb/core/usb-acpi.o: in function `acpi_get_gpiod':
   (.text+0x900): multiple definition of `acpi_get_gpiod'; drivers/usb/core/usb.o:(.text+0x2020): first defined here
--
   ia64-linux-ld: drivers/video/fbdev/core/fbmon.o: in function `acpi_get_gpiod':
>> (.text+0x4a0): multiple definition of `acpi_get_gpiod'; drivers/video/fbdev/core/fbmem.o:(.text+0x4b20): first defined here
   ia64-linux-ld: drivers/video/fbdev/core/fbcmap.o: in function `acpi_get_gpiod':
   (.text+0x960): multiple definition of `acpi_get_gpiod'; drivers/video/fbdev/core/fbmem.o:(.text+0x4b20): first defined here
   ia64-linux-ld: drivers/video/fbdev/core/fbsysfs.o: in function `acpi_get_gpiod':
   (.text+0x1400): multiple definition of `acpi_get_gpiod'; drivers/video/fbdev/core/fbmem.o:(.text+0x4b20): first defined here
   ia64-linux-ld: drivers/video/fbdev/core/modedb.o: in function `acpi_get_gpiod':
   (.text+0x22e0): multiple definition of `acpi_get_gpiod'; drivers/video/fbdev/core/fbmem.o:(.text+0x4b20): first defined here
   ia64-linux-ld: drivers/video/fbdev/core/fbcvt.o: in function `acpi_get_gpiod':
   fbcvt.c:(.text+0x0): multiple definition of `acpi_get_gpiod'; drivers/video/fbdev/core/fbmem.o:(.text+0x4b20): first defined here
   ia64-linux-ld: drivers/video/fbdev/core/fb_defio.o: in function `acpi_get_gpiod':
   (.text+0xf40): multiple definition of `acpi_get_gpiod'; drivers/video/fbdev/core/fbmem.o:(.text+0x4b20): first defined here
   ia64-linux-ld: drivers/video/fbdev/core/fbcon.o: in function `acpi_get_gpiod':
   (.text+0xcfa0): multiple definition of `acpi_get_gpiod'; drivers/video/fbdev/core/fbmem.o:(.text+0x4b20): first defined here
   ia64-linux-ld: drivers/video/fbdev/core/bitblit.o: in function `acpi_get_gpiod':
   (.text+0x29a0): multiple definition of `acpi_get_gpiod'; drivers/video/fbdev/core/fbmem.o:(.text+0x4b20): first defined here
   ia64-linux-ld: drivers/video/fbdev/core/softcursor.o: in function `acpi_get_gpiod':
   (.text+0x800): multiple definition of `acpi_get_gpiod'; drivers/video/fbdev/core/fbmem.o:(.text+0x4b20): first defined here
--
   ia64-linux-ld: drivers/acpi/processor_idle.o: in function `acpi_get_gpiod':
>> processor_idle.c:(.text+0x3000): multiple definition of `acpi_get_gpiod'; drivers/acpi/processor_driver.o:processor_driver.c:(.text+0xd20): first defined here
   ia64-linux-ld: drivers/acpi/processor_throttling.o: in function `acpi_get_gpiod':
   processor_throttling.c:(.text+0x27e0): multiple definition of `acpi_get_gpiod'; drivers/acpi/processor_driver.o:processor_driver.c:(.text+0xd20): first defined here
   ia64-linux-ld: drivers/acpi/processor_thermal.o: in function `acpi_get_gpiod':
   processor_thermal.c:(.text+0x2c0): multiple definition of `acpi_get_gpiod'; drivers/acpi/processor_driver.o:processor_driver.c:(.text+0xd20): first defined here
--
   ia64-linux-ld: drivers/gpu/drm/drm_crtc_helper.o: in function `acpi_get_gpiod':
>> (.text+0x22e0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_dp_helper.o: in function `acpi_get_gpiod':
   (.text+0x5460): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_dsc.o: in function `acpi_get_gpiod':
   (.text+0x1220): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_probe_helper.o: in function `acpi_get_gpiod':
   (.text+0x1340): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_plane_helper.o: in function `acpi_get_gpiod':
   (.text+0x920): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_dp_mst_topology.o: in function `acpi_get_gpiod':
   (.text+0xaa60): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_atomic_helper.o: in function `acpi_get_gpiod':
   (.text+0xed00): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_kms_helper_common.o: in function `acpi_get_gpiod':
   drm_kms_helper_common.c:(.text+0x0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_dp_dual_mode_helper.o: in function `acpi_get_gpiod':
   (.text+0x1280): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_simple_kms_helper.o: in function `acpi_get_gpiod':
   (.text+0xb60): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_modeset_helper.o: in function `acpi_get_gpiod':
   (.text+0x8a0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_scdc_helper.o: in function `acpi_get_gpiod':
   (.text+0x620): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_gem_framebuffer_helper.o: in function `acpi_get_gpiod':
   (.text+0x11c0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_atomic_state_helper.o: in function `acpi_get_gpiod':
   (.text+0x1b80): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_damage_helper.o: in function `acpi_get_gpiod':
   (.text+0x1380): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_self_refresh_helper.o: in function `acpi_get_gpiod':
   (.text+0xc00): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/bridge/panel.o: in function `acpi_get_gpiod':
   (.text+0xa20): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_fb_helper.o: in function `acpi_get_gpiod':
   (.text+0x7d80): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_bridge_connector.o:(.text+0xb80): first defined here
--
   ia64-linux-ld: drivers/gpu/drm/drm_ioctl.o: in function `acpi_get_gpiod':
>> (.text+0x2540): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_drv.o: in function `acpi_get_gpiod':
   (.text+0x2940): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_sysfs.o: in function `acpi_get_gpiod':
   (.text+0xe40): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_crtc.o: in function `acpi_get_gpiod':
   (.text+0x1340): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_modes.o: in function `acpi_get_gpiod':
   (.text+0x4f60): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_edid.o: in function `acpi_get_gpiod':
   (.text+0xa7a0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_encoder_slave.o: in function `acpi_get_gpiod':
   (.text+0x760): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_modeset_lock.o: in function `acpi_get_gpiod':
   (.text+0x1a40): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_atomic.o: in function `acpi_get_gpiod':
   (.text+0x63c0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_bridge.o: in function `acpi_get_gpiod':
   (.text+0x2940): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_framebuffer.o: in function `acpi_get_gpiod':
   (.text+0x1260): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_connector.o: in function `acpi_get_gpiod':
   (.text+0x48a0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_blend.o: in function `acpi_get_gpiod':
   (.text+0x1100): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_encoder.o: in function `acpi_get_gpiod':
   (.text+0x520): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_mode_object.o: in function `acpi_get_gpiod':
   (.text+0xb20): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_property.o: in function `acpi_get_gpiod':
   (.text+0x17a0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_plane.o: in function `acpi_get_gpiod':
   (.text+0x1680): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_color_mgmt.o: in function `acpi_get_gpiod':
   (.text+0xb00): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_mode_config.o: in function `acpi_get_gpiod':
   (.text+0x1760): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_vblank.o: in function `acpi_get_gpiod':
   (.text+0x40c0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_lease.o: in function `acpi_get_gpiod':
   drm_lease.c:(.text+0x9a0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_writeback.o: in function `acpi_get_gpiod':
   (.text+0xec0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_client.o: in function `acpi_get_gpiod':
   (.text+0x1200): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_client_modeset.o: in function `acpi_get_gpiod':
   (.text+0x52a0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_atomic_uapi.o: in function `acpi_get_gpiod':
   (.text+0x1120): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_vblank_work.o: in function `acpi_get_gpiod':
   (.text+0xb20): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
   ia64-linux-ld: drivers/gpu/drm/drm_panel.o: in function `acpi_get_gpiod':
   (.text+0xa40): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/drm_file.o:(.text+0x19c0): first defined here
--
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_device.o: in function `acpi_get_gpiod':
>> radeon_device.c:(.text+0xe00): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_asic.o: in function `acpi_get_gpiod':
   radeon_asic.c:(.text+0x140): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_kms.o: in function `acpi_get_gpiod':
   radeon_kms.c:(.text+0x1d80): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_atombios.o: in function `acpi_get_gpiod':
   radeon_atombios.c:(.text+0x19c0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_agp.o: in function `acpi_get_gpiod':
   radeon_agp.c:(.text+0x0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/atombios_crtc.o: in function `acpi_get_gpiod':
   atombios_crtc.c:(.text+0xb200): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_combios.o: in function `acpi_get_gpiod':
   radeon_combios.c:(.text+0x2320): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/atom.o: in function `acpi_get_gpiod':
   atom.c:(.text+0xb440): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_fence.o: in function `acpi_get_gpiod':
   radeon_fence.c:(.text+0x1740): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_ttm.o: in function `acpi_get_gpiod':
   radeon_ttm.c:(.text+0x2d20): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_object.o: in function `acpi_get_gpiod':
   radeon_object.c:(.text+0x5a0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_gart.o: in function `acpi_get_gpiod':
   radeon_gart.c:(.text+0x0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_legacy_crtc.o: in function `acpi_get_gpiod':
   radeon_legacy_crtc.c:(.text+0x3440): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_legacy_encoders.o: in function `acpi_get_gpiod':
   radeon_legacy_encoders.c:(.text+0x7760): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_connectors.o: in function `acpi_get_gpiod':
   radeon_connectors.c:(.text+0x6380): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_encoders.o: in function `acpi_get_gpiod':
   radeon_encoders.c:(.text+0x0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_display.o: in function `acpi_get_gpiod':
   radeon_display.c:(.text+0x4580): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_cursor.o: in function `acpi_get_gpiod':
   radeon_cursor.c:(.text+0x1a80): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_i2c.o: in function `acpi_get_gpiod':
   radeon_i2c.c:(.text+0x6060): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_clocks.o: in function `acpi_get_gpiod':
   radeon_clocks.c:(.text+0x0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_fb.o: in function `acpi_get_gpiod':
   radeon_fb.c:(.text+0x360): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_gem.o: in function `acpi_get_gpiod':
   radeon_gem.c:(.text+0x60): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_ring.o: in function `acpi_get_gpiod':
   radeon_ring.c:(.text+0x0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_irq_kms.o: in function `acpi_get_gpiod':
   radeon_irq_kms.c:(.text+0x1e0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_cs.o: in function `acpi_get_gpiod':
   radeon_cs.c:(.text+0x2080): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_bios.o: in function `acpi_get_gpiod':
   radeon_bios.c:(.text+0x420): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_benchmark.o: in function `acpi_get_gpiod':
   radeon_benchmark.c:(.text+0xf80): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/r100.o: in function `acpi_get_gpiod':
   r100.c:(.text+0x1640): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/r300.o: in function `acpi_get_gpiod':
   r300.c:(.text+0x2b00): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/r420.o: in function `acpi_get_gpiod':
   r420.c:(.text+0x1e0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/rs400.o: in function `acpi_get_gpiod':
   rs400.c:(.text+0x0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/rs600.o: in function `acpi_get_gpiod':
   rs600.c:(.text+0x320): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/rs690.o: in function `acpi_get_gpiod':
   rs690.c:(.text+0x1400): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/rv515.o: in function `acpi_get_gpiod':
   rv515.c:(.text+0x1180): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/r520.o: in function `acpi_get_gpiod':
   r520.c:(.text+0x0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/r600.o: in function `acpi_get_gpiod':
   r600.c:(.text+0x26a0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/rv770.o: in function `acpi_get_gpiod':
   rv770.c:(.text+0x3500): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_test.o: in function `acpi_get_gpiod':
   radeon_test.c:(.text+0x1a20): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/r200.o: in function `acpi_get_gpiod':
   r200.c:(.text+0x0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_legacy_tv.o: in function `acpi_get_gpiod':
   radeon_legacy_tv.c:(.text+0x600): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/r600_cs.o: in function `acpi_get_gpiod':
   r600_cs.c:(.text+0x4bc0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_pm.o: in function `acpi_get_gpiod':
   radeon_pm.c:(.text+0x4660): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/atombios_dp.o: in function `acpi_get_gpiod':
   atombios_dp.c:(.text+0x13a0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/r600_hdmi.o: in function `acpi_get_gpiod':
   r600_hdmi.c:(.text+0x4a0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/dce3_1_afmt.o: in function `acpi_get_gpiod':
   dce3_1_afmt.c:(.text+0x0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/evergreen.o: in function `acpi_get_gpiod':
   evergreen.c:(.text+0x99a0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/evergreen_cs.o: in function `acpi_get_gpiod':
   evergreen_cs.c:(.text+0xe240): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/evergreen_hdmi.o: in function `acpi_get_gpiod':
   evergreen_hdmi.c:(.text+0x0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/radeon_trace_points.o: in function `acpi_get_gpiod':
   radeon_trace_points.c:(.text+0x0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/ni.o: in function `acpi_get_gpiod':
   ni.c:(.text+0x85c0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here
   ia64-linux-ld: drivers/gpu/drm/radeon/atombios_encoders.o: in function `acpi_get_gpiod':
   atombios_encoders.c:(.text+0x18e0): multiple definition of `acpi_get_gpiod'; drivers/gpu/drm/radeon/radeon_drv.o:radeon_drv.c:(.text+0xb80): first defined here

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 19934 bytes --]

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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-30 17:09   ` Laurent Pinchart
@ 2020-11-30 18:14     ` Andy Shevchenko
  2020-12-01 22:08     ` Dan Scally
  1 sibling, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 18:14 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Mon, Nov 30, 2020 at 07:09:55PM +0200, Laurent Pinchart wrote:
> On Mon, Nov 30, 2020 at 01:31:24PM +0000, Daniel Scally wrote:

I agree with most of Laurent's comments. S

...

> > +	  Say Y here if your device is a detachable / hybrid laptop that comes
> > +	  with Windows installed by the OEM, for example:
> > +

> > +	  	- Microsoft Surface models (except Surface Pro 3)

In this line mixed TABs and spaces. Not sure if it's only in Laurent's reply.

> > +		- The Lenovo Miix line (for example the 510, 520, 710 and 720)
> > +		- Dell 7285

...

> > +	for (i = 0; i < ARRAY_SIZE(cio2_supported_devices); i++) {
> > +		const char *this_device = cio2_supported_devices[i];
> 
> s/this_device/name/ (or sensor_name, ...) ?

I would go with hid.

...

> > +		for_each_acpi_dev_match(adev, this_device, NULL, -1) {
> > +			if (!adev || !(adev->status.present && adev->status.enabled))
> 
> 			if (!adev || !adev->status.present || !adev->status.enabled))
> 
> may be a bit more readable. Does for_each_acpi_dev_match() return NULL
> devices though ? If no, you could drop the !adev check. You may also be
> able to drop the !present check, as I don't think ACPI allows !present
> && enabled.

I think this should be rather

        if (acpi_bus_get_status(adev) || !adev->status.present)

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 14/18] acpi: utils: Add function to fetch dependent acpi_devices
  2020-11-30 13:31 ` [PATCH 14/18] acpi: utils: Add function to fetch dependent acpi_devices Daniel Scally
@ 2020-11-30 18:23   ` Andy Shevchenko
  2020-11-30 18:40     ` Laurent Pinchart
  2020-11-30 23:54     ` Dan Scally
  0 siblings, 2 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 18:23 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

On Mon, Nov 30, 2020 at 01:31:25PM +0000, Daniel Scally wrote:
> ACPI devices declare themselves dependent on other devices via the _DEP
> buffer. Fetching the dependee from dependent is a matter of parsing
> _DEP, but currently there's no method to fetch dependent from dependee.
> Add one, so we can parse sensors dependent on a PMIC from the PMIC's
> acpi_driver.

Do I understand correctly that it's an existing table provided by firmware that
(ab)uses _DEP in such way? Note, the specification doesn't tell we may use it
in this way, OTOH I don't remember if it strictly forbids such use.

So, please elaborate in the commit message why you need this and pint out to
the 6.5.8 "_DEP (Operation Region Dependencies)" which clearly says about
OpRegions and that part already supported by ACPI in the Linux, if I'm not
mistaken, need to refresh my memory.

...

> +	handle = adev->handle;
> +
> +	if (!acpi_has_method(handle, "_DEP"))
> +		return 0;
> +
> +	status = acpi_evaluate_reference(handle, "_DEP", NULL, &dep_handles);
> +	if (ACPI_FAILURE(status))
> +		return 0;
> +
> +	for (i = 0; i < dep_handles.count; i++) {
> +		struct acpi_device_info *info;
> +
> +		status = acpi_get_object_info(dep_handles.handles[i], &info);
> +		if (ACPI_FAILURE(status))
> +			continue;
> +
> +		if (info->valid & ACPI_VALID_HID) {
> +			ret = acpi_bus_get_device(dep_handles.handles[i], &candidate);
> +			if (ret || !candidate) {
> +				kfree(info);
> +				continue;
> +			}
> +
> +			if (candidate == dependee) {
> +				acpi_dev_put(candidate);
> +				kfree(info);
> +				return 1;
> +			}
> +
> +			kfree(info);
> +		}
> +	}

Can you utilize (by moving to here and export for ACPI layer the
acpi_lpss_dep()?

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 14/18] acpi: utils: Add function to fetch dependent acpi_devices
  2020-11-30 18:23   ` Andy Shevchenko
@ 2020-11-30 18:40     ` Laurent Pinchart
  2020-11-30 23:54     ` Dan Scally
  1 sibling, 0 replies; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 18:40 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Andy,

On Mon, Nov 30, 2020 at 08:23:54PM +0200, Andy Shevchenko wrote:
> On Mon, Nov 30, 2020 at 01:31:25PM +0000, Daniel Scally wrote:
> > ACPI devices declare themselves dependent on other devices via the _DEP
> > buffer. Fetching the dependee from dependent is a matter of parsing
> > _DEP, but currently there's no method to fetch dependent from dependee.
> > Add one, so we can parse sensors dependent on a PMIC from the PMIC's
> > acpi_driver.
> 
> Do I understand correctly that it's an existing table provided by firmware that
> (ab)uses _DEP in such way? Note, the specification doesn't tell we may use it
> in this way, OTOH I don't remember if it strictly forbids such use.

The ACPI "bindings" (I come from the DT world, is there a standard term
to describe this in ACPI ?) for the camera in Windows-based Kaby Lake
machines could be used as textbook examples of how to abuse ACPI, in
many different ways :-) I'm sure that applies to ACPI in general
though...

Depending on the device, camera sensors are controlled by a PMIC that
provides regulators, clocks and GPIOs (for the reset and power down
signals), or directly by GPIOs that control discrete regulators and
sensor signals. In the first case an INT3472 device models the
regulator, which can be a TI TPS68470 or a uPI Semi uP6641Q (two
completely different devices with a single HID...). The device model is
specified in the CLDB, a custom data table for INT3472.

In the latter case, Intel has created ACPI bindings for a "discrete
PMIC". It uses an ACPI device object with HID set to INT3472 as well,
also with a CLDB whose type field indicate the PMIC is "discrete". The
ACPI device is only used to reference up to 4 GPIOs (provided by the
Kaby Lake GPIO controller, the LPSS) in the _CRS. There's also a _DSM
that reports, for each GPIO, its function. All this information should
have been stored in the camera sensor ACPI device object, but that would
have been too simple...

In both cases, the PMIC device object is referenced by the _DEP data. We
need to access it to dig up the GPIOs, look up their type, and register
fixed regulators, supply mappings and GPIO mappings for the sensor.

> So, please elaborate in the commit message why you need this and pint out to
> the 6.5.8 "_DEP (Operation Region Dependencies)" which clearly says about
> OpRegions and that part already supported by ACPI in the Linux, if I'm not
> mistaken, need to refresh my memory.
> 
> ...
> 
> > +	handle = adev->handle;
> > +
> > +	if (!acpi_has_method(handle, "_DEP"))
> > +		return 0;
> > +
> > +	status = acpi_evaluate_reference(handle, "_DEP", NULL, &dep_handles);
> > +	if (ACPI_FAILURE(status))
> > +		return 0;
> > +
> > +	for (i = 0; i < dep_handles.count; i++) {
> > +		struct acpi_device_info *info;
> > +
> > +		status = acpi_get_object_info(dep_handles.handles[i], &info);
> > +		if (ACPI_FAILURE(status))
> > +			continue;
> > +
> > +		if (info->valid & ACPI_VALID_HID) {
> > +			ret = acpi_bus_get_device(dep_handles.handles[i], &candidate);
> > +			if (ret || !candidate) {
> > +				kfree(info);
> > +				continue;
> > +			}
> > +
> > +			if (candidate == dependee) {
> > +				acpi_dev_put(candidate);
> > +				kfree(info);
> > +				return 1;
> > +			}
> > +
> > +			kfree(info);
> > +		}
> > +	}
> 
> Can you utilize (by moving to here and export for ACPI layer the
> acpi_lpss_dep()?

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 02/18] property: Add support for calling fwnode_graph_get_endpoint_by_id() for fwnode->secondary
  2020-11-30 17:53       ` Andy Shevchenko
@ 2020-11-30 18:41         ` Laurent Pinchart
  2020-11-30 19:21           ` Andy Shevchenko
  0 siblings, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 18:41 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Andy,

On Mon, Nov 30, 2020 at 07:53:19PM +0200, Andy Shevchenko wrote:
> On Mon, Nov 30, 2020 at 07:28:57PM +0200, Laurent Pinchart wrote:
> > On Mon, Nov 30, 2020 at 07:29:00PM +0200, Andy Shevchenko wrote:
> > > On Mon, Nov 30, 2020 at 01:31:13PM +0000, Daniel Scally wrote:
> 
> ...
> 
> > > > +	if (!best_ep && fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
> > > > +		return fwnode_graph_get_endpoint_by_id(fwnode->secondary, port,
> > > > +						       endpoint, flags);
> > > 
> > > >  	return best_ep;
> > > 
> > > Can we, please, do
> > > 
> > > 	if (best_ep)
> > > 		return best_ep;
> > > 
> > > 	if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
> > > 		return fwnode_graph_get_endpoint_by_id(fwnode->secondary, port,
> > > 						       endpoint, flags);
> > > 
> > > 	return NULL;
> > > 
> > > ?
> > > 
> > > This 'if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary))' becomes kinda
> > > idiomatic to the cases when we need to proceed primary followed by the
> > > secondary in cases where it's not already done.
> > 
> > We could also move the !fwnode check to the beginning of the function.
> 
> It's already there (1). What did I miss?

It is, but as we need an explicitly check at the end, it feels cleaner
to move it to the beginning. No big deal though.

> 1) via fwnode_graph_get_next_endpoint() -> fwnode_call_ptr_op()

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 16/18] i2c: i2c-core-base: Use the new i2c_acpi_dev_name() in i2c_set_dev_name()
  2020-11-30 17:12   ` Laurent Pinchart
@ 2020-11-30 19:18     ` Andy Shevchenko
  2020-12-02  9:35       ` Andy Shevchenko
  2020-12-01 23:50     ` Dan Scally
  1 sibling, 1 reply; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 19:18 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Mon, Nov 30, 2020 at 07:12:41PM +0200, Laurent Pinchart wrote:
> On Mon, Nov 30, 2020 at 01:31:27PM +0000, Daniel Scally wrote:
> > From: Dan Scally <djrscally@gmail.com>
> > 
> > To make sure the new i2c_acpi_dev_name() always reflects the name of i2c
> > devices sourced from ACPI, use it in i2c_set_dev_name().
> > 
> > Signed-off-by: Dan Scally <djrscally@gmail.com>
> 
> I'd squash this with 15/18, which would make it clear there's a memory
> leak :-)

...

> >  	if (adev) {
> > -		dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev));
> > +		dev_set_name(&client->dev, i2c_acpi_dev_name(adev));
> >  		return;

But you split pattern used in i2c_dev_set_name().
What you need is to provide something like this

#define I2C_DEV_NAME_FORMAT	"i2c-%s"

const char *i2c_acpi_get_dev_name(...)
{
	return kasprintf(..., I2C_DEV_NAME_FORMAT, ...);
}

(Possible in the future if anybody needs
  const char *i2c_dev_get_name_by_bus_and_addr(int bus, unsigned short addr)
)

And here

-		dev_set_name(&client->dev, "i2c-%s", info->dev_name);
+		dev_set_name(&client->dev, I2C_DEV_NAME_FORMAT, info->dev_name);

-		dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev));
+		dev_set_name(&client->dev, I2C_DEV_NAME_FORMAT, acpi_dev_name(adev));

-- 
With Best Regards,
Andy Shevchenko;



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

* Re: [PATCH 17/18] gpio: gpiolib-acpi: Export acpi_get_gpiod()
  2020-11-30 13:31 ` [PATCH 17/18] gpio: gpiolib-acpi: Export acpi_get_gpiod() Daniel Scally
  2020-11-30 17:02   ` kernel test robot
  2020-11-30 18:04   ` kernel test robot
@ 2020-11-30 19:20   ` Andy Shevchenko
  2 siblings, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 19:20 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

On Mon, Nov 30, 2020 at 01:31:28PM +0000, Daniel Scally wrote:
> I need to be able to translate GPIO resources in an acpi_device's _CRS
> into gpio_descs. Those are represented in _CRS as a pathname to a GPIO
> device plus the pin's index number: this function is perfect for that
> purpose.

Destiny of this patch depends on the review of the next one.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 02/18] property: Add support for calling fwnode_graph_get_endpoint_by_id() for fwnode->secondary
  2020-11-30 18:41         ` Laurent Pinchart
@ 2020-11-30 19:21           ` Andy Shevchenko
  0 siblings, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 19:21 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Mon, Nov 30, 2020 at 08:41:41PM +0200, Laurent Pinchart wrote:
> On Mon, Nov 30, 2020 at 07:53:19PM +0200, Andy Shevchenko wrote:
> > On Mon, Nov 30, 2020 at 07:28:57PM +0200, Laurent Pinchart wrote:
> > > On Mon, Nov 30, 2020 at 07:29:00PM +0200, Andy Shevchenko wrote:

...

> > > We could also move the !fwnode check to the beginning of the function.
> > 
> > It's already there (1). What did I miss?
> 
> It is, but as we need an explicitly check at the end, it feels cleaner
> to move it to the beginning. No big deal though.

I prefer to stick with a pattern I mentioned because we may easily to find and
unify these ones somehow.

> > 1) via fwnode_graph_get_next_endpoint() -> fwnode_call_ptr_op()

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 13:31 ` [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device Daniel Scally
  2020-11-30 16:17   ` Jean-Michel Hautbois
  2020-11-30 16:29   ` Kieran Bingham
@ 2020-11-30 20:07   ` Andy Shevchenko
  2020-11-30 23:32     ` Laurent Pinchart
                       ` (2 more replies)
  2020-11-30 20:52   ` Sakari Ailus
  3 siblings, 3 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-11-30 20:07 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus, Laurent Pinchart

On Mon, Nov 30, 2020 at 01:31:29PM +0000, Daniel Scally wrote:
> On platforms where ACPI is designed for use with Windows, resources
> that are intended to be consumed by sensor devices are sometimes in
> the _CRS of a dummy INT3472 device upon which the sensor depends. This
> driver binds to the dummy acpi device (which does not represent a

acpi device -> acpi_device

> physical PMIC) and maps them into GPIO lines and regulators for use by
> the sensor device instead.

...

> This patch contains the bits of this process that we're least sure about.
> The sensors in scope for this work are called out as dependent (in their
> DSDT entry's _DEP) on a device with _HID INT3472. These come in at least
> 2 kinds; those with an I2cSerialBusV2 entry (which we presume therefore
> are legitimate tps68470 PMICs that need handling by those drivers - work
> on that in the future). And those without an I2C device. For those without
> an I2C device they instead have an array of GPIO pins defined in _CRS. So
> for example, my Lenovo Miix 510's OVTI2680 sensor is dependent on one of
> the _latter_ kind of INT3472 devices, with this _CRS:
> 
> Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
> {
>     Name (SBUF, ResourceTemplate ()
>     {
>         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> 	    0x00, ResourceConsumer, ,
>             )
>             {   // Pin list
>                 0x0079
>             }
>         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> 	    0x00, ResourceConsumer, ,
>             )
>             {   // Pin list
>                 0x007A
>             }
>         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> 	    0x00, ResourceConsumer, ,
>             )
>             {   // Pin list
>                 0x008F
>             }
>     })
>     Return (SBUF) /* \_SB_.PCI0.PMI1._CRS.SBUF */
> }
> 
> and the same device has a _DSM Method, which returns 32-bit ints where
> the second lowest byte we noticed to match the pin numbers of the GPIO
> lines:
> 
> Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
> {
>     If ((Arg0 == ToUUID ("79234640-9e10-4fea-a5c1-b5aa8b19756f")))
>     {
>         If ((Arg2 == One))
>         {
>             Return (0x03)
>         }
> 
>         If ((Arg2 == 0x02))
>         {
>             Return (0x01007900)
>         }
> 
>         If ((Arg2 == 0x03))
>         {
>             Return (0x01007A0C)
>         }
> 
>         If ((Arg2 == 0x04))
>         {
>             Return (0x01008F01)
>         }
>     }
> 
>     Return (Zero)
> }
> 
> We know that at least some of those pins have to be toggled active for the
> sensor devices to be available in i2c, so the conclusion we came to was
> that those GPIO entries assigned to the INT3472 device actually represent
> GPIOs and regulators to be consumed by the sensors themselves. Tsuchiya
> noticed that the lowest byte in the return values of the _DSM method
> seemed to represent the type or function of the GPIO line, and we
> confirmed that by testing on each surface device that GPIO lines where the
> low byte in the _DSM entry for that pin was 0x0d controlled the privacy
> LED of the cameras.
> 
> We're guessing as to the exact meaning of the function byte, but I
> conclude they're something like this:
> 
> 0x00 - probably a reset GPIO
> 0x01 - regulator for the sensor
> 0x0c - regulator for the sensor
> 0x0b - regulator again, but for a VCM or EEPROM
> 0x0d - privacy led (only one we're totally confident of since we can see
>        it happen!)

It's solely Windows driver design...
Luckily I found some information and can clarify above table:

0x00 Reset
0x01 Power down
0x0b Power enable
0x0c Clock enable
0x0d LED (active high)

The above text perhaps should go somewhere under Documentation.

> After much internal debate I decided to write this as a standalone
> acpi_driver. Alternative options we considered:
> 
> 1. Squash all this into the cio2-bridge code, which I did originally write
> but decided I didn't like.
> 2. Extend the existing tps68470 mfd driver...they share an ACPI ID so this
> kinda makes sense, but ultimately given there is no actual physical
> tps68470 in the scenario this patch handles I decided I didn't like this
> either.

Looking to this I think the best is to create a module that can be consumed by tps68470 and separately.
So, something near to it rather than under ipu3 hood.

You may use same ID's in both drivers (in PMIC less case it can be simple
platform and thus they won't conflict), but both of them should provide GPIO
resources for consumption.

So, something like

 tps68470.h with API to consume
 split tps68470 to -core, -i2c parts
 add int3472, which will serve for above and be standalone platform driver
 update cio2-bridge accordingly

Would it be feasible?


...

> +	table_entry = (struct gpiod_lookup)GPIO_LOOKUP_IDX(acpi_dev_name(adev),
> +							   ares->data.gpio.pin_table[0],
> +							   func, 0, GPIO_ACTIVE_HIGH);

You won't need this if you have regular INT3472 platform driver.
Simple call there _DSM to map resources to the type and use devm_gpiod_get on
consumer behalf. Thus, previous patch is not needed.

...

> +	case 0x01: /* Power regulators (we think) */
> +	case 0x0c:
> +	case 0x0b: /* Power regulators, but to a device separate to sensor */
> +	case 0x0d: /* Indicator LEDs */


Give names to those constants.

	#define INT3472_GPIO_TYPE_RESET 0x00
	...


> +static struct acpi_driver int3472_driver = {

No acpi_driver! Use platform_driver instead with plenty of examples all over
the kernel.

> +	.name = "int3472",
> +	.ids = int3472_device_id,
> +	.ops = {
> +		.add = int3472_add,
> +		.remove = int3472_remove,
> +	},

> +	.owner = THIS_MODULE,

No need

> +};

...

> +const guid_t int3472_gpio_guid = GUID_INIT(0x79234640, 0x9e10, 0x4fea,
> +					     0xa5, 0xc1, 0xb5, 0xaa, 0x8b,
> +					     0x19, 0x75, 0x6f);
> +
> +const guid_t cio2_sensor_module_guid = GUID_INIT(0x822ace8f, 0x2814, 0x4174,
> +						 0xa5, 0x6b, 0x5f, 0x02, 0x9f,
> +						 0xe0, 0x79, 0xee);


Use more or less standard pattern for these, like

/* 79234640-9e10-4fea-a5c1b5aa8b19756f */
const guid_t int3472_gpio_guid =
	GUID_INIT(0x79234640, 0x9e10, 0x4fea,
		  0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f);

...

> +static struct regulator_consumer_supply miix_510_ov2680[] = {
> +	{ "i2c-OVTI2680:00", "avdd" },
> +	{ "i2c-OVTI2680:00", "dovdd" },
> +};

Can we use acpi_dev_first_match_dev() to get instance name out of their HIDs?

> +static struct regulator_consumer_supply surface_go2_ov5693[] = {
> +	{ "i2c-INT33BE:00", "avdd" },
> +	{ "i2c-INT33BE:00", "dovdd" },
> +};
> +
> +static struct regulator_consumer_supply surface_book_ov5693[] = {
> +	{ "i2c-INT33BE:00", "avdd" },
> +	{ "i2c-INT33BE:00", "dovdd" },
> +};

Ditto.

...

> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
> +	{ "GNDF140809R", 2, miix_510_ov2680 },
> +	{ "YHCU", 2, surface_go2_ov5693 },
> +	{ "MSHW0070", 2, surface_book_ov5693 },
> +};

Hmm... Usual way is to use DMI for that. I'm not sure above will not give us
false positive matches.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-30 13:31 ` [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
  2020-11-30 16:45   ` kernel test robot
  2020-11-30 17:09   ` Laurent Pinchart
@ 2020-11-30 20:27   ` kernel test robot
  2020-11-30 20:35   ` Sakari Ailus
  3 siblings, 0 replies; 144+ messages in thread
From: kernel test robot @ 2020-11-30 20:27 UTC (permalink / raw)
  To: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel
  Cc: kbuild-all, clang-built-linux, rjw, lenb, gregkh, mika.westerberg

[-- Attachment #1: Type: text/plain, Size: 2724 bytes --]

Hi Daniel,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on driver-core/driver-core-testing pm/linux-next v5.10-rc6 next-20201130]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Daniel-Scally/Add-functionality-to-ipu3-cio2-driver-allowing-software_node-connections-to-sensors-on-platforms-designed-for-Windows/20201130-214014
base:   git://linuxtv.org/media_tree.git master
config: x86_64-randconfig-a003-20201130 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project dfcf1acf13226be0f599a7ab6b395b66dc9545d6)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # https://github.com/0day-ci/linux/commit/05cb91d6b6272c4516b21b0ecd23a6ff8d861aae
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Daniel-Scally/Add-functionality-to-ipu3-cio2-driver-allowing-software_node-connections-to-sensors-on-platforms-designed-for-Windows/20201130-214014
        git checkout 05cb91d6b6272c4516b21b0ecd23a6ff8d861aae
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from drivers/media/pci/intel/ipu3/ipu3-cio2-main.c:31:
>> drivers/media/pci/intel/ipu3/ipu3-cio2.h:443:5: warning: no previous prototype for function 'cio2_bridge_init' [-Wmissing-prototypes]
   int cio2_bridge_init(struct pci_dev *cio2) { return 0; }
       ^
   drivers/media/pci/intel/ipu3/ipu3-cio2.h:443:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int cio2_bridge_init(struct pci_dev *cio2) { return 0; }
   ^
   static 
   1 warning generated.

vim +/cio2_bridge_init +443 drivers/media/pci/intel/ipu3/ipu3-cio2.h

   439	
   440	#if IS_ENABLED(CONFIG_CIO2_BRIDGE)
   441	int cio2_bridge_init(struct pci_dev *cio2);
   442	#else
 > 443	int cio2_bridge_init(struct pci_dev *cio2) { return 0; }
   444	#endif
   445	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 40463 bytes --]

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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-30 13:31 ` [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
                     ` (2 preceding siblings ...)
  2020-11-30 20:27   ` kernel test robot
@ 2020-11-30 20:35   ` Sakari Ailus
  2020-12-01  8:13     ` Dan Scally
                       ` (2 more replies)
  3 siblings, 3 replies; 144+ messages in thread
From: Sakari Ailus @ 2020-11-30 20:35 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Daniel,

Thanks for the update! This is starting to look really nice!

Please still see my comments below.

On Mon, Nov 30, 2020 at 01:31:24PM +0000, Daniel Scally wrote:
> Currently on platforms designed for Windows, connections between CIO2 and
> sensors are not properly defined in DSDT. This patch extends the ipu3-cio2
> driver to compensate by building software_node connections, parsing the
> connection properties from the sensor's SSDB buffer.
> 
> Suggested-by: Jordan Hand <jorhand@linux.microsoft.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes since RFC v3:
> 
> 	- Removed almost all global variables, dynamically allocated
> 	the cio2_bridge structure, plus a bunch of associated changes
> 	like 
> 	- Added a new function to ipu3-cio2-main.c to check for an 
> 	existing fwnode_graph before calling cio2_bridge_init()
> 	- Prefixed cio2_bridge_ to any variables and functions that
> 	lacked it
> 	- Assigned the new fwnode directly to the sensor's ACPI device
> 	fwnode as secondary. This removes the requirement to delay until
> 	the I2C devices are instantiated before ipu3-cio2 can probe, but
> 	it has a side effect, which is that those devices then grab a ref
> 	to the new software_node. This effectively prevents us from
> 	unloading the driver, because we can't free the memory that they
> 	live in whilst the device holds a reference to them. The work
> 	around at the moment is to _not_ unregister the software_nodes
> 	when ipu3-cio2 is unloaded; this becomes a one-time 'patch', that
> 	is simply skipped if the module is reloaded.
> 	- Moved the sensor's SSDB struct to be a member of cio2_sensor
> 	- Replaced ints with unsigned ints where appropriate
> 	- Iterated over all ACPI devices of a matching _HID rather than
> 	just the first to ensure we handle a device with multiple sensors
> 	of the same model.
> 
>  MAINTAINERS                                   |   1 +
>  drivers/media/pci/intel/ipu3/Kconfig          |  18 ++
>  drivers/media/pci/intel/ipu3/Makefile         |   1 +
>  drivers/media/pci/intel/ipu3/cio2-bridge.c    | 260 ++++++++++++++++++
>  drivers/media/pci/intel/ipu3/cio2-bridge.h    | 108 ++++++++
>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  27 ++
>  drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   6 +
>  7 files changed, 421 insertions(+)
>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9702b886d6a4..188559a0a610 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8927,6 +8927,7 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
>  M:	Yong Zhi <yong.zhi@intel.com>
>  M:	Sakari Ailus <sakari.ailus@linux.intel.com>
>  M:	Bingbu Cao <bingbu.cao@intel.com>
> +M:	Dan Scally <djrscally@gmail.com>
>  R:	Tianshu Qiu <tian.shu.qiu@intel.com>
>  L:	linux-media@vger.kernel.org
>  S:	Maintained
> diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
> index 82d7f17e6a02..2b3350d042be 100644
> --- a/drivers/media/pci/intel/ipu3/Kconfig
> +++ b/drivers/media/pci/intel/ipu3/Kconfig
> @@ -16,3 +16,21 @@ config VIDEO_IPU3_CIO2
>  	  Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2
>  	  connected camera.
>  	  The module will be called ipu3-cio2.
> +
> +config CIO2_BRIDGE
> +	bool "IPU3 CIO2 Sensors Bridge"
> +	depends on VIDEO_IPU3_CIO2
> +	help
> +	  This extension provides an API for the ipu3-cio2 driver to create
> +	  connections to cameras that are hidden in SSDB buffer in ACPI. It
> +	  can be used to enable support for cameras in detachable / hybrid
> +	  devices that ship with Windows.
> +
> +	  Say Y here if your device is a detachable / hybrid laptop that comes
> +	  with Windows installed by the OEM, for example:
> +
> +	  	- Microsoft Surface models (except Surface Pro 3)
> +		- The Lenovo Miix line (for example the 510, 520, 710 and 720)
> +		- Dell 7285
> +
> +	  If in doubt, say N here.
> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
> index 429d516452e4..933777e6ea8a 100644
> --- a/drivers/media/pci/intel/ipu3/Makefile
> +++ b/drivers/media/pci/intel/ipu3/Makefile
> @@ -2,3 +2,4 @@
>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
>  
>  ipu3-cio2-y += ipu3-cio2-main.o
> +ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> new file mode 100644
> index 000000000000..fd3f8ba07274
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> @@ -0,0 +1,260 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Author: Dan Scally <djrscally@gmail.com> */
> +#include <linux/acpi.h>
> +#include <linux/device.h>
> +#include <linux/i2c.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/pci.h>
> +#include <linux/property.h>
> +#include <media/v4l2-subdev.h>
> +
> +#include "cio2-bridge.h"
> +
> +/*
> + * Extend this array with ACPI Hardware ID's of devices known to be working.
> + * Do not add a HID for a sensor that is not actually supported.
> + */
> +static const char * const cio2_supported_devices[] = {
> +	"INT33BE",
> +	"OVTI2680",

I guess we don't have the known-good frequencies for the CSI-2 bus in
firmware?

One option would be to put there what the drivers currently use. This
assumes the support for these devices is, well, somewhat opportunistic but
I guess there's no way around that right now at least.

As the systems are laptops, they're likely somewhat less prone to EMI
issues to begin with than mobile phones anyway.

> +};
> +
> +static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id,
> +					void *data, u32 size)
> +{
> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> +	union acpi_object *obj;
> +	acpi_status status;
> +	int ret;
> +
> +	status = acpi_evaluate_object(adev->handle, id, NULL, &buffer);
> +	if (ACPI_FAILURE(status))
> +		return -ENODEV;
> +
> +	obj = buffer.pointer;
> +	if (!obj) {
> +		dev_err(&adev->dev, "Couldn't locate ACPI buffer\n");
> +		return -ENODEV;
> +	}
> +
> +	if (obj->type != ACPI_TYPE_BUFFER) {
> +		dev_err(&adev->dev, "Not an ACPI buffer\n");
> +		ret = -ENODEV;
> +		goto out_free_buff;
> +	}
> +
> +	if (obj->buffer.length > size) {
> +		dev_err(&adev->dev, "Given buffer is too small\n");
> +		ret = -EINVAL;
> +		goto out_free_buff;
> +	}
> +
> +	memcpy(data, obj->buffer.pointer, obj->buffer.length);
> +	ret = obj->buffer.length;
> +
> +out_free_buff:
> +	kfree(buffer.pointer);
> +	return ret;
> +}
> +
> +static void cio2_bridge_init_property_names(struct cio2_sensor *sensor)
> +{
> +	strcpy(sensor->prop_names.clock_frequency, "clock-frequency");
> +	strcpy(sensor->prop_names.rotation, "rotation");
> +	strcpy(sensor->prop_names.bus_type, "bus-type");
> +	strcpy(sensor->prop_names.data_lanes, "data-lanes");
> +	strcpy(sensor->prop_names.remote_endpoint, "remote-endpoint");

Please use the actual field size instead with strncpy / strscpy.

> +}
> +
> +static void cio2_bridge_create_fwnode_properties(struct cio2_sensor *sensor)
> +{
> +	unsigned int i;
> +
> +	cio2_bridge_init_property_names(sensor);
> +
> +	for (i = 0; i < 4; i++)
> +		sensor->data_lanes[i] = i + 1;
> +
> +	/*
> +	 * Can't use PROPERTY_ENTRY_REF because it creates a new variable to
> +	 * point to, which doesn't survive the function.
> +	 */
> +	sensor->local_ref[0] = (struct software_node_ref_args){
> +		.node = &sensor->swnodes[SWNODE_CIO2_ENDPOINT]
> +		};

I guess this line should be unindented by one tab stop. Same for the
similar case below.

> +	sensor->remote_ref[0] = (struct software_node_ref_args){
> +		.node = &sensor->swnodes[SWNODE_SENSOR_ENDPOINT]
> +		};
> +
> +	sensor->dev_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.clock_frequency,
> +						       sensor->ssdb.mclkspeed);
> +	sensor->dev_properties[1] = PROPERTY_ENTRY_U8(sensor->prop_names.rotation,
> +						      sensor->ssdb.degree);
> +
> +	sensor->ep_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.bus_type, 5);
> +	sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes,
> +								sensor->data_lanes,
> +								sensor->ssdb.lanes);
> +	sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint,
> +							    sensor->local_ref);
> +
> +	sensor->cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes,
> +								  sensor->data_lanes,
> +								  sensor->ssdb.lanes);
> +	sensor->cio2_properties[1] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint,
> +							      sensor->remote_ref);
> +}
> +
> +static void cio2_bridge_init_swnode_names(struct cio2_sensor *sensor)
> +{
> +	snprintf(sensor->node_names.remote_port, 6, "port%u", sensor->ssdb.link);
> +	strcpy(sensor->node_names.port, "port0");
> +	strcpy(sensor->node_names.endpoint, "endpoint0");

Please use the actual size of the field, and strncpy / strscpy.

> +}
> +
> +static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge,
> +						  struct cio2_sensor *sensor)
> +{
> +	struct software_node *nodes = sensor->swnodes;
> +
> +	cio2_bridge_init_swnode_names(sensor);
> +
> +	nodes[SWNODE_SENSOR_HID] = NODE_SENSOR(sensor->name,
> +					       sensor->dev_properties);
> +	nodes[SWNODE_SENSOR_PORT] = NODE_PORT(sensor->node_names.port,
> +					      &nodes[SWNODE_SENSOR_HID]);
> +	nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint,
> +						      &nodes[SWNODE_SENSOR_PORT],
> +						      sensor->ep_properties);
> +	nodes[SWNODE_CIO2_PORT] = NODE_PORT(sensor->node_names.remote_port,
> +					    &bridge->cio2_hid_node);
> +	nodes[SWNODE_CIO2_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint,
> +						    &nodes[SWNODE_CIO2_PORT],
> +						    sensor->cio2_properties);
> +}
> +
> +static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge)
> +{
> +	struct cio2_sensor *sensor;
> +	unsigned int i;
> +
> +	for (i = 0; i < bridge->n_sensors; i++) {
> +		sensor = &bridge->sensors[i];
> +		software_node_unregister_nodes(sensor->swnodes);
> +		acpi_dev_put(sensor->adev);
> +	}
> +}
> +
> +static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge)
> +{
> +	struct fwnode_handle *fwnode;
> +	struct cio2_sensor *sensor;
> +	struct acpi_device *adev;
> +	unsigned int i;
> +	int ret = 0;
> +
> +	for (i = 0; i < ARRAY_SIZE(cio2_supported_devices); i++) {
> +		const char *this_device = cio2_supported_devices[i];
> +
> +		for_each_acpi_dev_match(adev, this_device, NULL, -1) {
> +			if (!adev || !(adev->status.present && adev->status.enabled))
> +				continue;
> +
> +			sensor = &bridge->sensors[bridge->n_sensors];
> +			sensor->adev = adev;
> +			strscpy(sensor->name, this_device, sizeof(sensor->name));
> +
> +			ret = cio2_bridge_read_acpi_buffer(adev, "SSDB",
> +							   &sensor->ssdb,
> +							   sizeof(sensor->ssdb));
> +			if (ret < 0)
> +				goto err_put_adev;
> +
> +			if (sensor->ssdb.lanes > 4) {
> +				dev_err(&adev->dev,
> +					"Number of lanes in SSDB is invalid\n");
> +				goto err_put_adev;
> +			}
> +
> +			cio2_bridge_create_fwnode_properties(sensor);
> +			cio2_bridge_create_connection_swnodes(bridge, sensor);
> +
> +			ret = software_node_register_nodes(sensor->swnodes);
> +			if (ret)
> +				goto err_put_adev;
> +
> +			fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR_HID]);
> +			if (!fwnode) {
> +				ret = -ENODEV;
> +				goto err_free_swnodes;
> +			}
> +
> +			adev->fwnode.secondary = fwnode;
> +
> +			dev_info(&bridge->cio2->dev,
> +				 "Found supported sensor %s\n",
> +				 acpi_dev_name(adev));
> +
> +			bridge->n_sensors++;
> +		}
> +	}
> +
> +	return ret;
> +
> +err_free_swnodes:
> +	software_node_unregister_nodes(sensor->swnodes);
> +err_put_adev:
> +	acpi_dev_put(sensor->adev);
> +
> +	return ret;
> +}
> +
> +int cio2_bridge_init(struct pci_dev *cio2)
> +{
> +	struct device *dev = &cio2->dev;
> +	struct fwnode_handle *fwnode;
> +	struct cio2_bridge *bridge;
> +	int ret;
> +
> +	bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
> +	if (!bridge)
> +		return -ENOMEM;
> +
> +	strscpy(bridge->cio2_node_name, CIO2_HID, sizeof(bridge->cio2_node_name));
> +	bridge->cio2_hid_node = (const struct software_node){ bridge->cio2_node_name };
> +	bridge->cio2 = pci_dev_get(cio2);
> +
> +	ret = software_node_register(&bridge->cio2_hid_node);
> +	if (ret < 0) {
> +		dev_err(dev, "Failed to register the CIO2 HID node\n");
> +		goto err_put_cio2;
> +	}
> +
> +	ret = cio2_bridge_connect_sensors(bridge);
> +	if (ret || bridge->n_sensors == 0)
> +		goto err_unregister_cio2;
> +
> +	dev_info(dev, "Connected %d cameras\n", bridge->n_sensors);
> +
> +	fwnode = software_node_fwnode(&bridge->cio2_hid_node);
> +	if (!fwnode) {
> +		dev_err(dev, "Error getting fwnode from cio2 software_node\n");
> +		ret = -ENODEV;
> +		goto err_unregister_sensors;
> +	}
> +
> +	set_secondary_fwnode(dev, fwnode);
> +
> +	return 0;
> +
> +err_unregister_sensors:
> +	cio2_bridge_unregister_sensors(bridge);
> +err_unregister_cio2:
> +	software_node_unregister(&bridge->cio2_hid_node);
> +err_put_cio2:
> +	pci_dev_put(bridge->cio2);
> +
> +	kfree(bridge);
> +	return ret;
> +}
> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h
> new file mode 100644
> index 000000000000..96f5c8a12be0
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h
> @@ -0,0 +1,108 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Author: Dan Scally <djrscally@gmail.com> */
> +#ifndef __CIO2_BRIDGE_H
> +#define __CIO2_BRIDGE_H
> +
> +#include <linux/property.h>
> +
> +#define CIO2_HID				"INT343E"
> +#define CIO2_NUM_PORTS			  4
> +
> +#define NODE_SENSOR(_HID, _PROPS)		\
> +	((const struct software_node) {		\
> +		.name = _HID,			\
> +		.properties = _PROPS,		\
> +	})
> +
> +#define NODE_PORT(_PORT, _SENSOR_NODE)		\
> +	((const struct software_node) {		\
> +		_PORT,				\
> +		_SENSOR_NODE,			\
> +	})
> +
> +#define NODE_ENDPOINT(_EP, _PORT, _PROPS)	\
> +	((const struct software_node) {		\
> +		_EP,				\
> +		_PORT,				\
> +		_PROPS,				\
> +	})
> +
> +enum cio2_sensor_swnodes {
> +	SWNODE_SENSOR_HID,
> +	SWNODE_SENSOR_PORT,
> +	SWNODE_SENSOR_ENDPOINT,
> +	SWNODE_CIO2_PORT,
> +	SWNODE_CIO2_ENDPOINT,
> +	NR_OF_SENSOR_SWNODES
> +};
> +
> +/* Data representation as it is in ACPI SSDB buffer */
> +struct cio2_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__;

This should be "__packed".

> +
> +struct cio2_property_names {
> +	char clock_frequency[16];
> +	char rotation[9];
> +	char bus_type[9];
> +	char data_lanes[11];
> +	char remote_endpoint[16];
> +};
> +
> +struct cio2_node_names {
> +	char port[6];
> +	char endpoint[10];
> +	char remote_port[6];
> +};
> +
> +struct cio2_sensor {
> +	char name[ACPI_ID_LEN];
> +	struct acpi_device *adev;
> +
> +	struct software_node swnodes[6];
> +	struct cio2_node_names node_names;
> +
> +	u32 data_lanes[4];
> +	struct cio2_sensor_ssdb ssdb;
> +	struct cio2_property_names prop_names;
> +	struct property_entry ep_properties[4];
> +	struct property_entry dev_properties[3];
> +	struct property_entry cio2_properties[3];
> +	struct software_node_ref_args local_ref[1];
> +	struct software_node_ref_args remote_ref[1];
> +};
> +
> +struct cio2_bridge {
> +	struct pci_dev *cio2;
> +	char cio2_node_name[ACPI_ID_LEN];
> +	struct software_node cio2_hid_node;
> +	unsigned int n_sensors;
> +	struct cio2_sensor sensors[CIO2_NUM_PORTS];
> +};
> +
> +#endif
> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> index 36e354ecf71e..0d69b593e9f0 100644
> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> @@ -1702,6 +1702,22 @@ static void cio2_queues_exit(struct cio2_device *cio2)
>  		cio2_queue_exit(cio2, &cio2->queue[i]);
>  }
>  
> +static bool cio2_check_fwnode_graph(struct fwnode_handle *fwnode)
> +{
> +	struct fwnode_handle *endpoint;
> +
> +	if (IS_ERR_OR_NULL(fwnode))
> +		return false;
> +
> +	endpoint = fwnode_graph_get_next_endpoint(fwnode, NULL);
> +	if (endpoint) {
> +		fwnode_handle_put(endpoint);
> +		return true;
> +	}
> +
> +	return cio2_check_fwnode_graph(fwnode->secondary);
> +}
> +
>  /**************** PCI interface ****************/
>  
>  static int cio2_pci_probe(struct pci_dev *pci_dev,
> @@ -1715,6 +1731,17 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
>  		return -ENOMEM;
>  	cio2->pci_dev = pci_dev;
>  
> +	/*
> +	 * On some platforms no connections to sensors are defined in firmware,
> +	 * if the device has no endpoints then we can try to build those as
> +	 * software_nodes parsed from SSDB.
> +	 */
> +	if (!cio2_check_fwnode_graph(dev_fwnode(&pci_dev->dev))) {
> +		r = cio2_bridge_init(pci_dev);
> +		if (r)
> +			return r;
> +	}
> +
>  	r = pcim_enable_device(pci_dev);
>  	if (r) {
>  		dev_err(&pci_dev->dev, "failed to enable device (%d)\n", r);
> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.h b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
> index ccf0b85ae36f..520a27c9cdad 100644
> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.h
> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
> @@ -437,4 +437,10 @@ static inline struct cio2_queue *vb2q_to_cio2_queue(struct vb2_queue *vq)
>  	return container_of(vq, struct cio2_queue, vbq);
>  }
>  
> +#if IS_ENABLED(CONFIG_CIO2_BRIDGE)
> +int cio2_bridge_init(struct pci_dev *cio2);
> +#else
> +int cio2_bridge_init(struct pci_dev *cio2) { return 0; }
> +#endif
> +
>  #endif

-- 
Kind regards,

Sakari Ailus

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 13:31 ` [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device Daniel Scally
                     ` (2 preceding siblings ...)
  2020-11-30 20:07   ` Andy Shevchenko
@ 2020-11-30 20:52   ` Sakari Ailus
  2020-11-30 23:06     ` Dan Scally
  3 siblings, 1 reply; 144+ messages in thread
From: Sakari Ailus @ 2020-11-30 20:52 UTC (permalink / raw)
  To: Daniel Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

Hi Daniel,

Thanks for the patch.

On Mon, Nov 30, 2020 at 01:31:29PM +0000, Daniel Scally wrote:
> On platforms where ACPI is designed for use with Windows, resources
> that are intended to be consumed by sensor devices are sometimes in
> the _CRS of a dummy INT3472 device upon which the sensor depends. This
> driver binds to the dummy acpi device (which does not represent a
> physical PMIC) and maps them into GPIO lines and regulators for use by
> the sensor device instead.
> 
> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes since RFC v3:
> 
> 	- Patch introduced
> 
> This patch contains the bits of this process that we're least sure about.
> The sensors in scope for this work are called out as dependent (in their
> DSDT entry's _DEP) on a device with _HID INT3472. These come in at least
> 2 kinds; those with an I2cSerialBusV2 entry (which we presume therefore
> are legitimate tps68470 PMICs that need handling by those drivers - work
> on that in the future). And those without an I2C device. For those without
> an I2C device they instead have an array of GPIO pins defined in _CRS. So
> for example, my Lenovo Miix 510's OVTI2680 sensor is dependent on one of
> the _latter_ kind of INT3472 devices, with this _CRS:
> 
> Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
> {
>     Name (SBUF, ResourceTemplate ()
>     {
>         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> 	    0x00, ResourceConsumer, ,
>             )
>             {   // Pin list
>                 0x0079
>             }
>         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> 	    0x00, ResourceConsumer, ,
>             )
>             {   // Pin list
>                 0x007A
>             }
>         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> 	    0x00, ResourceConsumer, ,
>             )
>             {   // Pin list
>                 0x008F
>             }
>     })
>     Return (SBUF) /* \_SB_.PCI0.PMI1._CRS.SBUF */
> }
> 
> and the same device has a _DSM Method, which returns 32-bit ints where
> the second lowest byte we noticed to match the pin numbers of the GPIO
> lines:
> 
> Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
> {
>     If ((Arg0 == ToUUID ("79234640-9e10-4fea-a5c1-b5aa8b19756f")))
>     {
>         If ((Arg2 == One))
>         {
>             Return (0x03)
>         }
> 
>         If ((Arg2 == 0x02))
>         {
>             Return (0x01007900)
>         }
> 
>         If ((Arg2 == 0x03))
>         {
>             Return (0x01007A0C)
>         }
> 
>         If ((Arg2 == 0x04))
>         {
>             Return (0x01008F01)
>         }
>     }
> 
>     Return (Zero)
> }
> 
> We know that at least some of those pins have to be toggled active for the
> sensor devices to be available in i2c, so the conclusion we came to was
> that those GPIO entries assigned to the INT3472 device actually represent
> GPIOs and regulators to be consumed by the sensors themselves. Tsuchiya
> noticed that the lowest byte in the return values of the _DSM method
> seemed to represent the type or function of the GPIO line, and we
> confirmed that by testing on each surface device that GPIO lines where the
> low byte in the _DSM entry for that pin was 0x0d controlled the privacy
> LED of the cameras.
> 
> We're guessing as to the exact meaning of the function byte, but I
> conclude they're something like this:
> 
> 0x00 - probably a reset GPIO
> 0x01 - regulator for the sensor
> 0x0c - regulator for the sensor
> 0x0b - regulator again, but for a VCM or EEPROM
> 0x0d - privacy led (only one we're totally confident of since we can see
>        it happen!)
> 
> After much internal debate I decided to write this as a standalone
> acpi_driver. Alternative options we considered:
> 
> 1. Squash all this into the cio2-bridge code, which I did originally write
> but decided I didn't like.
> 2. Extend the existing tps68470 mfd driver...they share an ACPI ID so this
> kinda makes sense, but ultimately given there is no actual physical
> tps68470 in the scenario this patch handles I decided I didn't like this
> either.
> 
>  MAINTAINERS                            |   7 +
>  drivers/media/pci/intel/ipu3/Kconfig   |  14 +
>  drivers/media/pci/intel/ipu3/Makefile  |   1 +
>  drivers/media/pci/intel/ipu3/int3472.c | 381 +++++++++++++++++++++++++
>  drivers/media/pci/intel/ipu3/int3472.h |  96 +++++++
>  5 files changed, 499 insertions(+)
>  create mode 100644 drivers/media/pci/intel/ipu3/int3472.c
>  create mode 100644 drivers/media/pci/intel/ipu3/int3472.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 188559a0a610..d73471f9c2a3 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8753,6 +8753,13 @@ L:	linux-crypto@vger.kernel.org
>  S:	Maintained
>  F:	drivers/crypto/inside-secure/
>  
> +INT3472 ACPI DEVICE DRIVER
> +M:	Daniel Scally <djrscally@gmail.com>
> +L:	linux-media@vger.kernel.org
> +S:	Maintained
> +F:	drivers/media/pci/intel/ipu3/int3472.c
> +F:	drivers/media/pci/intel/ipu3/int3472.h
> +
>  INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
>  M:	Mimi Zohar <zohar@linux.ibm.com>
>  M:	Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
> diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
> index 2b3350d042be..9dd3b280f821 100644
> --- a/drivers/media/pci/intel/ipu3/Kconfig
> +++ b/drivers/media/pci/intel/ipu3/Kconfig
> @@ -34,3 +34,17 @@ config CIO2_BRIDGE
>  		- Dell 7285
>  
>  	  If in doubt, say N here.
> +
> +config INT3472
> +	tristate "INT3472 Dummy ACPI Device Driver"
> +	depends on VIDEO_IPU3_CIO2
> +	depends on ACPI && REGULATOR && GPIOLIB
> +	help
> +	  This module provides an ACPI driver for INT3472 devices that do not
> +	  represent an actual physical tps68470 device.
> +
> +	  Say Y here if your device is a detachable / hybrid laptop that comes
> +	  with Windows installed by the OEM.
> +	  The module will be called int3472.
> +
> +	  If in doubt, say N here.
> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
> index 933777e6ea8a..2285947b2bd2 100644
> --- a/drivers/media/pci/intel/ipu3/Makefile
> +++ b/drivers/media/pci/intel/ipu3/Makefile
> @@ -1,5 +1,6 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
> +obj-$(CONFIG_INT3472) += int3472.o
>  
>  ipu3-cio2-y += ipu3-cio2-main.o
>  ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
> diff --git a/drivers/media/pci/intel/ipu3/int3472.c b/drivers/media/pci/intel/ipu3/int3472.c
> new file mode 100644
> index 000000000000..6b0be75f7f35
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu3/int3472.c
> @@ -0,0 +1,381 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Author: Dan Scally <djrscally@gmail.com> */
> +#include <linux/acpi.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/gpio/machine.h>
> +#include <linux/i2c.h>
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/module.h>
> +#include <linux/regulator/driver.h>
> +
> +#include "int3472.h"
> +
> +/*
> + * The regulators have to have .ops to be valid, but the only ops we actually
> + * support are .enable and .disable which are handled via .ena_gpiod. Pass an
> + * empty struct to clear the check without lying about capabilities.
> + */
> +static const struct regulator_ops int3472_gpio_regulator_ops = { 0 };
> +
> +static int int3472_map_gpio_to_sensor(struct int3472_device *int3472,
> +				      struct acpi_resource *ares, char *func)
> +{
> +	char *path = ares->data.gpio.resource_source.string_ptr;
> +	struct gpiod_lookup table_entry;
> +	struct acpi_device *adev;
> +	acpi_handle handle;
> +	acpi_status status;
> +	int ret;
> +
> +	/* Make sure we don't overflow, and leave room for a terminator */
> +	if (int3472->n_sensor_gpios >= INT3472_MAX_SENSOR_GPIOS) {
> +		dev_warn(&int3472->sensor->dev, "Too many GPIOs mapped\n");
> +		return -EINVAL;
> +	}
> +
> +	/* Fetch ACPI handle for the GPIO chip  */
> +	status = acpi_get_handle(NULL, path, &handle);
> +	if (ACPI_FAILURE(status))
> +		return -EINVAL;
> +
> +	ret = acpi_bus_get_device(handle, &adev);
> +	if (ret)
> +		return -ENODEV;
> +
> +	table_entry = (struct gpiod_lookup)GPIO_LOOKUP_IDX(acpi_dev_name(adev),
> +							   ares->data.gpio.pin_table[0],
> +							   func, 0, GPIO_ACTIVE_HIGH);
> +
> +	memcpy(&int3472->gpios.table[int3472->n_sensor_gpios], &table_entry,
> +	       sizeof(table_entry));
> +	int3472->n_sensor_gpios++;
> +
> +	return 0;
> +}
> +
> +static struct int3472_sensor_regulator_map *
> +int3472_get_sensor_supply_map(struct int3472_device *int3472)
> +{
> +	struct int3472_sensor_regulator_map *ret;
> +	union acpi_object *obj;
> +	unsigned int i;
> +
> +	/*
> +	 * Sensor modules seem to be identified by a unique string. We use that
> +	 * to make sure we pass the right device and supply names to the new
> +	 * regulator's consumer_supplies
> +	 */
> +	obj = acpi_evaluate_dsm_typed(int3472->sensor->handle,
> +				      &cio2_sensor_module_guid, 0x00,
> +				      0x01, NULL, ACPI_TYPE_STRING);
> +
> +	if (!obj) {
> +		dev_err(&int3472->sensor->dev,
> +			"Failed to get sensor module string from _DSM\n");
> +		return ERR_PTR(-ENODEV);
> +	}
> +
> +	if (obj->string.type != ACPI_TYPE_STRING) {
> +		dev_err(&int3472->sensor->dev,
> +			"Sensor _DSM returned a non-string value\n");
> +		ret = ERR_PTR(-EINVAL);
> +		goto out_free_obj;
> +	}
> +
> +	ret = ERR_PTR(-ENODEV);
> +	for (i = 0; i < ARRAY_SIZE(int3472_sensor_regulator_maps); i++) {
> +		if (!strcmp(int3472_sensor_regulator_maps[i].sensor_module_name,
> +			    obj->string.pointer)) {
> +			ret = &int3472_sensor_regulator_maps[i];
> +			goto out_free_obj;
> +		}
> +	}
> +
> +out_free_obj:
> +	ACPI_FREE(obj);
> +	return ret;
> +}
> +
> +static int int3472_register_regulator(struct int3472_device *int3472,
> +				      struct acpi_resource *ares)
> +{
> +	char *path = ares->data.gpio.resource_source.string_ptr;
> +	struct int3472_sensor_regulator_map *regulator_map;
> +	struct regulator_init_data init_data = { };
> +	struct int3472_gpio_regulator *regulator;
> +	struct regulator_config cfg = { };
> +	int ret;
> +
> +	/*
> +	 * We lookup supply names from machine specific tables, based on a
> +	 * unique identifier in the sensor's _DSM
> +	 */
> +	regulator_map = int3472_get_sensor_supply_map(int3472);
> +	if (IS_ERR_OR_NULL(regulator_map)) {
> +		dev_err(&int3472->sensor->dev,
> +			"Found no supplies defined for this sensor\n");
> +		return PTR_ERR(regulator_map);
> +	}
> +
> +	if (int3472->n_regulators >= regulator_map->n_supplies) {
> +		dev_err(&int3472->sensor->dev,
> +			"All known supplies are already mapped\n");
> +		return -EINVAL;
> +	}
> +
> +	init_data.supply_regulator = NULL;
> +	init_data.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
> +	init_data.num_consumer_supplies = 1;
> +	init_data.consumer_supplies = &regulator_map->supplies[int3472->n_regulators];
> +
> +	regulator = kmalloc(sizeof(*regulator), GFP_KERNEL);
> +	if (!regulator)
> +		return -ENOMEM;
> +
> +	snprintf(regulator->regulator_name, GPIO_REGULATOR_NAME_LENGTH,
> +		 "gpio-regulator-%d", int3472->n_regulators);
> +	snprintf(regulator->supply_name, GPIO_REGULATOR_SUPPLY_NAME_LENGTH,
> +		 "supply-%d", int3472->n_regulators);
> +
> +	regulator->rdesc = INT3472_REGULATOR(regulator->regulator_name,
> +					     regulator->supply_name,
> +					     int3472->n_regulators,
> +					     &int3472_gpio_regulator_ops);
> +
> +	regulator->gpio = acpi_get_gpiod(path, ares->data.gpio.pin_table[0]);
> +	if (IS_ERR(regulator->gpio)) {
> +		ret = PTR_ERR(regulator->gpio);
> +		goto err_free_regulator;
> +	}
> +
> +	cfg.dev = &int3472->adev->dev;
> +	cfg.init_data = &init_data;
> +	cfg.ena_gpiod = regulator->gpio;
> +
> +	regulator->rdev = regulator_register(&regulator->rdesc, &cfg);
> +	if (IS_ERR(regulator->rdev)) {
> +		ret = PTR_ERR(regulator->rdev);
> +		goto err_free_gpio;
> +	}
> +
> +	list_add(&regulator->list, &int3472->regulators);
> +	int3472->n_regulators++;
> +
> +	return 0;
> +
> +err_free_gpio:
> +	gpiod_put(regulator->gpio);
> +err_free_regulator:
> +	kfree(regulator);
> +
> +	return ret;
> +}
> +
> +static int int3472_handle_gpio_resources(struct acpi_resource *ares,
> +					 void *data)
> +{
> +	struct int3472_device *int3472 = data;
> +	union acpi_object *obj;
> +	int ret = 0;
> +
> +	if (ares->type != ACPI_RESOURCE_TYPE_GPIO ||
> +	    ares->data.gpio.connection_type != ACPI_RESOURCE_GPIO_TYPE_IO)
> +		return EINVAL; /* Deliberately positive */
> +
> +	/*
> +	 * n_gpios + 2 because the index of this _DSM function is 1-based and
> +	 * the first function is just a count.
> +	 */
> +	obj = acpi_evaluate_dsm_typed(int3472->adev->handle,
> +				      &int3472_gpio_guid, 0x00,
> +				      int3472->n_gpios + 2,
> +				      NULL, ACPI_TYPE_INTEGER);
> +
> +	if (!obj) {
> +		dev_warn(&int3472->adev->dev,
> +			 "No _DSM entry for this GPIO pin\n");
> +		return ENODEV;
> +	}
> +
> +	switch (obj->integer.value & 0xff) { /* low byte holds type data */
> +	case 0x00: /* Purpose unclear, possibly a reset GPIO pin */
> +		ret = int3472_map_gpio_to_sensor(int3472, ares, "reset");
> +		if (ret)
> +			dev_warn(&int3472->adev->dev,
> +				 "Failed to map reset pin to sensor\n");
> +
> +		break;
> +	case 0x01: /* Power regulators (we think) */
> +	case 0x0c:
> +		ret = int3472_register_regulator(int3472, ares);
> +		if (ret)
> +			dev_warn(&int3472->adev->dev,
> +				 "Failed to map regulator to sensor\n");
> +
> +		break;
> +	case 0x0b: /* Power regulators, but to a device separate to sensor */
> +		ret = int3472_register_regulator(int3472, ares);
> +		if (ret)
> +			dev_warn(&int3472->adev->dev,
> +				 "Failed to map regulator to sensor\n");
> +
> +		break;
> +	case 0x0d: /* Indicator LEDs */
> +		ret = int3472_map_gpio_to_sensor(int3472, ares, "indicator-led");
> +		if (ret)
> +			dev_warn(&int3472->adev->dev,
> +				 "Failed to map indicator led to sensor\n");
> +
> +		break;
> +	default:
> +		/* if we've gotten here, we're not sure what they are yet */
> +		dev_warn(&int3472->adev->dev,
> +			 "GPIO type 0x%llx unknown; the sensor may not work\n",
> +			 (obj->integer.value & 0xff));
> +		ret = EINVAL;
> +	}
> +
> +	int3472->n_gpios++;
> +	ACPI_FREE(obj);
> +	return abs(ret);
> +}
> +
> +static void int3472_parse_crs(struct int3472_device *int3472)
> +{
> +	struct list_head resource_list;
> +
> +	INIT_LIST_HEAD(&resource_list);
> +
> +	acpi_dev_get_resources(int3472->adev, &resource_list,
> +			       int3472_handle_gpio_resources, int3472);
> +
> +	acpi_dev_free_resource_list(&resource_list);
> +	gpiod_add_lookup_table(&int3472->gpios);
> +}
> +
> +static int int3472_add(struct acpi_device *adev)
> +{
> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> +	struct int3472_device *int3472;
> +	struct int3472_cldb cldb;
> +	union acpi_object *obj;
> +	acpi_status status;
> +	int ret = 0;
> +
> +	/*
> +	 * This driver is only intended to support "dummy" INT3472 devices
> +	 * which appear in ACPI designed for Windows. These are distinguishable
> +	 * from INT3472 entries representing an actual tps68470 PMIC through
> +	 * the presence of a CLDB buffer with a particular value set.
> +	 */
> +	status = acpi_evaluate_object(adev->handle, "CLDB", NULL, &buffer);
> +	if (ACPI_FAILURE(status))
> +		return -ENODEV;
> +
> +	obj = buffer.pointer;
> +	if (!obj) {
> +		dev_err(&adev->dev, "ACPI device has no CLDB object\n");
> +		return -ENODEV;
> +	}
> +
> +	if (obj->type != ACPI_TYPE_BUFFER) {
> +		dev_err(&adev->dev, "CLDB object is not an ACPI buffer\n");
> +		ret = -EINVAL;
> +		goto out_free_buff;
> +	}
> +
> +	if (obj->buffer.length > sizeof(cldb)) {
> +		dev_err(&adev->dev, "The CLDB buffer is too large\n");
> +		ret = -EINVAL;
> +		goto out_free_buff;
> +	}
> +
> +	memcpy(&cldb, obj->buffer.pointer, obj->buffer.length);
> +
> +	/*
> +	 * control_logic_type = 1 indicates this is a dummy INT3472 device of
> +	 * the kind we're looking for. If any other value then we shouldn't try
> +	 * to handle it
> +	 */
> +	if (cldb.control_logic_type != 1) {
> +		ret = -EINVAL;
> +		goto out_free_buff;
> +	}
> +
> +	/* Space for 4 GPIOs - one more than we've seen so far plus a null */
> +	int3472 = kzalloc(sizeof(*int3472) +
> +			 ((INT3472_MAX_SENSOR_GPIOS + 1) * sizeof(struct gpiod_lookup)),
> +			 GFP_KERNEL);
> +	if (!int3472) {
> +		ret = -ENOMEM;
> +		goto out_free_buff;
> +	}
> +
> +	int3472->adev = adev;
> +	adev->driver_data = int3472;
> +
> +	int3472->sensor = acpi_dev_get_next_dep_dev(adev, NULL);
> +	if (!int3472->sensor) {
> +		dev_err(&adev->dev,
> +			"This INT3472 entry seems to have no dependents.\n");
> +		ret = -ENODEV;
> +		goto out_free_int3472;
> +	}
> +
> +	int3472->gpios.dev_id = i2c_acpi_dev_name(int3472->sensor);
> +
> +	INIT_LIST_HEAD(&int3472->regulators);
> +
> +	int3472_parse_crs(int3472);
> +
> +	goto out_free_buff;
> +
> +out_free_int3472:
> +	kfree(int3472);
> +out_free_buff:
> +	kfree(buffer.pointer);
> +	return ret;
> +}
> +
> +static int int3472_remove(struct acpi_device *adev)
> +{
> +	struct int3472_gpio_regulator *reg;
> +	struct int3472_device *int3472;
> +
> +	int3472 = acpi_driver_data(adev);
> +
> +	acpi_dev_put(int3472->sensor);
> +	gpiod_remove_lookup_table(&int3472->gpios);
> +
> +	list_for_each_entry(reg, &int3472->regulators, list) {
> +		gpiod_put(reg->gpio);
> +		regulator_unregister(reg->rdev);
> +	}
> +
> +	kfree(int3472);
> +
> +	return 0;
> +}
> +
> +static const struct acpi_device_id int3472_device_id[] = {
> +	{ "INT3472", 0 },

The INT3472 _HID is really allocated for the tps68470 PMIC chip. It may not
be used by other drivers; people will want to build kernels where both of
these ACPI table layouts are functional.

Instead, I propose, that you add this as an option to the tps68470 driver
that figures out whether the ACPI device for the tps68470 device actually
describes something else, in a similar fashion you do with the cio2-bridge
driver. I think it may need a separate Kconfig option albeit this and
cio2-bridge cannot be used separately.

> +	{ },
> +};
> +MODULE_DEVICE_TABLE(acpi, int3472_device_id);
> +
> +static struct acpi_driver int3472_driver = {
> +	.name = "int3472",
> +	.ids = int3472_device_id,
> +	.ops = {
> +		.add = int3472_add,
> +		.remove = int3472_remove,
> +	},
> +	.owner = THIS_MODULE,
> +};
> +
> +module_acpi_driver(int3472_driver);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Dan Scally <djrscally@gmail.com>");
> +MODULE_DESCRIPTION("ACPI Driver for Discrete type INT3472 ACPI Devices");
> diff --git a/drivers/media/pci/intel/ipu3/int3472.h b/drivers/media/pci/intel/ipu3/int3472.h
> new file mode 100644
> index 000000000000..6964726e8e1f
> --- /dev/null
> +++ b/drivers/media/pci/intel/ipu3/int3472.h
> @@ -0,0 +1,96 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Author: Dan Scally <djrscally@gmail.com> */
> +#include <linux/regulator/machine.h>
> +
> +#define INT3472_MAX_SENSOR_GPIOS			3
> +#define GPIO_REGULATOR_NAME_LENGTH			17
> +#define GPIO_REGULATOR_SUPPLY_NAME_LENGTH		9
> +
> +#define INT3472_REGULATOR(_NAME, _SUPPLY, _ID, _OPS)	\
> +	((const struct regulator_desc) {		\
> +		.name = _NAME,				\
> +		.supply_name = _SUPPLY,			\
> +		.id = _ID,				\
> +		.type = REGULATOR_VOLTAGE,		\
> +		.ops = _OPS,				\
> +		.owner = THIS_MODULE,			\
> +	})
> +
> +const guid_t int3472_gpio_guid = GUID_INIT(0x79234640, 0x9e10, 0x4fea,
> +					     0xa5, 0xc1, 0xb5, 0xaa, 0x8b,
> +					     0x19, 0x75, 0x6f);
> +
> +const guid_t cio2_sensor_module_guid = GUID_INIT(0x822ace8f, 0x2814, 0x4174,
> +						 0xa5, 0x6b, 0x5f, 0x02, 0x9f,
> +						 0xe0, 0x79, 0xee);
> +
> +struct int3472_cldb {
> +	u8 version;
> +	/*
> +	 * control logic type
> +	 * 0: UNKNOWN
> +	 * 1: DISCRETE(CRD-D)
> +	 * 2: PMIC TPS68470
> +	 * 3: PMIC uP6641
> +	 */
> +	u8 control_logic_type;
> +	u8 control_logic_id;
> +	u8 sensor_card_sku;
> +	u8 reserved[28];
> +};
> +
> +struct int3472_device {
> +	struct acpi_device *adev;
> +	struct acpi_device *sensor;
> +
> +	unsigned int n_gpios; /* how many GPIOs have we seen */
> +
> +	unsigned int n_regulators;
> +	struct list_head regulators;
> +
> +	unsigned int n_sensor_gpios; /* how many have we mapped to sensor */
> +	struct gpiod_lookup_table gpios;
> +};
> +
> +struct int3472_gpio_regulator {
> +	char regulator_name[GPIO_REGULATOR_NAME_LENGTH];
> +	char supply_name[GPIO_REGULATOR_SUPPLY_NAME_LENGTH];
> +	struct gpio_desc *gpio;
> +	struct regulator_dev *rdev;
> +	struct regulator_desc rdesc;
> +	struct list_head list;
> +};
> +
> +struct int3472_sensor_regulator_map {
> +	char *sensor_module_name;
> +	unsigned int n_supplies;
> +	struct regulator_consumer_supply *supplies;
> +};
> +
> +/*
> + * Here follows platform specific mapping information that we can pass to
> + * regulator_init_data when we register our regulators. They're just mapped
> + * via index, I.E. the first regulator pin that the code finds for the
> + * i2c-OVTI2680:00 device is avdd, the second is dovdd and so on.
> + */
> +
> +static struct regulator_consumer_supply miix_510_ov2680[] = {
> +	{ "i2c-OVTI2680:00", "avdd" },
> +	{ "i2c-OVTI2680:00", "dovdd" },
> +};
> +
> +static struct regulator_consumer_supply surface_go2_ov5693[] = {
> +	{ "i2c-INT33BE:00", "avdd" },
> +	{ "i2c-INT33BE:00", "dovdd" },
> +};
> +
> +static struct regulator_consumer_supply surface_book_ov5693[] = {
> +	{ "i2c-INT33BE:00", "avdd" },
> +	{ "i2c-INT33BE:00", "dovdd" },
> +};
> +
> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
> +	{ "GNDF140809R", 2, miix_510_ov2680 },
> +	{ "YHCU", 2, surface_go2_ov5693 },
> +	{ "MSHW0070", 2, surface_book_ov5693 },
> +};

-- 
Kind regards,

Sakari Ailus

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 20:52   ` Sakari Ailus
@ 2020-11-30 23:06     ` Dan Scally
  2020-11-30 23:21       ` Laurent Pinchart
                         ` (2 more replies)
  0 siblings, 3 replies; 144+ messages in thread
From: Dan Scally @ 2020-11-30 23:06 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

Hi Sakari

On 30/11/2020 20:52, Sakari Ailus wrote:
>> +static const struct acpi_device_id int3472_device_id[] = {
>> +	{ "INT3472", 0 },
> The INT3472 _HID is really allocated for the tps68470 PMIC chip. It may not
> be used by other drivers; people will want to build kernels where both of
> these ACPI table layouts are functional.
>
> Instead, I propose, that you add this as an option to the tps68470 driver
> that figures out whether the ACPI device for the tps68470 device actually
> describes something else, in a similar fashion you do with the cio2-bridge
> driver. I think it may need a separate Kconfig option albeit this and
> cio2-bridge cannot be used separately.

It actually occurs to me that that may not work (I know I called that
out as an option we considered, but that was a while ago actually). The
reason I wasn't worried about the existing tps68470 driver binding to
these devices is that it's an i2c driver, and these dummy devices don't
have an I2cSerialBusV2, so no I2C device is created by them the kernel.


Won't that mean the tps68470 driver won't ever be probed for these devices?

>
>> +	{ },
>> +};
>> +MODULE_DEVICE_TABLE(acpi, int3472_device_id);
>> +
>> +static struct acpi_driver int3472_driver = {
>> +	.name = "int3472",
>> +	.ids = int3472_device_id,
>> +	.ops = {
>> +		.add = int3472_add,
>> +		.remove = int3472_remove,
>> +	},
>> +	.owner = THIS_MODULE,
>> +};
>> +
>> +module_acpi_driver(int3472_driver);
>> +
>> +MODULE_LICENSE("GPL v2");
>> +MODULE_AUTHOR("Dan Scally <djrscally@gmail.com>");
>> +MODULE_DESCRIPTION("ACPI Driver for Discrete type INT3472 ACPI Devices");
>> diff --git a/drivers/media/pci/intel/ipu3/int3472.h b/drivers/media/pci/intel/ipu3/int3472.h
>> new file mode 100644
>> index 000000000000..6964726e8e1f
>> --- /dev/null
>> +++ b/drivers/media/pci/intel/ipu3/int3472.h
>> @@ -0,0 +1,96 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/* Author: Dan Scally <djrscally@gmail.com> */
>> +#include <linux/regulator/machine.h>
>> +
>> +#define INT3472_MAX_SENSOR_GPIOS			3
>> +#define GPIO_REGULATOR_NAME_LENGTH			17
>> +#define GPIO_REGULATOR_SUPPLY_NAME_LENGTH		9
>> +
>> +#define INT3472_REGULATOR(_NAME, _SUPPLY, _ID, _OPS)	\
>> +	((const struct regulator_desc) {		\
>> +		.name = _NAME,				\
>> +		.supply_name = _SUPPLY,			\
>> +		.id = _ID,				\
>> +		.type = REGULATOR_VOLTAGE,		\
>> +		.ops = _OPS,				\
>> +		.owner = THIS_MODULE,			\
>> +	})
>> +
>> +const guid_t int3472_gpio_guid = GUID_INIT(0x79234640, 0x9e10, 0x4fea,
>> +					     0xa5, 0xc1, 0xb5, 0xaa, 0x8b,
>> +					     0x19, 0x75, 0x6f);
>> +
>> +const guid_t cio2_sensor_module_guid = GUID_INIT(0x822ace8f, 0x2814, 0x4174,
>> +						 0xa5, 0x6b, 0x5f, 0x02, 0x9f,
>> +						 0xe0, 0x79, 0xee);
>> +
>> +struct int3472_cldb {
>> +	u8 version;
>> +	/*
>> +	 * control logic type
>> +	 * 0: UNKNOWN
>> +	 * 1: DISCRETE(CRD-D)
>> +	 * 2: PMIC TPS68470
>> +	 * 3: PMIC uP6641
>> +	 */
>> +	u8 control_logic_type;
>> +	u8 control_logic_id;
>> +	u8 sensor_card_sku;
>> +	u8 reserved[28];
>> +};
>> +
>> +struct int3472_device {
>> +	struct acpi_device *adev;
>> +	struct acpi_device *sensor;
>> +
>> +	unsigned int n_gpios; /* how many GPIOs have we seen */
>> +
>> +	unsigned int n_regulators;
>> +	struct list_head regulators;
>> +
>> +	unsigned int n_sensor_gpios; /* how many have we mapped to sensor */
>> +	struct gpiod_lookup_table gpios;
>> +};
>> +
>> +struct int3472_gpio_regulator {
>> +	char regulator_name[GPIO_REGULATOR_NAME_LENGTH];
>> +	char supply_name[GPIO_REGULATOR_SUPPLY_NAME_LENGTH];
>> +	struct gpio_desc *gpio;
>> +	struct regulator_dev *rdev;
>> +	struct regulator_desc rdesc;
>> +	struct list_head list;
>> +};
>> +
>> +struct int3472_sensor_regulator_map {
>> +	char *sensor_module_name;
>> +	unsigned int n_supplies;
>> +	struct regulator_consumer_supply *supplies;
>> +};
>> +
>> +/*
>> + * Here follows platform specific mapping information that we can pass to
>> + * regulator_init_data when we register our regulators. They're just mapped
>> + * via index, I.E. the first regulator pin that the code finds for the
>> + * i2c-OVTI2680:00 device is avdd, the second is dovdd and so on.
>> + */
>> +
>> +static struct regulator_consumer_supply miix_510_ov2680[] = {
>> +	{ "i2c-OVTI2680:00", "avdd" },
>> +	{ "i2c-OVTI2680:00", "dovdd" },
>> +};
>> +
>> +static struct regulator_consumer_supply surface_go2_ov5693[] = {
>> +	{ "i2c-INT33BE:00", "avdd" },
>> +	{ "i2c-INT33BE:00", "dovdd" },
>> +};
>> +
>> +static struct regulator_consumer_supply surface_book_ov5693[] = {
>> +	{ "i2c-INT33BE:00", "avdd" },
>> +	{ "i2c-INT33BE:00", "dovdd" },
>> +};
>> +
>> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
>> +	{ "GNDF140809R", 2, miix_510_ov2680 },
>> +	{ "YHCU", 2, surface_go2_ov5693 },
>> +	{ "MSHW0070", 2, surface_book_ov5693 },
>> +};

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

* Re: [PATCH 04/18] software_node: Enforce parent before child ordering of nodes array for software_node_register_nodes()
  2020-11-30 16:12     ` Laurent Pinchart
@ 2020-11-30 23:10       ` Dan Scally
  0 siblings, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-11-30 23:10 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Laurent

On 30/11/2020 16:12, Laurent Pinchart wrote:
> On Mon, Nov 30, 2020 at 06:11:52PM +0200, Laurent Pinchart wrote:
>> Hi Daniel,
>>
>> Thank you for the patch.
>>
>> On Mon, Nov 30, 2020 at 01:31:15PM +0000, Daniel Scally wrote:
>>> Registering software_nodes with the .parent member set to point to a
>>> currently unregistered software_node has the potential for problems,
>>> so enforce parent -> child ordering in arrays passed to this function.
>>>
>>> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>>> ---
>>> Changes since RFC v3:
>>>
>>> 	Patch introduced
>>>
>>>  drivers/base/swnode.c | 15 +++++++++++----
>>>  1 file changed, 11 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
>>> index 615a0c93e116..af7930b3679e 100644
>>> --- a/drivers/base/swnode.c
>>> +++ b/drivers/base/swnode.c
>>> @@ -700,14 +700,21 @@ int software_node_register_nodes(const struct software_node *nodes)
>>>  	int i;
>>>  
>>>  	for (i = 0; nodes[i].name; i++) {
>>> +		if (nodes[i].parent)
>>> +			if (!software_node_to_swnode(nodes[i].parent)) {
>>> +				ret = -EINVAL;
>>> +				goto err_unregister_nodes;
>>> +			}
>>> +
>>>  		ret = software_node_register(&nodes[i]);
>>> -		if (ret) {
>>> -			software_node_unregister_nodes(nodes);
>>> -			return ret;
>>> -		}
>>> +		if (ret)
>>> +			goto err_unregister_nodes;
>>>  	}
>>>  
>>>  	return 0;
>> I'd add a blank line here.
>>
>> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> I spoke a bit too soon. Could you update the documentation of the
> function to explain this new requirement ?
Oops - of course, will do
>>> +err_unregister_nodes:
>>> +	software_node_unregister_nodes(nodes);
>>> +	return ret;
>>>  }
>>>  EXPORT_SYMBOL_GPL(software_node_register_nodes);
>>>  
>> -- 
>> Regards,
>>
>> Laurent Pinchart

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 16:17   ` Jean-Michel Hautbois
@ 2020-11-30 23:20     ` Dan Scally
  2020-12-01 18:31       ` Andy Shevchenko
  0 siblings, 1 reply; 144+ messages in thread
From: Dan Scally @ 2020-11-30 23:20 UTC (permalink / raw)
  To: Jean-Michel Hautbois, linux-kernel, linux-acpi, linux-gpio,
	linux-i2c, linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

Hi Jean-Michel

On 30/11/2020 16:17, Jean-Michel Hautbois wrote:
>> We're guessing as to the exact meaning of the function byte, but I
>> conclude they're something like this:
>>
>> 0x00 - probably a reset GPIO
>> 0x01 - regulator for the sensor
>> 0x0c - regulator for the sensor
>> 0x0b - regulator again, but for a VCM or EEPROM
> Is it possible that the ad5823 would be here, and controled by this bit ?

That's one of the devices Laurent guessed might be there yes; when that
GPIO line is toggled it causes an extra device to show on the i2c-bus,
but the ACPI table doesn't define an I2CSerialBusV2 for it. Instead it's
rolled under the sensor's entry, there's a second entry in _CRS for the
sensor that matches the address of the new device:


            Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
            {
                Name (SBUF, ResourceTemplate ()
                {
                    I2cSerialBusV2 (0x0036, ControllerInitiated, 0x00061A80,
                        AddressingMode7Bit, "\\_SB.PCI0.I2C2",
                        0x00, ResourceConsumer, , Exclusive,
                        )
                    I2cSerialBusV2 (0x000C, ControllerInitiated, 0x00061A80,
                        AddressingMode7Bit, "\\_SB.PCI0.I2C2",
                        0x00, ResourceConsumer, , Exclusive,
                        )
                })
                Return (SBUF) /* \_SB_.PCI0.CAM0._CRS.SBUF */
            }

So that's another thing we need to work on. At the moment it doesn't
exist as far as the kernel is concerned.

>> 0x0d - privacy led (only one we're totally confident of since we can see
>>        it happen!)
>>
>> After much internal debate I decided to write this as a standalone
>> acpi_driver. Alternative options we considered:
>>
>> 1. Squash all this into the cio2-bridge code, which I did originally write
>> but decided I didn't like.
>> 2. Extend the existing tps68470 mfd driver...they share an ACPI ID so this
>> kinda makes sense, but ultimately given there is no actual physical
>> tps68470 in the scenario this patch handles I decided I didn't like this
>> either.
>>
>>  MAINTAINERS                            |   7 +
>>  drivers/media/pci/intel/ipu3/Kconfig   |  14 +
>>  drivers/media/pci/intel/ipu3/Makefile  |   1 +
>>  drivers/media/pci/intel/ipu3/int3472.c | 381 +++++++++++++++++++++++++
>>  drivers/media/pci/intel/ipu3/int3472.h |  96 +++++++
>>  5 files changed, 499 insertions(+)
>>  create mode 100644 drivers/media/pci/intel/ipu3/int3472.c
>>  create mode 100644 drivers/media/pci/intel/ipu3/int3472.h
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 188559a0a610..d73471f9c2a3 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -8753,6 +8753,13 @@ L:	linux-crypto@vger.kernel.org
>>  S:	Maintained
>>  F:	drivers/crypto/inside-secure/
>>  
>> +INT3472 ACPI DEVICE DRIVER
>> +M:	Daniel Scally <djrscally@gmail.com>
>> +L:	linux-media@vger.kernel.org
>> +S:	Maintained
>> +F:	drivers/media/pci/intel/ipu3/int3472.c
>> +F:	drivers/media/pci/intel/ipu3/int3472.h
>> +
>>  INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
>>  M:	Mimi Zohar <zohar@linux.ibm.com>
>>  M:	Dmitry Kasatkin <dmitry.kasatkin@gmail.com>
>> diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
>> index 2b3350d042be..9dd3b280f821 100644
>> --- a/drivers/media/pci/intel/ipu3/Kconfig
>> +++ b/drivers/media/pci/intel/ipu3/Kconfig
>> @@ -34,3 +34,17 @@ config CIO2_BRIDGE
>>  		- Dell 7285
>>  
>>  	  If in doubt, say N here.
>> +
>> +config INT3472
>> +	tristate "INT3472 Dummy ACPI Device Driver"
>> +	depends on VIDEO_IPU3_CIO2
>> +	depends on ACPI && REGULATOR && GPIOLIB
>> +	help
>> +	  This module provides an ACPI driver for INT3472 devices that do not
>> +	  represent an actual physical tps68470 device.
>> +
>> +	  Say Y here if your device is a detachable / hybrid laptop that comes
>> +	  with Windows installed by the OEM.
>> +	  The module will be called int3472.
>> +
>> +	  If in doubt, say N here.
> Is there any issue if the tps68470 driver is also selected and probed ?
>
>> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
>> index 933777e6ea8a..2285947b2bd2 100644
>> --- a/drivers/media/pci/intel/ipu3/Makefile
>> +++ b/drivers/media/pci/intel/ipu3/Makefile
>> @@ -1,5 +1,6 @@
>>  # SPDX-License-Identifier: GPL-2.0-only
>>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
>> +obj-$(CONFIG_INT3472) += int3472.o
>>  
>>  ipu3-cio2-y += ipu3-cio2-main.o
>>  ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
>> diff --git a/drivers/media/pci/intel/ipu3/int3472.c b/drivers/media/pci/intel/ipu3/int3472.c
>> new file mode 100644
>> index 000000000000..6b0be75f7f35
>> --- /dev/null
>> +++ b/drivers/media/pci/intel/ipu3/int3472.c
>> @@ -0,0 +1,381 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/* Author: Dan Scally <djrscally@gmail.com> */
>> +#include <linux/acpi.h>
>> +#include <linux/gpio/consumer.h>
>> +#include <linux/gpio/machine.h>
>> +#include <linux/i2c.h>
>> +#include <linux/kernel.h>
>> +#include <linux/list.h>
>> +#include <linux/module.h>
>> +#include <linux/regulator/driver.h>
>> +
>> +#include "int3472.h"
>> +
>> +/*
>> + * The regulators have to have .ops to be valid, but the only ops we actually
>> + * support are .enable and .disable which are handled via .ena_gpiod. Pass an
>> + * empty struct to clear the check without lying about capabilities.
>> + */
>> +static const struct regulator_ops int3472_gpio_regulator_ops = { 0 };
>> +
>> +static int int3472_map_gpio_to_sensor(struct int3472_device *int3472,
>> +				      struct acpi_resource *ares, char *func)
>> +{
>> +	char *path = ares->data.gpio.resource_source.string_ptr;
>> +	struct gpiod_lookup table_entry;
>> +	struct acpi_device *adev;
>> +	acpi_handle handle;
>> +	acpi_status status;
>> +	int ret;
>> +
>> +	/* Make sure we don't overflow, and leave room for a terminator */
>> +	if (int3472->n_sensor_gpios >= INT3472_MAX_SENSOR_GPIOS) {
>> +		dev_warn(&int3472->sensor->dev, "Too many GPIOs mapped\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	/* Fetch ACPI handle for the GPIO chip  */
>> +	status = acpi_get_handle(NULL, path, &handle);
>> +	if (ACPI_FAILURE(status))
>> +		return -EINVAL;
>> +
>> +	ret = acpi_bus_get_device(handle, &adev);
>> +	if (ret)
>> +		return -ENODEV;
>> +
>> +	table_entry = (struct gpiod_lookup)GPIO_LOOKUP_IDX(acpi_dev_name(adev),
>> +							   ares->data.gpio.pin_table[0],
>> +							   func, 0, GPIO_ACTIVE_HIGH);
>> +
>> +	memcpy(&int3472->gpios.table[int3472->n_sensor_gpios], &table_entry,
>> +	       sizeof(table_entry));
>> +	int3472->n_sensor_gpios++;
>> +
>> +	return 0;
>> +}
>> +
>> +static struct int3472_sensor_regulator_map *
>> +int3472_get_sensor_supply_map(struct int3472_device *int3472)
>> +{
>> +	struct int3472_sensor_regulator_map *ret;
>> +	union acpi_object *obj;
>> +	unsigned int i;
>> +
>> +	/*
>> +	 * Sensor modules seem to be identified by a unique string. We use that
>> +	 * to make sure we pass the right device and supply names to the new
>> +	 * regulator's consumer_supplies
>> +	 */
>> +	obj = acpi_evaluate_dsm_typed(int3472->sensor->handle,
>> +				      &cio2_sensor_module_guid, 0x00,
>> +				      0x01, NULL, ACPI_TYPE_STRING);
>> +
>> +	if (!obj) {
>> +		dev_err(&int3472->sensor->dev,
>> +			"Failed to get sensor module string from _DSM\n");
>> +		return ERR_PTR(-ENODEV);
>> +	}
>> +
>> +	if (obj->string.type != ACPI_TYPE_STRING) {
>> +		dev_err(&int3472->sensor->dev,
>> +			"Sensor _DSM returned a non-string value\n");
>> +		ret = ERR_PTR(-EINVAL);
>> +		goto out_free_obj;
>> +	}
>> +
>> +	ret = ERR_PTR(-ENODEV);
>> +	for (i = 0; i < ARRAY_SIZE(int3472_sensor_regulator_maps); i++) {
>> +		if (!strcmp(int3472_sensor_regulator_maps[i].sensor_module_name,
>> +			    obj->string.pointer)) {
>> +			ret = &int3472_sensor_regulator_maps[i];
>> +			goto out_free_obj;
>> +		}
>> +	}
>> +
>> +out_free_obj:
>> +	ACPI_FREE(obj);
>> +	return ret;
>> +}
>> +
>> +static int int3472_register_regulator(struct int3472_device *int3472,
>> +				      struct acpi_resource *ares)
>> +{
>> +	char *path = ares->data.gpio.resource_source.string_ptr;
>> +	struct int3472_sensor_regulator_map *regulator_map;
>> +	struct regulator_init_data init_data = { };
>> +	struct int3472_gpio_regulator *regulator;
>> +	struct regulator_config cfg = { };
>> +	int ret;
>> +
>> +	/*
>> +	 * We lookup supply names from machine specific tables, based on a
>> +	 * unique identifier in the sensor's _DSM
>> +	 */
>> +	regulator_map = int3472_get_sensor_supply_map(int3472);
>> +	if (IS_ERR_OR_NULL(regulator_map)) {
>> +		dev_err(&int3472->sensor->dev,
>> +			"Found no supplies defined for this sensor\n");
>> +		return PTR_ERR(regulator_map);
>> +	}
>> +
>> +	if (int3472->n_regulators >= regulator_map->n_supplies) {
>> +		dev_err(&int3472->sensor->dev,
>> +			"All known supplies are already mapped\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	init_data.supply_regulator = NULL;
>> +	init_data.constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
>> +	init_data.num_consumer_supplies = 1;
>> +	init_data.consumer_supplies = &regulator_map->supplies[int3472->n_regulators];
>> +
>> +	regulator = kmalloc(sizeof(*regulator), GFP_KERNEL);
>> +	if (!regulator)
>> +		return -ENOMEM;
>> +
>> +	snprintf(regulator->regulator_name, GPIO_REGULATOR_NAME_LENGTH,
>> +		 "gpio-regulator-%d", int3472->n_regulators);
>> +	snprintf(regulator->supply_name, GPIO_REGULATOR_SUPPLY_NAME_LENGTH,
>> +		 "supply-%d", int3472->n_regulators);
>> +
>> +	regulator->rdesc = INT3472_REGULATOR(regulator->regulator_name,
>> +					     regulator->supply_name,
>> +					     int3472->n_regulators,
>> +					     &int3472_gpio_regulator_ops);
>> +
>> +	regulator->gpio = acpi_get_gpiod(path, ares->data.gpio.pin_table[0]);
>> +	if (IS_ERR(regulator->gpio)) {
>> +		ret = PTR_ERR(regulator->gpio);
>> +		goto err_free_regulator;
>> +	}
>> +
>> +	cfg.dev = &int3472->adev->dev;
>> +	cfg.init_data = &init_data;
>> +	cfg.ena_gpiod = regulator->gpio;
>> +
>> +	regulator->rdev = regulator_register(&regulator->rdesc, &cfg);
>> +	if (IS_ERR(regulator->rdev)) {
>> +		ret = PTR_ERR(regulator->rdev);
>> +		goto err_free_gpio;
>> +	}
>> +
>> +	list_add(&regulator->list, &int3472->regulators);
>> +	int3472->n_regulators++;
>> +
>> +	return 0;
>> +
>> +err_free_gpio:
>> +	gpiod_put(regulator->gpio);
>> +err_free_regulator:
>> +	kfree(regulator);
>> +
>> +	return ret;
>> +}
>> +
>> +static int int3472_handle_gpio_resources(struct acpi_resource *ares,
>> +					 void *data)
>> +{
>> +	struct int3472_device *int3472 = data;
>> +	union acpi_object *obj;
>> +	int ret = 0;
>> +
>> +	if (ares->type != ACPI_RESOURCE_TYPE_GPIO ||
>> +	    ares->data.gpio.connection_type != ACPI_RESOURCE_GPIO_TYPE_IO)
>> +		return EINVAL; /* Deliberately positive */
>> +
>> +	/*
>> +	 * n_gpios + 2 because the index of this _DSM function is 1-based and
>> +	 * the first function is just a count.
>> +	 */
>> +	obj = acpi_evaluate_dsm_typed(int3472->adev->handle,
>> +				      &int3472_gpio_guid, 0x00,
>> +				      int3472->n_gpios + 2,
>> +				      NULL, ACPI_TYPE_INTEGER);
>> +
>> +	if (!obj) {
>> +		dev_warn(&int3472->adev->dev,
>> +			 "No _DSM entry for this GPIO pin\n");
>> +		return ENODEV;
>> +	}
>> +
>> +	switch (obj->integer.value & 0xff) { /* low byte holds type data */
>> +	case 0x00: /* Purpose unclear, possibly a reset GPIO pin */
>> +		ret = int3472_map_gpio_to_sensor(int3472, ares, "reset");
>> +		if (ret)
>> +			dev_warn(&int3472->adev->dev,
>> +				 "Failed to map reset pin to sensor\n");
>> +
>> +		break;
>> +	case 0x01: /* Power regulators (we think) */
>> +	case 0x0c:
>> +		ret = int3472_register_regulator(int3472, ares);
>> +		if (ret)
>> +			dev_warn(&int3472->adev->dev,
>> +				 "Failed to map regulator to sensor\n");
>> +
>> +		break;
>> +	case 0x0b: /* Power regulators, but to a device separate to sensor */
>> +		ret = int3472_register_regulator(int3472, ares);
>> +		if (ret)
>> +			dev_warn(&int3472->adev->dev,
>> +				 "Failed to map regulator to sensor\n");
>> +
>> +		break;
>> +	case 0x0d: /* Indicator LEDs */
>> +		ret = int3472_map_gpio_to_sensor(int3472, ares, "indicator-led");
>> +		if (ret)
>> +			dev_warn(&int3472->adev->dev,
>> +				 "Failed to map indicator led to sensor\n");
>> +
>> +		break;
>> +	default:
>> +		/* if we've gotten here, we're not sure what they are yet */
>> +		dev_warn(&int3472->adev->dev,
>> +			 "GPIO type 0x%llx unknown; the sensor may not work\n",
>> +			 (obj->integer.value & 0xff));
>> +		ret = EINVAL;
>> +	}
>> +
>> +	int3472->n_gpios++;
>> +	ACPI_FREE(obj);
>> +	return abs(ret);
>> +}
>> +
>> +static void int3472_parse_crs(struct int3472_device *int3472)
>> +{
>> +	struct list_head resource_list;
>> +
>> +	INIT_LIST_HEAD(&resource_list);
>> +
>> +	acpi_dev_get_resources(int3472->adev, &resource_list,
>> +			       int3472_handle_gpio_resources, int3472);
>> +
>> +	acpi_dev_free_resource_list(&resource_list);
>> +	gpiod_add_lookup_table(&int3472->gpios);
>> +}
>> +
>> +static int int3472_add(struct acpi_device *adev)
>> +{
>> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
>> +	struct int3472_device *int3472;
>> +	struct int3472_cldb cldb;
>> +	union acpi_object *obj;
>> +	acpi_status status;
>> +	int ret = 0;
>> +
>> +	/*
>> +	 * This driver is only intended to support "dummy" INT3472 devices
>> +	 * which appear in ACPI designed for Windows. These are distinguishable
>> +	 * from INT3472 entries representing an actual tps68470 PMIC through
>> +	 * the presence of a CLDB buffer with a particular value set.
>> +	 */
>> +	status = acpi_evaluate_object(adev->handle, "CLDB", NULL, &buffer);
>> +	if (ACPI_FAILURE(status))
>> +		return -ENODEV;
>> +
>> +	obj = buffer.pointer;
>> +	if (!obj) {
>> +		dev_err(&adev->dev, "ACPI device has no CLDB object\n");
>> +		return -ENODEV;
>> +	}
>> +
>> +	if (obj->type != ACPI_TYPE_BUFFER) {
>> +		dev_err(&adev->dev, "CLDB object is not an ACPI buffer\n");
>> +		ret = -EINVAL;
>> +		goto out_free_buff;
>> +	}
>> +
>> +	if (obj->buffer.length > sizeof(cldb)) {
>> +		dev_err(&adev->dev, "The CLDB buffer is too large\n");
>> +		ret = -EINVAL;
>> +		goto out_free_buff;
>> +	}
>> +
>> +	memcpy(&cldb, obj->buffer.pointer, obj->buffer.length);
>> +
>> +	/*
>> +	 * control_logic_type = 1 indicates this is a dummy INT3472 device of
>> +	 * the kind we're looking for. If any other value then we shouldn't try
>> +	 * to handle it
>> +	 */
>> +	if (cldb.control_logic_type != 1) {
>> +		ret = -EINVAL;
>> +		goto out_free_buff;
>> +	}
>> +
>> +	/* Space for 4 GPIOs - one more than we've seen so far plus a null */
>> +	int3472 = kzalloc(sizeof(*int3472) +
>> +			 ((INT3472_MAX_SENSOR_GPIOS + 1) * sizeof(struct gpiod_lookup)),
>> +			 GFP_KERNEL);
>> +	if (!int3472) {
>> +		ret = -ENOMEM;
>> +		goto out_free_buff;
>> +	}
>> +
>> +	int3472->adev = adev;
>> +	adev->driver_data = int3472;
>> +
>> +	int3472->sensor = acpi_dev_get_next_dep_dev(adev, NULL);
>> +	if (!int3472->sensor) {
>> +		dev_err(&adev->dev,
>> +			"This INT3472 entry seems to have no dependents.\n");
>> +		ret = -ENODEV;
>> +		goto out_free_int3472;
>> +	}
>> +
>> +	int3472->gpios.dev_id = i2c_acpi_dev_name(int3472->sensor);
>> +
>> +	INIT_LIST_HEAD(&int3472->regulators);
>> +
>> +	int3472_parse_crs(int3472);
>> +
>> +	goto out_free_buff;
>> +
>> +out_free_int3472:
>> +	kfree(int3472);
>> +out_free_buff:
>> +	kfree(buffer.pointer);
>> +	return ret;
>> +}
>> +
>> +static int int3472_remove(struct acpi_device *adev)
>> +{
>> +	struct int3472_gpio_regulator *reg;
>> +	struct int3472_device *int3472;
>> +
>> +	int3472 = acpi_driver_data(adev);
>> +
>> +	acpi_dev_put(int3472->sensor);
>> +	gpiod_remove_lookup_table(&int3472->gpios);
>> +
>> +	list_for_each_entry(reg, &int3472->regulators, list) {
>> +		gpiod_put(reg->gpio);
>> +		regulator_unregister(reg->rdev);
>> +	}
>> +
>> +	kfree(int3472);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct acpi_device_id int3472_device_id[] = {
>> +	{ "INT3472", 0 },
>> +	{ },
>> +};
>> +MODULE_DEVICE_TABLE(acpi, int3472_device_id);
>> +
>> +static struct acpi_driver int3472_driver = {
>> +	.name = "int3472",
>> +	.ids = int3472_device_id,
>> +	.ops = {
>> +		.add = int3472_add,
>> +		.remove = int3472_remove,
>> +	},
>> +	.owner = THIS_MODULE,
>> +};
>> +
>> +module_acpi_driver(int3472_driver);
>> +
>> +MODULE_LICENSE("GPL v2");
>> +MODULE_AUTHOR("Dan Scally <djrscally@gmail.com>");
>> +MODULE_DESCRIPTION("ACPI Driver for Discrete type INT3472 ACPI Devices");
>> diff --git a/drivers/media/pci/intel/ipu3/int3472.h b/drivers/media/pci/intel/ipu3/int3472.h
>> new file mode 100644
>> index 000000000000..6964726e8e1f
>> --- /dev/null
>> +++ b/drivers/media/pci/intel/ipu3/int3472.h
>> @@ -0,0 +1,96 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/* Author: Dan Scally <djrscally@gmail.com> */
>> +#include <linux/regulator/machine.h>
>> +
>> +#define INT3472_MAX_SENSOR_GPIOS			3
>> +#define GPIO_REGULATOR_NAME_LENGTH			17
>> +#define GPIO_REGULATOR_SUPPLY_NAME_LENGTH		9
>> +
>> +#define INT3472_REGULATOR(_NAME, _SUPPLY, _ID, _OPS)	\
>> +	((const struct regulator_desc) {		\
>> +		.name = _NAME,				\
>> +		.supply_name = _SUPPLY,			\
>> +		.id = _ID,				\
>> +		.type = REGULATOR_VOLTAGE,		\
>> +		.ops = _OPS,				\
>> +		.owner = THIS_MODULE,			\
>> +	})
>> +
>> +const guid_t int3472_gpio_guid = GUID_INIT(0x79234640, 0x9e10, 0x4fea,
>> +					     0xa5, 0xc1, 0xb5, 0xaa, 0x8b,
>> +					     0x19, 0x75, 0x6f);
>> +
>> +const guid_t cio2_sensor_module_guid = GUID_INIT(0x822ace8f, 0x2814, 0x4174,
>> +						 0xa5, 0x6b, 0x5f, 0x02, 0x9f,
>> +						 0xe0, 0x79, 0xee);
>> +
>> +struct int3472_cldb {
>> +	u8 version;
>> +	/*
>> +	 * control logic type
>> +	 * 0: UNKNOWN
>> +	 * 1: DISCRETE(CRD-D)
>> +	 * 2: PMIC TPS68470
>> +	 * 3: PMIC uP6641
>> +	 */
>> +	u8 control_logic_type;
>> +	u8 control_logic_id;
>> +	u8 sensor_card_sku;
>> +	u8 reserved[28];
>> +};
>> +
>> +struct int3472_device {
>> +	struct acpi_device *adev;
>> +	struct acpi_device *sensor;
>> +
>> +	unsigned int n_gpios; /* how many GPIOs have we seen */
>> +
>> +	unsigned int n_regulators;
>> +	struct list_head regulators;
>> +
>> +	unsigned int n_sensor_gpios; /* how many have we mapped to sensor */
>> +	struct gpiod_lookup_table gpios;
>> +};
>> +
>> +struct int3472_gpio_regulator {
>> +	char regulator_name[GPIO_REGULATOR_NAME_LENGTH];
>> +	char supply_name[GPIO_REGULATOR_SUPPLY_NAME_LENGTH];
>> +	struct gpio_desc *gpio;
>> +	struct regulator_dev *rdev;
>> +	struct regulator_desc rdesc;
>> +	struct list_head list;
>> +};
>> +
>> +struct int3472_sensor_regulator_map {
>> +	char *sensor_module_name;
>> +	unsigned int n_supplies;
>> +	struct regulator_consumer_supply *supplies;
>> +};
>> +
>> +/*
>> + * Here follows platform specific mapping information that we can pass to
>> + * regulator_init_data when we register our regulators. They're just mapped
>> + * via index, I.E. the first regulator pin that the code finds for the
>> + * i2c-OVTI2680:00 device is avdd, the second is dovdd and so on.
>> + */
>> +
>> +static struct regulator_consumer_supply miix_510_ov2680[] = {
>> +	{ "i2c-OVTI2680:00", "avdd" },
>> +	{ "i2c-OVTI2680:00", "dovdd" },
>> +};
>> +
>> +static struct regulator_consumer_supply surface_go2_ov5693[] = {
>> +	{ "i2c-INT33BE:00", "avdd" },
>> +	{ "i2c-INT33BE:00", "dovdd" },
>> +};
>> +
>> +static struct regulator_consumer_supply surface_book_ov5693[] = {
>> +	{ "i2c-INT33BE:00", "avdd" },
>> +	{ "i2c-INT33BE:00", "dovdd" },
>> +};
>> +
>> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
>> +	{ "GNDF140809R", 2, miix_510_ov2680 },
>> +	{ "YHCU", 2, surface_go2_ov5693 },
>> +	{ "MSHW0070", 2, surface_book_ov5693 },
>> +};
>>
> Thanks,
> JM

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 23:06     ` Dan Scally
@ 2020-11-30 23:21       ` Laurent Pinchart
  2020-12-01  0:05         ` Dan Scally
  2020-12-01  6:44       ` Sakari Ailus
  2020-12-01 18:55       ` Andy Shevchenko
  2 siblings, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 23:21 UTC (permalink / raw)
  To: Dan Scally
  Cc: Sakari Ailus, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	andriy.shevchenko, linus.walleij, bgolaszewski, wsa, yong.zhi,
	sakari.ailus, bingbu.cao, tian.shu.qiu, mchehab, robert.moore,
	erik.kaneda, pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hello,

On Mon, Nov 30, 2020 at 11:06:03PM +0000, Dan Scally wrote:
> On 30/11/2020 20:52, Sakari Ailus wrote:
> >> +static const struct acpi_device_id int3472_device_id[] = {
> >> +	{ "INT3472", 0 },
> >
> > The INT3472 _HID is really allocated for the tps68470 PMIC chip. It may not
> > be used by other drivers; people will want to build kernels where both of
> > these ACPI table layouts are functional.

I actually don't think it is, at least not if you consider how Intel
uses it. It can mean TI TPS64870, uPI Semi uP6641Q, or "discrete
regulator". It's called an "Intel camera power management device" in
Windows if I remember correctly.

If we go in the direction of creating a platform driver for this ACPI
HID, it should be called accordingly (int3472, intel-camera-pmic, ...),
check the device type from the CLDB, and register the right device.

One Chrome OS platforms, INT3472 refers to the TPS64870 only, and the
ACPI device object doesn't have a CLDB. That's easy to detect, and we
can enable tps64870 support when there's no CLDB. Note that for the
TPS64870 case, when a CLDB is present, the kernel driver will need to
register regulators and clocks, while when no CLDB is present, it will
need to register an opregion as done today. That's yet another mode of
operation of this driver.

> > Instead, I propose, that you add this as an option to the tps68470 driver
> > that figures out whether the ACPI device for the tps68470 device actually
> > describes something else, in a similar fashion you do with the cio2-bridge
> > driver. I think it may need a separate Kconfig option albeit this and
> > cio2-bridge cannot be used separately.
> 
> It actually occurs to me that that may not work (I know I called that
> out as an option we considered, but that was a while ago actually). The
> reason I wasn't worried about the existing tps68470 driver binding to
> these devices is that it's an i2c driver, and these dummy devices don't
> have an I2cSerialBusV2, so no I2C device is created by them the kernel.
> 
> Won't that mean the tps68470 driver won't ever be probed for these devices?

I think we can create a platform driver in that case. The same module
can register multiple drivers (platform and I2C).

> >> +	{ },
> >> +};
> >> +MODULE_DEVICE_TABLE(acpi, int3472_device_id);
> >> +
> >> +static struct acpi_driver int3472_driver = {
> >> +	.name = "int3472",
> >> +	.ids = int3472_device_id,
> >> +	.ops = {
> >> +		.add = int3472_add,
> >> +		.remove = int3472_remove,
> >> +	},
> >> +	.owner = THIS_MODULE,
> >> +};
> >> +
> >> +module_acpi_driver(int3472_driver);
> >> +
> >> +MODULE_LICENSE("GPL v2");
> >> +MODULE_AUTHOR("Dan Scally <djrscally@gmail.com>");
> >> +MODULE_DESCRIPTION("ACPI Driver for Discrete type INT3472 ACPI Devices");
> >> diff --git a/drivers/media/pci/intel/ipu3/int3472.h b/drivers/media/pci/intel/ipu3/int3472.h
> >> new file mode 100644
> >> index 000000000000..6964726e8e1f
> >> --- /dev/null
> >> +++ b/drivers/media/pci/intel/ipu3/int3472.h
> >> @@ -0,0 +1,96 @@
> >> +/* SPDX-License-Identifier: GPL-2.0 */
> >> +/* Author: Dan Scally <djrscally@gmail.com> */
> >> +#include <linux/regulator/machine.h>
> >> +
> >> +#define INT3472_MAX_SENSOR_GPIOS			3
> >> +#define GPIO_REGULATOR_NAME_LENGTH			17
> >> +#define GPIO_REGULATOR_SUPPLY_NAME_LENGTH		9
> >> +
> >> +#define INT3472_REGULATOR(_NAME, _SUPPLY, _ID, _OPS)	\
> >> +	((const struct regulator_desc) {		\
> >> +		.name = _NAME,				\
> >> +		.supply_name = _SUPPLY,			\
> >> +		.id = _ID,				\
> >> +		.type = REGULATOR_VOLTAGE,		\
> >> +		.ops = _OPS,				\
> >> +		.owner = THIS_MODULE,			\
> >> +	})
> >> +
> >> +const guid_t int3472_gpio_guid = GUID_INIT(0x79234640, 0x9e10, 0x4fea,
> >> +					     0xa5, 0xc1, 0xb5, 0xaa, 0x8b,
> >> +					     0x19, 0x75, 0x6f);
> >> +
> >> +const guid_t cio2_sensor_module_guid = GUID_INIT(0x822ace8f, 0x2814, 0x4174,
> >> +						 0xa5, 0x6b, 0x5f, 0x02, 0x9f,
> >> +						 0xe0, 0x79, 0xee);
> >> +
> >> +struct int3472_cldb {
> >> +	u8 version;
> >> +	/*
> >> +	 * control logic type
> >> +	 * 0: UNKNOWN
> >> +	 * 1: DISCRETE(CRD-D)
> >> +	 * 2: PMIC TPS68470
> >> +	 * 3: PMIC uP6641
> >> +	 */
> >> +	u8 control_logic_type;
> >> +	u8 control_logic_id;
> >> +	u8 sensor_card_sku;
> >> +	u8 reserved[28];
> >> +};
> >> +
> >> +struct int3472_device {
> >> +	struct acpi_device *adev;
> >> +	struct acpi_device *sensor;
> >> +
> >> +	unsigned int n_gpios; /* how many GPIOs have we seen */
> >> +
> >> +	unsigned int n_regulators;
> >> +	struct list_head regulators;
> >> +
> >> +	unsigned int n_sensor_gpios; /* how many have we mapped to sensor */
> >> +	struct gpiod_lookup_table gpios;
> >> +};
> >> +
> >> +struct int3472_gpio_regulator {
> >> +	char regulator_name[GPIO_REGULATOR_NAME_LENGTH];
> >> +	char supply_name[GPIO_REGULATOR_SUPPLY_NAME_LENGTH];
> >> +	struct gpio_desc *gpio;
> >> +	struct regulator_dev *rdev;
> >> +	struct regulator_desc rdesc;
> >> +	struct list_head list;
> >> +};
> >> +
> >> +struct int3472_sensor_regulator_map {
> >> +	char *sensor_module_name;
> >> +	unsigned int n_supplies;
> >> +	struct regulator_consumer_supply *supplies;
> >> +};
> >> +
> >> +/*
> >> + * Here follows platform specific mapping information that we can pass to
> >> + * regulator_init_data when we register our regulators. They're just mapped
> >> + * via index, I.E. the first regulator pin that the code finds for the
> >> + * i2c-OVTI2680:00 device is avdd, the second is dovdd and so on.
> >> + */
> >> +
> >> +static struct regulator_consumer_supply miix_510_ov2680[] = {
> >> +	{ "i2c-OVTI2680:00", "avdd" },
> >> +	{ "i2c-OVTI2680:00", "dovdd" },
> >> +};
> >> +
> >> +static struct regulator_consumer_supply surface_go2_ov5693[] = {
> >> +	{ "i2c-INT33BE:00", "avdd" },
> >> +	{ "i2c-INT33BE:00", "dovdd" },
> >> +};
> >> +
> >> +static struct regulator_consumer_supply surface_book_ov5693[] = {
> >> +	{ "i2c-INT33BE:00", "avdd" },
> >> +	{ "i2c-INT33BE:00", "dovdd" },
> >> +};
> >> +
> >> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
> >> +	{ "GNDF140809R", 2, miix_510_ov2680 },
> >> +	{ "YHCU", 2, surface_go2_ov5693 },
> >> +	{ "MSHW0070", 2, surface_book_ov5693 },
> >> +};

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 20:07   ` Andy Shevchenko
@ 2020-11-30 23:32     ` Laurent Pinchart
  2020-12-01 15:55       ` Sakari Ailus
  2020-12-01 18:49       ` Andy Shevchenko
  2020-12-01  8:30     ` Dan Scally
  2021-01-07 23:55     ` Daniel Scally
  2 siblings, 2 replies; 144+ messages in thread
From: Laurent Pinchart @ 2020-11-30 23:32 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Andy,

On Mon, Nov 30, 2020 at 10:07:19PM +0200, Andy Shevchenko wrote:
> On Mon, Nov 30, 2020 at 01:31:29PM +0000, Daniel Scally wrote:
> > On platforms where ACPI is designed for use with Windows, resources
> > that are intended to be consumed by sensor devices are sometimes in
> > the _CRS of a dummy INT3472 device upon which the sensor depends. This
> > driver binds to the dummy acpi device (which does not represent a
> 
> acpi device -> acpi_device
> 
> > physical PMIC) and maps them into GPIO lines and regulators for use by
> > the sensor device instead.
> 
> ...
> 
> > This patch contains the bits of this process that we're least sure about.
> > The sensors in scope for this work are called out as dependent (in their
> > DSDT entry's _DEP) on a device with _HID INT3472. These come in at least
> > 2 kinds; those with an I2cSerialBusV2 entry (which we presume therefore
> > are legitimate tps68470 PMICs that need handling by those drivers - work
> > on that in the future). And those without an I2C device. For those without
> > an I2C device they instead have an array of GPIO pins defined in _CRS. So
> > for example, my Lenovo Miix 510's OVTI2680 sensor is dependent on one of
> > the _latter_ kind of INT3472 devices, with this _CRS:
> > 
> > Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
> > {
> >     Name (SBUF, ResourceTemplate ()
> >     {
> >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > 	    0x00, ResourceConsumer, ,
> >             )
> >             {   // Pin list
> >                 0x0079
> >             }
> >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > 	    0x00, ResourceConsumer, ,
> >             )
> >             {   // Pin list
> >                 0x007A
> >             }
> >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > 	    0x00, ResourceConsumer, ,
> >             )
> >             {   // Pin list
> >                 0x008F
> >             }
> >     })
> >     Return (SBUF) /* \_SB_.PCI0.PMI1._CRS.SBUF */
> > }
> > 
> > and the same device has a _DSM Method, which returns 32-bit ints where
> > the second lowest byte we noticed to match the pin numbers of the GPIO
> > lines:
> > 
> > Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
> > {
> >     If ((Arg0 == ToUUID ("79234640-9e10-4fea-a5c1-b5aa8b19756f")))
> >     {
> >         If ((Arg2 == One))
> >         {
> >             Return (0x03)
> >         }
> > 
> >         If ((Arg2 == 0x02))
> >         {
> >             Return (0x01007900)
> >         }
> > 
> >         If ((Arg2 == 0x03))
> >         {
> >             Return (0x01007A0C)
> >         }
> > 
> >         If ((Arg2 == 0x04))
> >         {
> >             Return (0x01008F01)
> >         }
> >     }
> > 
> >     Return (Zero)
> > }
> > 
> > We know that at least some of those pins have to be toggled active for the
> > sensor devices to be available in i2c, so the conclusion we came to was
> > that those GPIO entries assigned to the INT3472 device actually represent
> > GPIOs and regulators to be consumed by the sensors themselves. Tsuchiya
> > noticed that the lowest byte in the return values of the _DSM method
> > seemed to represent the type or function of the GPIO line, and we
> > confirmed that by testing on each surface device that GPIO lines where the
> > low byte in the _DSM entry for that pin was 0x0d controlled the privacy
> > LED of the cameras.
> > 
> > We're guessing as to the exact meaning of the function byte, but I
> > conclude they're something like this:
> > 
> > 0x00 - probably a reset GPIO
> > 0x01 - regulator for the sensor
> > 0x0c - regulator for the sensor
> > 0x0b - regulator again, but for a VCM or EEPROM
> > 0x0d - privacy led (only one we're totally confident of since we can see
> >        it happen!)
> 
> It's solely Windows driver design...
> Luckily I found some information and can clarify above table:
> 
> 0x00 Reset
> 0x01 Power down
> 0x0b Power enable
> 0x0c Clock enable
> 0x0d LED (active high)

That's very useful information ! Thank you.

> The above text perhaps should go somewhere under Documentation.

Or in the driver source code, but definitely somewhere else than in the
commit message.

> > After much internal debate I decided to write this as a standalone
> > acpi_driver. Alternative options we considered:
> > 
> > 1. Squash all this into the cio2-bridge code, which I did originally write
> > but decided I didn't like.
> > 2. Extend the existing tps68470 mfd driver...they share an ACPI ID so this
> > kinda makes sense, but ultimately given there is no actual physical
> > tps68470 in the scenario this patch handles I decided I didn't like this
> > either.
> 
> Looking to this I think the best is to create a module that can be consumed by tps68470 and separately.
> So, something near to it rather than under ipu3 hood.
> 
> You may use same ID's in both drivers (in PMIC less case it can be simple
> platform and thus they won't conflict), but both of them should provide GPIO
> resources for consumption.
> 
> So, something like
> 
>  tps68470.h with API to consume
>  split tps68470 to -core, -i2c parts
>  add int3472, which will serve for above and be standalone platform driver
>  update cio2-bridge accordingly
> 
> Would it be feasible?

Given that INT3472 means Intel camera power management device (that's
more or less the wording in Windows, I can double-check), would the
following make sense ?

A top-level module named intel-camera-pmic (or int3472, or ...) would
register two drivers, a platform driver and an I2C driver, to
accommodate for both cases ("discrete PMIC" that doesn't have an
I2cSerialBusV2, and TPS64870 or uP6641Q that are I2C devices). The probe
function would perform the following:

- If there's no CLDB, then the device uses the Chrome OS "ACPI
  bindings", and refers to a TPS64870. The code that exists in the
  kernel today (registering GPIOs, and registering an OpRegion to
  communicate with the power management code in the DSDT) would be
  activated.

- If there's a CLDB, then the device type would be retrieved from it:

  - If the device is a "discrete PMIC", the driver would register clocks
    and regulators controlled by GPIOs, and create clock, regulator and
    GPIO lookup entries for the sensor device that references the PMIC.

  - If the device is a TPS64870, the code that exists in the kernel
    today to register GPIOs would be activated, and new code would need
    to be written to register regulators and clocks.

  - If the device is a uP6641Q, a new driver will need to be written (I
    don't know on which devices this PMIC is used, so this can probably
    be deferred).

We can split this in multiple files and/or modules.

> ...
> 
> > +	table_entry = (struct gpiod_lookup)GPIO_LOOKUP_IDX(acpi_dev_name(adev),
> > +							   ares->data.gpio.pin_table[0],
> > +							   func, 0, GPIO_ACTIVE_HIGH);
> 
> You won't need this if you have regular INT3472 platform driver.
> Simple call there _DSM to map resources to the type and use devm_gpiod_get on
> consumer behalf. Thus, previous patch is not needed.

How does the consumer (the camera sensor) retrieve the GPIO though ? The
_DSM is in the PMIC device object, while the real consumer is the camera
sensor.

> ...
> 
> > +	case 0x01: /* Power regulators (we think) */
> > +	case 0x0c:
> > +	case 0x0b: /* Power regulators, but to a device separate to sensor */
> > +	case 0x0d: /* Indicator LEDs */
> 
> 
> Give names to those constants.
> 
> 	#define INT3472_GPIO_TYPE_RESET 0x00
> 	...
> 
> 
> > +static struct acpi_driver int3472_driver = {
> 
> No acpi_driver! Use platform_driver instead with plenty of examples all over
> the kernel.
> 
> > +	.name = "int3472",
> > +	.ids = int3472_device_id,
> > +	.ops = {
> > +		.add = int3472_add,
> > +		.remove = int3472_remove,
> > +	},
> 
> > +	.owner = THIS_MODULE,
> 
> No need
> 
> > +};
> 
> ...
> 
> > +const guid_t int3472_gpio_guid = GUID_INIT(0x79234640, 0x9e10, 0x4fea,
> > +					     0xa5, 0xc1, 0xb5, 0xaa, 0x8b,
> > +					     0x19, 0x75, 0x6f);
> > +
> > +const guid_t cio2_sensor_module_guid = GUID_INIT(0x822ace8f, 0x2814, 0x4174,
> > +						 0xa5, 0x6b, 0x5f, 0x02, 0x9f,
> > +						 0xe0, 0x79, 0xee);
> 
> Use more or less standard pattern for these, like
> 
> /* 79234640-9e10-4fea-a5c1b5aa8b19756f */
> const guid_t int3472_gpio_guid =
> 	GUID_INIT(0x79234640, 0x9e10, 0x4fea,
> 		  0xa5, 0xc1, 0xb5, 0xaa, 0x8b, 0x19, 0x75, 0x6f);
> 
> ...
> 
> > +static struct regulator_consumer_supply miix_510_ov2680[] = {
> > +	{ "i2c-OVTI2680:00", "avdd" },
> > +	{ "i2c-OVTI2680:00", "dovdd" },
> > +};
> 
> Can we use acpi_dev_first_match_dev() to get instance name out of their HIDs?
> 
> > +static struct regulator_consumer_supply surface_go2_ov5693[] = {
> > +	{ "i2c-INT33BE:00", "avdd" },
> > +	{ "i2c-INT33BE:00", "dovdd" },
> > +};
> > +
> > +static struct regulator_consumer_supply surface_book_ov5693[] = {
> > +	{ "i2c-INT33BE:00", "avdd" },
> > +	{ "i2c-INT33BE:00", "dovdd" },
> > +};
> 
> Ditto.
> 
> ...
> 
> > +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
> > +	{ "GNDF140809R", 2, miix_510_ov2680 },
> > +	{ "YHCU", 2, surface_go2_ov5693 },
> > +	{ "MSHW0070", 2, surface_book_ov5693 },
> > +};
> 
> Hmm... Usual way is to use DMI for that. I'm not sure above will not give us
> false positive matches.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 07/18] software_node: Add support for fwnode_graph*() family of functions
  2020-11-30 16:25   ` Laurent Pinchart
@ 2020-11-30 23:34     ` Dan Scally
  0 siblings, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-11-30 23:34 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Laurent

On 30/11/2020 16:25, Laurent Pinchart wrote:
> Hi Daniel and Heikki,
>
> Thank you for the patch.
>
> On Mon, Nov 30, 2020 at 01:31:18PM +0000, Daniel Scally wrote:
>> From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>>
>> From: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>>
> There seems to be one From: line too many. You can drop the one in the
> commit message, git-format-patch will add it automatically.
Ah! Thanks, sorry about that
>> This implements the remaining .graph_* callbacks in the
>> fwnode operations vector for the software nodes. That makes
> s/vector/structure/ ?
Yeah, sure.
>> the fwnode_graph*() functions available in the drivers also
>> when software nodes are used.
>>
>> The implementation tries to mimic the "OF graph" as much as
>> possible, but there is no support for the "reg" device
>> property. The ports will need to have the index in their
>> name which starts with "port" (for example "port0", "port1",
>> ...) and endpoints will use the index of the software node
>> that is given to them during creation. The port nodes can
>> also be grouped under a specially named "ports" subnode,
>> just like in DT, if necessary.
> I'm not very familiar with swnodes, but could we name ports port@n
> instead of portn to mimic OF nodes ?
Yes, I don't see any reason why not.
>
>> The remote-endpoints are reference properties under the
>> endpoint nodes that are named "remote-endpoint".
>>
>> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>> Co-developed-by: Daniel Scally <djrscally@gmail.com>
>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>> ---
>> changes since RFC v3:
>> 	- Simplified software_node_get_next_endpoint() a little
>> 	- Squared away references in software_node_get_next_endpoint()
>> 	and swnode_graph_find_next_port(), since they were affected by
>> 	the change to the earlier patch that had *get_next_child() also
>> 	put the previous reference.
>> 	- Dropped Andy's R-b, since the code changed.
>> changes in RFC v3:
>> 	- removed software_node_device_is_available
>> 	- moved the change to software_node_get_next_child to a separate
>> 	patch
>> 	- switched to use fwnode_handle_put() in graph_get_next_endpoint()
>> 	instead of software_node_put()
>>
>> changes in RFC v2:
>> 	- added software_node_device_is_available
>> 	- altered software_node_get_next_child to get references
>> 	- altered software_node_get_next_endpoint to release references
>> 	to ports and avoid passing invalid combinations of swnodes to
>> 	software_node_get_next_child
>> 	- altered swnode_graph_find_next_port to release port rather than
>> 	old
>>
>>  drivers/base/swnode.c | 110 +++++++++++++++++++++++++++++++++++++++++-
>>  1 file changed, 109 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
>> index 9bd0bb77ad5b..0c7a8d6b9ea8 100644
>> --- a/drivers/base/swnode.c
>> +++ b/drivers/base/swnode.c
>> @@ -540,6 +540,110 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
>>  	return 0;
>>  }
>>  
>> +static struct fwnode_handle *
>> +swnode_graph_find_next_port(const struct fwnode_handle *parent,
>> +			    struct fwnode_handle *port)
>> +{
>> +	struct fwnode_handle *old = port;
>> +
>> +	while ((port = software_node_get_next_child(parent, old))) {
>> +		if (!strncmp(to_swnode(port)->node->name, "port", 4))
>> +			return port;
>> +		old = port;
>> +	}
>> +
>> +	return NULL;
>> +}
>> +
>> +static struct fwnode_handle *
>> +software_node_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
>> +				      struct fwnode_handle *endpoint)
>> +{
>> +	struct swnode *swnode = to_swnode(fwnode);
>> +	struct fwnode_handle *old = endpoint;
>> +	struct fwnode_handle *parent;
>> +	struct fwnode_handle *port;
>> +
>> +	if (!swnode)
>> +		return NULL;
>> +
>> +	if (endpoint) {
>> +		port = software_node_get_parent(endpoint);
>> +		parent = software_node_get_parent(port);
>> +	} else {
>> +		parent = software_node_get_named_child_node(fwnode, "ports");
>> +		if (!parent)
>> +			parent = software_node_get(&swnode->fwnode);
>> +
>> +		port = swnode_graph_find_next_port(parent, NULL);
>> +	}
>> +
>> +	for (; port; port = swnode_graph_find_next_port(parent, port)) {
>> +		endpoint = software_node_get_next_child(port, old);
>> +		if (endpoint) {
>> +			fwnode_handle_put(port);
>> +			break;
>> +		}
>> +
>> +		/* No more endpoints for that port, so stop passing old */
>> +		old = NULL;
>> +	}
>> +
>> +	fwnode_handle_put(parent);
>> +
>> +	return endpoint;
>> +}
>> +
>> +static struct fwnode_handle *
>> +software_node_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
>> +{
>> +	struct swnode *swnode = to_swnode(fwnode);
>> +	const struct software_node_ref_args *ref;
>> +	const struct property_entry *prop;
>> +
>> +	if (!swnode)
>> +		return NULL;
>> +
>> +	prop = property_entry_get(swnode->node->properties, "remote-endpoint");
>> +	if (!prop || prop->type != DEV_PROP_REF || prop->is_inline)
>> +		return NULL;
>> +
>> +	ref = prop->pointer;
>> +
>> +	return software_node_get(software_node_fwnode(ref[0].node));
>> +}
>> +
>> +static struct fwnode_handle *
>> +software_node_graph_get_port_parent(struct fwnode_handle *fwnode)
>> +{
>> +	struct swnode *swnode = to_swnode(fwnode);
>> +	struct fwnode_handle *parent;
>> +
>> +	if (!strcmp(swnode->parent->node->name, "ports"))
>> +		parent = &swnode->parent->parent->fwnode;
>> +	else
>> +		parent = &swnode->parent->fwnode;
>> +
>> +	return software_node_get(parent);
>> +}
>> +
>> +static int
>> +software_node_graph_parse_endpoint(const struct fwnode_handle *fwnode,
>> +				   struct fwnode_endpoint *endpoint)
>> +{
>> +	struct swnode *swnode = to_swnode(fwnode);
>> +	int ret;
>> +
>> +	ret = kstrtou32(swnode->parent->node->name + 4, 10, &endpoint->port);
> If we use port@, s/4/5/. But I suppose we also want to support the case
> where a single port is used, with its name set to "port" ? The logic
> would then need to be a tad more complex. Not sure if the consistency is
> worth the additional complexity, up to you.
I'm conflicted; consistency is good but in my mind keeping the name as
"port@0" for a single port rather than dropping the suffix is the better
approach anyway.
>> +	if (ret)
>> +		return ret;
>> +
>> +	endpoint->id = swnode->id;
>> +	endpoint->local_fwnode = fwnode;
>> +
>> +	return 0;
>> +}
>> +
>>  static const struct fwnode_operations software_node_ops = {
>>  	.get = software_node_get,
>>  	.put = software_node_put,
>> @@ -551,7 +655,11 @@ static const struct fwnode_operations software_node_ops = {
>>  	.get_parent = software_node_get_parent,
>>  	.get_next_child_node = software_node_get_next_child,
>>  	.get_named_child_node = software_node_get_named_child_node,
>> -	.get_reference_args = software_node_get_reference_args
>> +	.get_reference_args = software_node_get_reference_args,
>> +	.graph_get_next_endpoint = software_node_graph_get_next_endpoint,
>> +	.graph_get_remote_endpoint = software_node_graph_get_remote_endpoint,
>> +	.graph_get_port_parent = software_node_graph_get_port_parent,
>> +	.graph_parse_endpoint = software_node_graph_parse_endpoint,
>>  };
>>  
>>  /* -------------------------------------------------------------------------- */

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

* Re: [PATCH 14/18] acpi: utils: Add function to fetch dependent acpi_devices
  2020-11-30 18:23   ` Andy Shevchenko
  2020-11-30 18:40     ` Laurent Pinchart
@ 2020-11-30 23:54     ` Dan Scally
  2020-12-01 15:10       ` Andy Shevchenko
  1 sibling, 1 reply; 144+ messages in thread
From: Dan Scally @ 2020-11-30 23:54 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

Hi Andy

On 30/11/2020 18:23, Andy Shevchenko wrote:
> On Mon, Nov 30, 2020 at 01:31:25PM +0000, Daniel Scally wrote:
>> ACPI devices declare themselves dependent on other devices via the _DEP
>> buffer. Fetching the dependee from dependent is a matter of parsing
>> _DEP, but currently there's no method to fetch dependent from dependee.
>> Add one, so we can parse sensors dependent on a PMIC from the PMIC's
>> acpi_driver.
> Do I understand correctly that it's an existing table provided by firmware that
> (ab)uses _DEP in such way? Note, the specification doesn't tell we may use it
> in this way, OTOH I don't remember if it strictly forbids such use.
>
> So, please elaborate in the commit message why you need this and pint out to
> the 6.5.8 "_DEP (Operation Region Dependencies)" which clearly says about
> OpRegions and that part already supported by ACPI in the Linux, if I'm not
> mistaken, need to refresh my memory.


Laurent's reply is good explanation, but for example see my Lenovo Miix
510's DSDT:


https://gist.githubusercontent.com/djrscally/e64d112180517352fa3392878b0f4a7d/raw/88b90b3ea4204fd7845257b6666fdade47cc2981/dsdt.dsl


Search OVTI2680 and OVTI5648 for the cameras. Both are dependent on
IN3472 devices (PMI0 and PMI1) which are the discrete type that we're
attempting to handle here.

>
> ...
>
>> +	handle = adev->handle;
>> +
>> +	if (!acpi_has_method(handle, "_DEP"))
>> +		return 0;
>> +
>> +	status = acpi_evaluate_reference(handle, "_DEP", NULL, &dep_handles);
>> +	if (ACPI_FAILURE(status))
>> +		return 0;
>> +
>> +	for (i = 0; i < dep_handles.count; i++) {
>> +		struct acpi_device_info *info;
>> +
>> +		status = acpi_get_object_info(dep_handles.handles[i], &info);
>> +		if (ACPI_FAILURE(status))
>> +			continue;
>> +
>> +		if (info->valid & ACPI_VALID_HID) {
>> +			ret = acpi_bus_get_device(dep_handles.handles[i], &candidate);
>> +			if (ret || !candidate) {
>> +				kfree(info);
>> +				continue;
>> +			}
>> +
>> +			if (candidate == dependee) {
>> +				acpi_dev_put(candidate);
>> +				kfree(info);
>> +				return 1;
>> +			}
>> +
>> +			kfree(info);
>> +		}
>> +	}
> Can you utilize (by moving to here and export for ACPI layer the
> acpi_lpss_dep()?
oooh, yes, I think I can. Thank you!

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 23:21       ` Laurent Pinchart
@ 2020-12-01  0:05         ` Dan Scally
  0 siblings, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-01  0:05 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Sakari Ailus, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	andriy.shevchenko, linus.walleij, bgolaszewski, wsa, yong.zhi,
	sakari.ailus, bingbu.cao, tian.shu.qiu, mchehab, robert.moore,
	erik.kaneda, pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus


On 30/11/2020 23:21, Laurent Pinchart wrote:
>>> Instead, I propose, that you add this as an option to the tps68470 driver
>>> that figures out whether the ACPI device for the tps68470 device actually
>>> describes something else, in a similar fashion you do with the cio2-bridge
>>> driver. I think it may need a separate Kconfig option albeit this and
>>> cio2-bridge cannot be used separately.
>> It actually occurs to me that that may not work (I know I called that
>> out as an option we considered, but that was a while ago actually). The
>> reason I wasn't worried about the existing tps68470 driver binding to
>> these devices is that it's an i2c driver, and these dummy devices don't
>> have an I2cSerialBusV2, so no I2C device is created by them the kernel.
>>
>> Won't that mean the tps68470 driver won't ever be probed for these devices?
> I think we can create a platform driver in that case. The same module
> can register multiple drivers (platform and I2C).
Ah, I follow. OK, that's an option then.

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

* Re: [PATCH 01/18] property: Return true in fwnode_device_is_available for node types that do not implement this operation
  2020-11-30 13:31 ` [PATCH 01/18] property: Return true in fwnode_device_is_available for node types that do not implement this operation Daniel Scally
  2020-11-30 16:05   ` Laurent Pinchart
  2020-11-30 17:21   ` Andy Shevchenko
@ 2020-12-01  3:12   ` Bingbu Cao
  2020-12-01  8:46     ` Dan Scally
  2 siblings, 1 reply; 144+ messages in thread
From: Bingbu Cao @ 2020-12-01  3:12 UTC (permalink / raw)
  To: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

Daniel, thanks for your patch.

On 11/30/20 9:31 PM, Daniel Scally wrote:
> Some types of fwnode_handle do not implement the device_is_available()
> check, such as those created by software_nodes. There isn't really a
> meaningful way to check for the availability of a device that doesn't
> actually exist, so if the check isn't implemented just assume that the
> "device" is present.
> 
> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes since RFC v3:
> 
> 	patch introduced
> 
>  drivers/base/property.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/base/property.c b/drivers/base/property.c
> index 4c43d30145c6..a5ca2306796f 100644
> --- a/drivers/base/property.c
> +++ b/drivers/base/property.c
> @@ -785,9 +785,14 @@ EXPORT_SYMBOL_GPL(fwnode_handle_put);
>  /**
>   * fwnode_device_is_available - check if a device is available for use
>   * @fwnode: Pointer to the fwnode of the device.
> + *
> + * For fwnode node types that don't implement the .device_is_available()
> + * operation, this function returns true.
>   */
>  bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
>  {
> +	if (!fwnode_has_op(fwnode, device_is_available))
> +		return true;

blank line here?

>  	return fwnode_call_bool_op(fwnode, device_is_available);
>  }
>  EXPORT_SYMBOL_GPL(fwnode_device_is_available);
> 

-- 
Best regards,
Bingbu Cao

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 23:06     ` Dan Scally
  2020-11-30 23:21       ` Laurent Pinchart
@ 2020-12-01  6:44       ` Sakari Ailus
  2020-12-01  8:08         ` Dan Scally
  2020-12-01 18:55       ` Andy Shevchenko
  2 siblings, 1 reply; 144+ messages in thread
From: Sakari Ailus @ 2020-12-01  6:44 UTC (permalink / raw)
  To: Dan Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

Hi Dan,

On Mon, Nov 30, 2020 at 11:06:03PM +0000, Dan Scally wrote:
> Hi Sakari
> 
> On 30/11/2020 20:52, Sakari Ailus wrote:
> >> +static const struct acpi_device_id int3472_device_id[] = {
> >> +	{ "INT3472", 0 },
> > The INT3472 _HID is really allocated for the tps68470 PMIC chip. It may not
> > be used by other drivers; people will want to build kernels where both of
> > these ACPI table layouts are functional.
> >
> > Instead, I propose, that you add this as an option to the tps68470 driver
> > that figures out whether the ACPI device for the tps68470 device actually
> > describes something else, in a similar fashion you do with the cio2-bridge
> > driver. I think it may need a separate Kconfig option albeit this and
> > cio2-bridge cannot be used separately.
> 
> It actually occurs to me that that may not work (I know I called that
> out as an option we considered, but that was a while ago actually). The
> reason I wasn't worried about the existing tps68470 driver binding to
> these devices is that it's an i2c driver, and these dummy devices don't
> have an I2cSerialBusV2, so no I2C device is created by them the kernel.
> 
> 
> Won't that mean the tps68470 driver won't ever be probed for these devices?

Oops. I missed this indeed was not an I²C driver. So please ignore the
comment.

So I guess this wouldn't be an actual problem. I'd still like to test this
on a system with tps68470, as the rest of the set.

-- 
Kind regards,

Sakari Ailus

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

* Re: [PATCH 10/18] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple source files retaining ipu3-cio2 name
  2020-11-30 13:31 ` [PATCH 10/18] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple source files retaining ipu3-cio2 name Daniel Scally
@ 2020-12-01  6:56   ` Bingbu Cao
  2020-12-01  7:07     ` Bingbu Cao
  0 siblings, 1 reply; 144+ messages in thread
From: Bingbu Cao @ 2020-12-01  6:56 UTC (permalink / raw)
  To: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

I see there will be multiple files, but there will be no conflict if keep as the main
file name unchanged, right? If so, I prefer keep as it was.

On 11/30/20 9:31 PM, Daniel Scally wrote:
> ipu3-cio2 driver needs extending with multiple files; rename the main
> source file and specify the renamed file in Makefile to accommodate that.
> 
> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> ---
> Changes since RFC v3:
> 
> 	- None
> 
>  drivers/media/pci/intel/ipu3/Makefile                          | 2 ++
>  drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} | 0
>  2 files changed, 2 insertions(+)
>  rename drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} (100%)
> 
> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
> index 98ddd5beafe0..429d516452e4 100644
> --- a/drivers/media/pci/intel/ipu3/Makefile
> +++ b/drivers/media/pci/intel/ipu3/Makefile
> @@ -1,2 +1,4 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
> +
> +ipu3-cio2-y += ipu3-cio2-main.o
> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> similarity index 100%
> rename from drivers/media/pci/intel/ipu3/ipu3-cio2.c
> rename to drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> 

-- 
Best regards,
Bingbu Cao

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

* Re: [PATCH 10/18] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple source files retaining ipu3-cio2 name
  2020-12-01  6:56   ` Bingbu Cao
@ 2020-12-01  7:07     ` Bingbu Cao
  0 siblings, 0 replies; 144+ messages in thread
From: Bingbu Cao @ 2020-12-01  7:07 UTC (permalink / raw)
  To: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

On 12/1/20 2:56 PM, Bingbu Cao wrote:
> I see there will be multiple files, but there will be no conflict if keep as the main
> file name unchanged, right? If so, I prefer keep as it was.

Oops, I notice you try to build all the files into single module, so please ignore my
comment above.

> 
> On 11/30/20 9:31 PM, Daniel Scally wrote:
>> ipu3-cio2 driver needs extending with multiple files; rename the main
>> source file and specify the renamed file in Makefile to accommodate that.
>>
>> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>> ---
>> Changes since RFC v3:
>>
>> 	- None
>>
>>  drivers/media/pci/intel/ipu3/Makefile                          | 2 ++
>>  drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} | 0
>>  2 files changed, 2 insertions(+)
>>  rename drivers/media/pci/intel/ipu3/{ipu3-cio2.c => ipu3-cio2-main.c} (100%)
>>
>> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
>> index 98ddd5beafe0..429d516452e4 100644
>> --- a/drivers/media/pci/intel/ipu3/Makefile
>> +++ b/drivers/media/pci/intel/ipu3/Makefile
>> @@ -1,2 +1,4 @@
>>  # SPDX-License-Identifier: GPL-2.0-only
>>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
>> +
>> +ipu3-cio2-y += ipu3-cio2-main.o
>> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
>> similarity index 100%
>> rename from drivers/media/pci/intel/ipu3/ipu3-cio2.c
>> rename to drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
>>
> 

-- 
Best regards,
Bingbu Cao

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01  6:44       ` Sakari Ailus
@ 2020-12-01  8:08         ` Dan Scally
  2020-12-01  8:09           ` Dan Scally
  2020-12-01 12:32           ` Sakari Ailus
  0 siblings, 2 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-01  8:08 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart


On 01/12/2020 06:44, Sakari Ailus wrote:
> Hi Dan,
>
> On Mon, Nov 30, 2020 at 11:06:03PM +0000, Dan Scally wrote:
>> Hi Sakari
>>
>> On 30/11/2020 20:52, Sakari Ailus wrote:
>>>> +static const struct acpi_device_id int3472_device_id[] = {
>>>> +	{ "INT3472", 0 },
>>> The INT3472 _HID is really allocated for the tps68470 PMIC chip. It may not
>>> be used by other drivers; people will want to build kernels where both of
>>> these ACPI table layouts are functional.
>>>
>>> Instead, I propose, that you add this as an option to the tps68470 driver
>>> that figures out whether the ACPI device for the tps68470 device actually
>>> describes something else, in a similar fashion you do with the cio2-bridge
>>> driver. I think it may need a separate Kconfig option albeit this and
>>> cio2-bridge cannot be used separately.
>> It actually occurs to me that that may not work (I know I called that
>> out as an option we considered, but that was a while ago actually). The
>> reason I wasn't worried about the existing tps68470 driver binding to
>> these devices is that it's an i2c driver, and these dummy devices don't
>> have an I2cSerialBusV2, so no I2C device is created by them the kernel.
>>
>>
>> Won't that mean the tps68470 driver won't ever be probed for these devices?
> Oops. I missed this indeed was not an I²C driver. So please ignore the
> comment.
>
> So I guess this wouldn't be an actual problem. I'd still like to test this
> on a system with tps68470, as the rest of the set.
On my Go2, it .probes() for the actual tps68740 (that machine has both
types of INT3472 device) but fails with EINVAL when it can't find the
CLDB buffer that these discrete type devices have. My understanding is
that means it's free for the actual tps68470 driver to grab the device;
although that's not happening because I had to blacklist that driver or
it stops the machine from booting at the moment - haven't gotten round
to investigating yet.

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01  8:08         ` Dan Scally
@ 2020-12-01  8:09           ` Dan Scally
  2020-12-01 12:32           ` Sakari Ailus
  1 sibling, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-01  8:09 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart


On 01/12/2020 08:08, Dan Scally wrote:
> On 01/12/2020 06:44, Sakari Ailus wrote:
>> Hi Dan,
>>
>> On Mon, Nov 30, 2020 at 11:06:03PM +0000, Dan Scally wrote:
>>> Hi Sakari
>>>
>>> On 30/11/2020 20:52, Sakari Ailus wrote:
>>>>> +static const struct acpi_device_id int3472_device_id[] = {
>>>>> +	{ "INT3472", 0 },
>>>> The INT3472 _HID is really allocated for the tps68470 PMIC chip. It may not
>>>> be used by other drivers; people will want to build kernels where both of
>>>> these ACPI table layouts are functional.
>>>>
>>>> Instead, I propose, that you add this as an option to the tps68470 driver
>>>> that figures out whether the ACPI device for the tps68470 device actually
>>>> describes something else, in a similar fashion you do with the cio2-bridge
>>>> driver. I think it may need a separate Kconfig option albeit this and
>>>> cio2-bridge cannot be used separately.
>>> It actually occurs to me that that may not work (I know I called that
>>> out as an option we considered, but that was a while ago actually). The
>>> reason I wasn't worried about the existing tps68470 driver binding to
>>> these devices is that it's an i2c driver, and these dummy devices don't
>>> have an I2cSerialBusV2, so no I2C device is created by them the kernel.
>>>
>>>
>>> Won't that mean the tps68470 driver won't ever be probed for these devices?
>> Oops. I missed this indeed was not an I²C driver. So please ignore the
>> comment.
>>
>> So I guess this wouldn't be an actual problem. I'd still like to test this
>> on a system with tps68470, as the rest of the set.
> On my Go2, it .probes() for the actual tps68740 (that machine has both
> types of INT3472 device) but fails with EINVAL when it can't find the
> CLDB buffer that these discrete type devices have. My understanding is
> that means it's free for the actual tps68470 driver to grab the device;
> although that's not happening because I had to blacklist that driver or
> it stops the machine from booting at the moment - haven't gotten round
> to investigating yet.
Though having said that, it looks like a separate driver like this is
the least favoured option anyway, so probably it's going to change anyway.

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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-30 20:35   ` Sakari Ailus
@ 2020-12-01  8:13     ` Dan Scally
  2020-12-01 15:06     ` Andy Shevchenko
  2020-12-15 10:28     ` Daniel Scally
  2 siblings, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-01  8:13 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Sakari

On 30/11/2020 20:35, Sakari Ailus wrote:
> Hi Daniel,
>
> Thanks for the update! This is starting to look really nice!
>
> Please still see my comments below.

Thanks!

>
> On Mon, Nov 30, 2020 at 01:31:24PM +0000, Daniel Scally wrote:
>> Currently on platforms designed for Windows, connections between CIO2 and
>> sensors are not properly defined in DSDT. This patch extends the ipu3-cio2
>> driver to compensate by building software_node connections, parsing the
>> connection properties from the sensor's SSDB buffer.
>>
>> Suggested-by: Jordan Hand <jorhand@linux.microsoft.com>
>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>> ---
>> Changes since RFC v3:
>>
>> 	- Removed almost all global variables, dynamically allocated
>> 	the cio2_bridge structure, plus a bunch of associated changes
>> 	like 
>> 	- Added a new function to ipu3-cio2-main.c to check for an 
>> 	existing fwnode_graph before calling cio2_bridge_init()
>> 	- Prefixed cio2_bridge_ to any variables and functions that
>> 	lacked it
>> 	- Assigned the new fwnode directly to the sensor's ACPI device
>> 	fwnode as secondary. This removes the requirement to delay until
>> 	the I2C devices are instantiated before ipu3-cio2 can probe, but
>> 	it has a side effect, which is that those devices then grab a ref
>> 	to the new software_node. This effectively prevents us from
>> 	unloading the driver, because we can't free the memory that they
>> 	live in whilst the device holds a reference to them. The work
>> 	around at the moment is to _not_ unregister the software_nodes
>> 	when ipu3-cio2 is unloaded; this becomes a one-time 'patch', that
>> 	is simply skipped if the module is reloaded.
>> 	- Moved the sensor's SSDB struct to be a member of cio2_sensor
>> 	- Replaced ints with unsigned ints where appropriate
>> 	- Iterated over all ACPI devices of a matching _HID rather than
>> 	just the first to ensure we handle a device with multiple sensors
>> 	of the same model.
>>
>>  MAINTAINERS                                   |   1 +
>>  drivers/media/pci/intel/ipu3/Kconfig          |  18 ++
>>  drivers/media/pci/intel/ipu3/Makefile         |   1 +
>>  drivers/media/pci/intel/ipu3/cio2-bridge.c    | 260 ++++++++++++++++++
>>  drivers/media/pci/intel/ipu3/cio2-bridge.h    | 108 ++++++++
>>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  27 ++
>>  drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   6 +
>>  7 files changed, 421 insertions(+)
>>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
>>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 9702b886d6a4..188559a0a610 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -8927,6 +8927,7 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
>>  M:	Yong Zhi <yong.zhi@intel.com>
>>  M:	Sakari Ailus <sakari.ailus@linux.intel.com>
>>  M:	Bingbu Cao <bingbu.cao@intel.com>
>> +M:	Dan Scally <djrscally@gmail.com>
>>  R:	Tianshu Qiu <tian.shu.qiu@intel.com>
>>  L:	linux-media@vger.kernel.org
>>  S:	Maintained
>> diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
>> index 82d7f17e6a02..2b3350d042be 100644
>> --- a/drivers/media/pci/intel/ipu3/Kconfig
>> +++ b/drivers/media/pci/intel/ipu3/Kconfig
>> @@ -16,3 +16,21 @@ config VIDEO_IPU3_CIO2
>>  	  Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2
>>  	  connected camera.
>>  	  The module will be called ipu3-cio2.
>> +
>> +config CIO2_BRIDGE
>> +	bool "IPU3 CIO2 Sensors Bridge"
>> +	depends on VIDEO_IPU3_CIO2
>> +	help
>> +	  This extension provides an API for the ipu3-cio2 driver to create
>> +	  connections to cameras that are hidden in SSDB buffer in ACPI. It
>> +	  can be used to enable support for cameras in detachable / hybrid
>> +	  devices that ship with Windows.
>> +
>> +	  Say Y here if your device is a detachable / hybrid laptop that comes
>> +	  with Windows installed by the OEM, for example:
>> +
>> +	  	- Microsoft Surface models (except Surface Pro 3)
>> +		- The Lenovo Miix line (for example the 510, 520, 710 and 720)
>> +		- Dell 7285
>> +
>> +	  If in doubt, say N here.
>> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
>> index 429d516452e4..933777e6ea8a 100644
>> --- a/drivers/media/pci/intel/ipu3/Makefile
>> +++ b/drivers/media/pci/intel/ipu3/Makefile
>> @@ -2,3 +2,4 @@
>>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
>>  
>>  ipu3-cio2-y += ipu3-cio2-main.o
>> +ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
>> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
>> new file mode 100644
>> index 000000000000..fd3f8ba07274
>> --- /dev/null
>> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
>> @@ -0,0 +1,260 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/* Author: Dan Scally <djrscally@gmail.com> */
>> +#include <linux/acpi.h>
>> +#include <linux/device.h>
>> +#include <linux/i2c.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/pci.h>
>> +#include <linux/property.h>
>> +#include <media/v4l2-subdev.h>
>> +
>> +#include "cio2-bridge.h"
>> +
>> +/*
>> + * Extend this array with ACPI Hardware ID's of devices known to be working.
>> + * Do not add a HID for a sensor that is not actually supported.
>> + */
>> +static const char * const cio2_supported_devices[] = {
>> +	"INT33BE",
>> +	"OVTI2680",
> I guess we don't have the known-good frequencies for the CSI-2 bus in
> firmware?
You mean link-frequencies? Indeed I can't see it anywhere in the buffers
from ACPI
> One option would be to put there what the drivers currently use. This
> assumes the support for these devices is, well, somewhat opportunistic but
> I guess there's no way around that right now at least.
>
> As the systems are laptops, they're likely somewhat less prone to EMI
> issues to begin with than mobile phones anyway.

Ah I guess that's a good point...and then add it as a property along
with the rest.


Ack to the other comments; I'll make those changes.



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 20:07   ` Andy Shevchenko
  2020-11-30 23:32     ` Laurent Pinchart
@ 2020-12-01  8:30     ` Dan Scally
  2020-12-01 18:54       ` Andy Shevchenko
  2021-01-07 23:55     ` Daniel Scally
  2 siblings, 1 reply; 144+ messages in thread
From: Dan Scally @ 2020-12-01  8:30 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus, Laurent Pinchart

Hi Andy, thanks for comments

On 30/11/2020 20:07, Andy Shevchenko wrote:
>> We know that at least some of those pins have to be toggled active for the
>> sensor devices to be available in i2c, so the conclusion we came to was
>> that those GPIO entries assigned to the INT3472 device actually represent
>> GPIOs and regulators to be consumed by the sensors themselves. Tsuchiya
>> noticed that the lowest byte in the return values of the _DSM method
>> seemed to represent the type or function of the GPIO line, and we
>> confirmed that by testing on each surface device that GPIO lines where the
>> low byte in the _DSM entry for that pin was 0x0d controlled the privacy
>> LED of the cameras.
>>
>> We're guessing as to the exact meaning of the function byte, but I
>> conclude they're something like this:
>>
>> 0x00 - probably a reset GPIO
>> 0x01 - regulator for the sensor
>> 0x0c - regulator for the sensor
>> 0x0b - regulator again, but for a VCM or EEPROM
>> 0x0d - privacy led (only one we're totally confident of since we can see
>>        it happen!)
> It's solely Windows driver design...
> Luckily I found some information and can clarify above table:
>
> 0x00 Reset
> 0x01 Power down
> 0x0b Power enable
> 0x0c Clock enable
> 0x0d LED (active high)
>
> The above text perhaps should go somewhere under Documentation.

Ah! That's really useful, thank you. We can handle the clock the same
way as regulators are being handled now, so that's no problem. And
likewise 0x01 for power down can just be mapped to the Sensor device
along with the reset pin and led pins. "Power enable" sounds like a
regulator indeed...it's not present on many (most) of our sensors
actually but that's not a problem for them of course as they'll just be
driven by the dummy regulators.


Thanks for the info


>
> ...
>
>> +	table_entry = (struct gpiod_lookup)GPIO_LOOKUP_IDX(acpi_dev_name(adev),
>> +							   ares->data.gpio.pin_table[0],
>> +							   func, 0, GPIO_ACTIVE_HIGH);
> You won't need this if you have regular INT3472 platform driver.
> Simple call there _DSM to map resources to the type and use devm_gpiod_get on
> consumer behalf. Thus, previous patch is not needed.
But the resources need to be available to the sensor devices; they're
basically in the wrong place. They should be in _CRS of the sensor,
rather than INT3472, so we need to map them across.
> ...
>
>> +static struct regulator_consumer_supply miix_510_ov2680[] = {
>> +	{ "i2c-OVTI2680:00", "avdd" },
>> +	{ "i2c-OVTI2680:00", "dovdd" },
>> +};
> Can we use acpi_dev_first_match_dev() to get instance name out of their HIDs?
We need the full i2c device name, which afaik isn't available from the
acpi_device
>> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
>> +	{ "GNDF140809R", 2, miix_510_ov2680 },
>> +	{ "YHCU", 2, surface_go2_ov5693 },
>> +	{ "MSHW0070", 2, surface_book_ov5693 },
>> +};
> Hmm... Usual way is to use DMI for that. I'm not sure above will not give us
> false positive matches.
I considered DMI too, no problem to switch to that if it's a better choice.

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

* Re: [PATCH 01/18] property: Return true in fwnode_device_is_available for node types that do not implement this operation
  2020-12-01  3:12   ` Bingbu Cao
@ 2020-12-01  8:46     ` Dan Scally
  0 siblings, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-01  8:46 UTC (permalink / raw)
  To: Bingbu Cao, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel
  Cc: rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

Hi Bingbu

On 01/12/2020 03:12, Bingbu Cao wrote:
> Daniel, thanks for your patch.
>
> On 11/30/20 9:31 PM, Daniel Scally wrote:
>> Some types of fwnode_handle do not implement the device_is_available()
>> check, such as those created by software_nodes. There isn't really a
>> meaningful way to check for the availability of a device that doesn't
>> actually exist, so if the check isn't implemented just assume that the
>> "device" is present.
>>
>> Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>> ---
>> Changes since RFC v3:
>>
>> 	patch introduced
>>
>>  drivers/base/property.c | 5 +++++
>>  1 file changed, 5 insertions(+)
>>
>> diff --git a/drivers/base/property.c b/drivers/base/property.c
>> index 4c43d30145c6..a5ca2306796f 100644
>> --- a/drivers/base/property.c
>> +++ b/drivers/base/property.c
>> @@ -785,9 +785,14 @@ EXPORT_SYMBOL_GPL(fwnode_handle_put);
>>  /**
>>   * fwnode_device_is_available - check if a device is available for use
>>   * @fwnode: Pointer to the fwnode of the device.
>> + *
>> + * For fwnode node types that don't implement the .device_is_available()
>> + * operation, this function returns true.
>>   */
>>  bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
>>  {
>> +	if (!fwnode_has_op(fwnode, device_is_available))
>> +		return true;
> blank line here?
Sure thing - I'll add one in
>>  	return fwnode_call_bool_op(fwnode, device_is_available);
>>  }
>>  EXPORT_SYMBOL_GPL(fwnode_device_is_available);
>>

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01  8:08         ` Dan Scally
  2020-12-01  8:09           ` Dan Scally
@ 2020-12-01 12:32           ` Sakari Ailus
  2020-12-01 12:40             ` Laurent Pinchart
  2020-12-01 12:48             ` Dan Scally
  1 sibling, 2 replies; 144+ messages in thread
From: Sakari Ailus @ 2020-12-01 12:32 UTC (permalink / raw)
  To: Dan Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

Hi Dan,

On Tue, Dec 01, 2020 at 08:08:26AM +0000, Dan Scally wrote:
> 
> On 01/12/2020 06:44, Sakari Ailus wrote:
> > Hi Dan,
> >
> > On Mon, Nov 30, 2020 at 11:06:03PM +0000, Dan Scally wrote:
> >> Hi Sakari
> >>
> >> On 30/11/2020 20:52, Sakari Ailus wrote:
> >>>> +static const struct acpi_device_id int3472_device_id[] = {
> >>>> +	{ "INT3472", 0 },
> >>> The INT3472 _HID is really allocated for the tps68470 PMIC chip. It may not
> >>> be used by other drivers; people will want to build kernels where both of
> >>> these ACPI table layouts are functional.
> >>>
> >>> Instead, I propose, that you add this as an option to the tps68470 driver
> >>> that figures out whether the ACPI device for the tps68470 device actually
> >>> describes something else, in a similar fashion you do with the cio2-bridge
> >>> driver. I think it may need a separate Kconfig option albeit this and
> >>> cio2-bridge cannot be used separately.
> >> It actually occurs to me that that may not work (I know I called that
> >> out as an option we considered, but that was a while ago actually). The
> >> reason I wasn't worried about the existing tps68470 driver binding to
> >> these devices is that it's an i2c driver, and these dummy devices don't
> >> have an I2cSerialBusV2, so no I2C device is created by them the kernel.
> >>
> >>
> >> Won't that mean the tps68470 driver won't ever be probed for these devices?
> > Oops. I missed this indeed was not an I²C driver. So please ignore the
> > comment.
> >
> > So I guess this wouldn't be an actual problem. I'd still like to test this
> > on a system with tps68470, as the rest of the set.
> On my Go2, it .probes() for the actual tps68740 (that machine has both
> types of INT3472 device) but fails with EINVAL when it can't find the
> CLDB buffer that these discrete type devices have. My understanding is
> that means it's free for the actual tps68470 driver to grab the device;
> although that's not happening because I had to blacklist that driver or
> it stops the machine from booting at the moment - haven't gotten round
> to investigating yet.

Oh, then the problem is actually there. If it probes the tps68470 driver on
the systems with Windows ACPI tables, then it should be that driver which
works with the Windows ACPI tables, too.

Checking for random objects such as CLDB in multiple drivers and returning
an error based on them being there or not wouldn't be exactly neat.
Although I'm not sure thare are options that are obviosly pretty here. I
wouldn't two separate drivers checking for e.g. CLDB (tps68470 + this one).

The tps68470 driver is an MFD driver that instantiates a number of platform
devices. Alternatively, if you make this one a platform device, you can, in
case the CLDB (or whatever object) is present, in the tps68470 driver
instantiate a device for this driver instead of the rest.

So I'd think what matters is that both drivers can be selected at the same
time but the user does not need to manually select them. Both ways could
work I guess?

-- 
Kind regards,

Sakari Ailus

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 12:32           ` Sakari Ailus
@ 2020-12-01 12:40             ` Laurent Pinchart
  2020-12-01 12:44               ` Sakari Ailus
  2020-12-01 12:48             ` Dan Scally
  1 sibling, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-12-01 12:40 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Dan Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	andriy.shevchenko, linus.walleij, bgolaszewski, wsa, yong.zhi,
	sakari.ailus, bingbu.cao, tian.shu.qiu, mchehab, robert.moore,
	erik.kaneda, pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Sakari,

On Tue, Dec 01, 2020 at 02:32:44PM +0200, Sakari Ailus wrote:
> On Tue, Dec 01, 2020 at 08:08:26AM +0000, Dan Scally wrote:
> > On 01/12/2020 06:44, Sakari Ailus wrote:
> > > On Mon, Nov 30, 2020 at 11:06:03PM +0000, Dan Scally wrote:
> > >> On 30/11/2020 20:52, Sakari Ailus wrote:
> > >>>> +static const struct acpi_device_id int3472_device_id[] = {
> > >>>> +	{ "INT3472", 0 },
> > >>>
> > >>> The INT3472 _HID is really allocated for the tps68470 PMIC chip. It may not
> > >>> be used by other drivers; people will want to build kernels where both of
> > >>> these ACPI table layouts are functional.
> > >>>
> > >>> Instead, I propose, that you add this as an option to the tps68470 driver
> > >>> that figures out whether the ACPI device for the tps68470 device actually
> > >>> describes something else, in a similar fashion you do with the cio2-bridge
> > >>> driver. I think it may need a separate Kconfig option albeit this and
> > >>> cio2-bridge cannot be used separately.
> > >>
> > >> It actually occurs to me that that may not work (I know I called that
> > >> out as an option we considered, but that was a while ago actually). The
> > >> reason I wasn't worried about the existing tps68470 driver binding to
> > >> these devices is that it's an i2c driver, and these dummy devices don't
> > >> have an I2cSerialBusV2, so no I2C device is created by them the kernel.
> > >>
> > >> Won't that mean the tps68470 driver won't ever be probed for these devices?
> > >
> > > Oops. I missed this indeed was not an I²C driver. So please ignore the
> > > comment.
> > >
> > > So I guess this wouldn't be an actual problem. I'd still like to test this
> > > on a system with tps68470, as the rest of the set.
> >
> > On my Go2, it .probes() for the actual tps68740 (that machine has both
> > types of INT3472 device) but fails with EINVAL when it can't find the
> > CLDB buffer that these discrete type devices have. My understanding is
> > that means it's free for the actual tps68470 driver to grab the device;
> > although that's not happening because I had to blacklist that driver or
> > it stops the machine from booting at the moment - haven't gotten round
> > to investigating yet.
> 
> Oh, then the problem is actually there. If it probes the tps68470 driver on
> the systems with Windows ACPI tables, then it should be that driver which
> works with the Windows ACPI tables, too.
> 
> Checking for random objects such as CLDB in multiple drivers and returning
> an error based on them being there or not wouldn't be exactly neat.
> Although I'm not sure thare are options that are obviosly pretty here. I
> wouldn't two separate drivers checking for e.g. CLDB (tps68470 + this one).
> 
> The tps68470 driver is an MFD driver that instantiates a number of platform
> devices. Alternatively, if you make this one a platform device, you can, in
> case the CLDB (or whatever object) is present, in the tps68470 driver
> instantiate a device for this driver instead of the rest.
> 
> So I'd think what matters is that both drivers can be selected at the same
> time but the user does not need to manually select them. Both ways could
> work I guess?

Let's make it simpler instead of creating lots of devices. Here's what
I've proposed in a different e-mail in this thread.

> Given that INT3472 means Intel camera power management device (that's
> more or less the wording in Windows, I can double-check), would the
> following make sense ?
> 
> A top-level module named intel-camera-pmic (or int3472, or ...) would
> register two drivers, a platform driver and an I2C driver, to
> accommodate for both cases ("discrete PMIC" that doesn't have an
> I2cSerialBusV2, and TPS64870 or uP6641Q that are I2C devices). The probe
> function would perform the following:
> 
> - If there's no CLDB, then the device uses the Chrome OS "ACPI
>   bindings", and refers to a TPS64870. The code that exists in the
>   kernel today (registering GPIOs, and registering an OpRegion to
>   communicate with the power management code in the DSDT) would be
>   activated.
> 
> - If there's a CLDB, then the device type would be retrieved from it:
> 
>   - If the device is a "discrete PMIC", the driver would register clocks
>     and regulators controlled by GPIOs, and create clock, regulator and
>     GPIO lookup entries for the sensor device that references the PMIC.
> 
>   - If the device is a TPS64870, the code that exists in the kernel
>     today to register GPIOs would be activated, and new code would need
>     to be written to register regulators and clocks.
> 
>   - If the device is a uP6641Q, a new driver will need to be written (I
>     don't know on which devices this PMIC is used, so this can probably
>     be deferred).
> 
> We can split this in multiple files and/or modules.

Could you reply to 20201130233232.GD25713@pendragon.ideasonboard.com to
avoid splitting the conversation ?

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 12:40             ` Laurent Pinchart
@ 2020-12-01 12:44               ` Sakari Ailus
  0 siblings, 0 replies; 144+ messages in thread
From: Sakari Ailus @ 2020-12-01 12:44 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Dan Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	andriy.shevchenko, linus.walleij, bgolaszewski, wsa, yong.zhi,
	sakari.ailus, bingbu.cao, tian.shu.qiu, mchehab, robert.moore,
	erik.kaneda, pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Tue, Dec 01, 2020 at 02:40:32PM +0200, Laurent Pinchart wrote:
> Hi Sakari,
> 
> On Tue, Dec 01, 2020 at 02:32:44PM +0200, Sakari Ailus wrote:
> > On Tue, Dec 01, 2020 at 08:08:26AM +0000, Dan Scally wrote:
> > > On 01/12/2020 06:44, Sakari Ailus wrote:
> > > > On Mon, Nov 30, 2020 at 11:06:03PM +0000, Dan Scally wrote:
> > > >> On 30/11/2020 20:52, Sakari Ailus wrote:
> > > >>>> +static const struct acpi_device_id int3472_device_id[] = {
> > > >>>> +	{ "INT3472", 0 },
> > > >>>
> > > >>> The INT3472 _HID is really allocated for the tps68470 PMIC chip. It may not
> > > >>> be used by other drivers; people will want to build kernels where both of
> > > >>> these ACPI table layouts are functional.
> > > >>>
> > > >>> Instead, I propose, that you add this as an option to the tps68470 driver
> > > >>> that figures out whether the ACPI device for the tps68470 device actually
> > > >>> describes something else, in a similar fashion you do with the cio2-bridge
> > > >>> driver. I think it may need a separate Kconfig option albeit this and
> > > >>> cio2-bridge cannot be used separately.
> > > >>
> > > >> It actually occurs to me that that may not work (I know I called that
> > > >> out as an option we considered, but that was a while ago actually). The
> > > >> reason I wasn't worried about the existing tps68470 driver binding to
> > > >> these devices is that it's an i2c driver, and these dummy devices don't
> > > >> have an I2cSerialBusV2, so no I2C device is created by them the kernel.
> > > >>
> > > >> Won't that mean the tps68470 driver won't ever be probed for these devices?
> > > >
> > > > Oops. I missed this indeed was not an I²C driver. So please ignore the
> > > > comment.
> > > >
> > > > So I guess this wouldn't be an actual problem. I'd still like to test this
> > > > on a system with tps68470, as the rest of the set.
> > >
> > > On my Go2, it .probes() for the actual tps68740 (that machine has both
> > > types of INT3472 device) but fails with EINVAL when it can't find the
> > > CLDB buffer that these discrete type devices have. My understanding is
> > > that means it's free for the actual tps68470 driver to grab the device;
> > > although that's not happening because I had to blacklist that driver or
> > > it stops the machine from booting at the moment - haven't gotten round
> > > to investigating yet.
> > 
> > Oh, then the problem is actually there. If it probes the tps68470 driver on
> > the systems with Windows ACPI tables, then it should be that driver which
> > works with the Windows ACPI tables, too.
> > 
> > Checking for random objects such as CLDB in multiple drivers and returning
> > an error based on them being there or not wouldn't be exactly neat.
> > Although I'm not sure thare are options that are obviosly pretty here. I
> > wouldn't two separate drivers checking for e.g. CLDB (tps68470 + this one).
> > 
> > The tps68470 driver is an MFD driver that instantiates a number of platform
> > devices. Alternatively, if you make this one a platform device, you can, in
> > case the CLDB (or whatever object) is present, in the tps68470 driver
> > instantiate a device for this driver instead of the rest.
> > 
> > So I'd think what matters is that both drivers can be selected at the same
> > time but the user does not need to manually select them. Both ways could
> > work I guess?
> 
> Let's make it simpler instead of creating lots of devices. Here's what
> I've proposed in a different e-mail in this thread.
> 
> > Given that INT3472 means Intel camera power management device (that's
> > more or less the wording in Windows, I can double-check), would the
> > following make sense ?
> > 
> > A top-level module named intel-camera-pmic (or int3472, or ...) would
> > register two drivers, a platform driver and an I2C driver, to
> > accommodate for both cases ("discrete PMIC" that doesn't have an
> > I2cSerialBusV2, and TPS64870 or uP6641Q that are I2C devices). The probe
> > function would perform the following:
> > 
> > - If there's no CLDB, then the device uses the Chrome OS "ACPI
> >   bindings", and refers to a TPS64870. The code that exists in the
> >   kernel today (registering GPIOs, and registering an OpRegion to
> >   communicate with the power management code in the DSDT) would be
> >   activated.
> > 
> > - If there's a CLDB, then the device type would be retrieved from it:
> > 
> >   - If the device is a "discrete PMIC", the driver would register clocks
> >     and regulators controlled by GPIOs, and create clock, regulator and
> >     GPIO lookup entries for the sensor device that references the PMIC.
> > 
> >   - If the device is a TPS64870, the code that exists in the kernel
> >     today to register GPIOs would be activated, and new code would need
> >     to be written to register regulators and clocks.
> > 
> >   - If the device is a uP6641Q, a new driver will need to be written (I
> >     don't know on which devices this PMIC is used, so this can probably
> >     be deferred).
> > 
> > We can split this in multiple files and/or modules.
> 
> Could you reply to 20201130233232.GD25713@pendragon.ideasonboard.com to
> avoid splitting the conversation ?

Yeah... I hadn't gotten that far yet. :-)

-- 
Sakari Ailus

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 12:32           ` Sakari Ailus
  2020-12-01 12:40             ` Laurent Pinchart
@ 2020-12-01 12:48             ` Dan Scally
  2020-12-01 19:01               ` Andy Shevchenko
  1 sibling, 1 reply; 144+ messages in thread
From: Dan Scally @ 2020-12-01 12:48 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart


On 01/12/2020 12:32, Sakari Ailus wrote:
> Hi Dan,
>
> On Tue, Dec 01, 2020 at 08:08:26AM +0000, Dan Scally wrote:
>> On 01/12/2020 06:44, Sakari Ailus wrote:
>>> Hi Dan,
>>>
>>> On Mon, Nov 30, 2020 at 11:06:03PM +0000, Dan Scally wrote:
>>>> Hi Sakari
>>>>
>>>> On 30/11/2020 20:52, Sakari Ailus wrote:
>>>>>> +static const struct acpi_device_id int3472_device_id[] = {
>>>>>> +	{ "INT3472", 0 },
>>>>> The INT3472 _HID is really allocated for the tps68470 PMIC chip. It may not
>>>>> be used by other drivers; people will want to build kernels where both of
>>>>> these ACPI table layouts are functional.
>>>>>
>>>>> Instead, I propose, that you add this as an option to the tps68470 driver
>>>>> that figures out whether the ACPI device for the tps68470 device actually
>>>>> describes something else, in a similar fashion you do with the cio2-bridge
>>>>> driver. I think it may need a separate Kconfig option albeit this and
>>>>> cio2-bridge cannot be used separately.
>>>> It actually occurs to me that that may not work (I know I called that
>>>> out as an option we considered, but that was a while ago actually). The
>>>> reason I wasn't worried about the existing tps68470 driver binding to
>>>> these devices is that it's an i2c driver, and these dummy devices don't
>>>> have an I2cSerialBusV2, so no I2C device is created by them the kernel.
>>>>
>>>>
>>>> Won't that mean the tps68470 driver won't ever be probed for these devices?
>>> Oops. I missed this indeed was not an I²C driver. So please ignore the
>>> comment.
>>>
>>> So I guess this wouldn't be an actual problem. I'd still like to test this
>>> on a system with tps68470, as the rest of the set.
>> On my Go2, it .probes() for the actual tps68740 (that machine has both
>> types of INT3472 device) but fails with EINVAL when it can't find the
>> CLDB buffer that these discrete type devices have. My understanding is
>> that means it's free for the actual tps68470 driver to grab the device;
>> although that's not happening because I had to blacklist that driver or
>> it stops the machine from booting at the moment - haven't gotten round
>> to investigating yet.
> Oh, then the problem is actually there. If it probes the tps68470 driver on
> the systems with Windows ACPI tables, then it should be that driver which
> works with the Windows ACPI tables, too.
Sorry, clarification here: The INT3472 driver in patch #18 runs probe()
for the device representing a physical tps68470, but then -EINVAL's. The
existing tps68470 mfd driver doesn't probe() for the dummy INT3472 device.

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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-30 20:35   ` Sakari Ailus
  2020-12-01  8:13     ` Dan Scally
@ 2020-12-01 15:06     ` Andy Shevchenko
  2020-12-15 10:28     ` Daniel Scally
  2 siblings, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-01 15:06 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Mon, Nov 30, 2020 at 10:35:51PM +0200, Sakari Ailus wrote:
> On Mon, Nov 30, 2020 at 01:31:24PM +0000, Daniel Scally wrote:

...

> > +/*
> > + * Extend this array with ACPI Hardware ID's of devices known to be working.
> > + * Do not add a HID for a sensor that is not actually supported.
> > + */
> > +static const char * const cio2_supported_devices[] = {
> > +	"INT33BE",
> > +	"OVTI2680",
> 
> I guess we don't have the known-good frequencies for the CSI-2 bus in
> firmware?
> 
> One option would be to put there what the drivers currently use. This
> assumes the support for these devices is, well, somewhat opportunistic but
> I guess there's no way around that right now at least.
> 
> As the systems are laptops, they're likely somewhat less prone to EMI
> issues to begin with than mobile phones anyway.

ACPI has only XTAL clock frequency (dunno if it's the same as CSI-2 bus clock).
Currently it may be one out of 19.2 MHz, 24 MHz (with a remark that all sensors
must use same value as PMIC can't produce several clocks).

> > +};

...

> > +	strcpy(sensor->prop_names.clock_frequency, "clock-frequency");
> > +	strcpy(sensor->prop_names.rotation, "rotation");
> > +	strcpy(sensor->prop_names.bus_type, "bus-type");
> > +	strcpy(sensor->prop_names.data_lanes, "data-lanes");
> > +	strcpy(sensor->prop_names.remote_endpoint, "remote-endpoint");
> 
> Please use the actual field size instead with strncpy / strscpy.

Perhaps Laurent's proposal is better?

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 14/18] acpi: utils: Add function to fetch dependent acpi_devices
  2020-11-30 23:54     ` Dan Scally
@ 2020-12-01 15:10       ` Andy Shevchenko
  2020-12-01 15:23         ` Dan Scally
  0 siblings, 1 reply; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-01 15:10 UTC (permalink / raw)
  To: Dan Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

On Mon, Nov 30, 2020 at 11:54:44PM +0000, Dan Scally wrote:
> Hi Andy
> 
> On 30/11/2020 18:23, Andy Shevchenko wrote:
> > On Mon, Nov 30, 2020 at 01:31:25PM +0000, Daniel Scally wrote:
> >> ACPI devices declare themselves dependent on other devices via the _DEP
> >> buffer. Fetching the dependee from dependent is a matter of parsing
> >> _DEP, but currently there's no method to fetch dependent from dependee.
> >> Add one, so we can parse sensors dependent on a PMIC from the PMIC's
> >> acpi_driver.
> > Do I understand correctly that it's an existing table provided by firmware that
> > (ab)uses _DEP in such way? Note, the specification doesn't tell we may use it
> > in this way, OTOH I don't remember if it strictly forbids such use.
> >
> > So, please elaborate in the commit message why you need this and pint out to
> > the 6.5.8 "_DEP (Operation Region Dependencies)" which clearly says about
> > OpRegions and that part already supported by ACPI in the Linux, if I'm not
> > mistaken, need to refresh my memory.
> 
> 
> Laurent's reply is good explanation, but for example see my Lenovo Miix
> 510's DSDT:
> 
> 
> https://gist.githubusercontent.com/djrscally/e64d112180517352fa3392878b0f4a7d/raw/88b90b3ea4204fd7845257b6666fdade47cc2981/dsdt.dsl
> 
> 
> Search OVTI2680 and OVTI5648 for the cameras. Both are dependent on
> IN3472 devices (PMI0 and PMI1) which are the discrete type that we're
> attempting to handle here.

Yes, it seems since PMIC is kinda "power resource" (don't mix with real power
resource as by ACPI specifications) and that's why they decided to include it
into _DEP.  So, it seems a de facto common practice. Thus, it would be nice to
have the above in the commit message in some form. Can you do it?

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 14/18] acpi: utils: Add function to fetch dependent acpi_devices
  2020-12-01 15:10       ` Andy Shevchenko
@ 2020-12-01 15:23         ` Dan Scally
  0 siblings, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-01 15:23 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus


On 01/12/2020 15:10, Andy Shevchenko wrote:
> On Mon, Nov 30, 2020 at 11:54:44PM +0000, Dan Scally wrote:
>> Hi Andy
>>
>> On 30/11/2020 18:23, Andy Shevchenko wrote:
>>> On Mon, Nov 30, 2020 at 01:31:25PM +0000, Daniel Scally wrote:
>>>> ACPI devices declare themselves dependent on other devices via the _DEP
>>>> buffer. Fetching the dependee from dependent is a matter of parsing
>>>> _DEP, but currently there's no method to fetch dependent from dependee.
>>>> Add one, so we can parse sensors dependent on a PMIC from the PMIC's
>>>> acpi_driver.
>>> Do I understand correctly that it's an existing table provided by firmware that
>>> (ab)uses _DEP in such way? Note, the specification doesn't tell we may use it
>>> in this way, OTOH I don't remember if it strictly forbids such use.
>>>
>>> So, please elaborate in the commit message why you need this and pint out to
>>> the 6.5.8 "_DEP (Operation Region Dependencies)" which clearly says about
>>> OpRegions and that part already supported by ACPI in the Linux, if I'm not
>>> mistaken, need to refresh my memory.
>>
>> Laurent's reply is good explanation, but for example see my Lenovo Miix
>> 510's DSDT:
>>
>>
>> https://gist.githubusercontent.com/djrscally/e64d112180517352fa3392878b0f4a7d/raw/88b90b3ea4204fd7845257b6666fdade47cc2981/dsdt.dsl
>>
>>
>> Search OVTI2680 and OVTI5648 for the cameras. Both are dependent on
>> IN3472 devices (PMI0 and PMI1) which are the discrete type that we're
>> attempting to handle here.
> Yes, it seems since PMIC is kinda "power resource" (don't mix with real power
> resource as by ACPI specifications) and that's why they decided to include it
> into _DEP.  So, it seems a de facto common practice. Thus, it would be nice to
> have the above in the commit message in some form. Can you do it?
>
Sure, no problem. I'll include that in the next version

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 23:32     ` Laurent Pinchart
@ 2020-12-01 15:55       ` Sakari Ailus
  2020-12-01 18:37         ` Laurent Pinchart
  2020-12-01 18:49       ` Andy Shevchenko
  1 sibling, 1 reply; 144+ messages in thread
From: Sakari Ailus @ 2020-12-01 15:55 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Andy Shevchenko, Daniel Scally, linux-kernel, linux-acpi,
	linux-gpio, linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Laurent,

On Tue, Dec 01, 2020 at 01:32:32AM +0200, Laurent Pinchart wrote:
> Hi Andy,
> 
> On Mon, Nov 30, 2020 at 10:07:19PM +0200, Andy Shevchenko wrote:
> > On Mon, Nov 30, 2020 at 01:31:29PM +0000, Daniel Scally wrote:
> > > On platforms where ACPI is designed for use with Windows, resources
> > > that are intended to be consumed by sensor devices are sometimes in
> > > the _CRS of a dummy INT3472 device upon which the sensor depends. This
> > > driver binds to the dummy acpi device (which does not represent a
> > 
> > acpi device -> acpi_device
> > 
> > > physical PMIC) and maps them into GPIO lines and regulators for use by
> > > the sensor device instead.
> > 
> > ...
> > 
> > > This patch contains the bits of this process that we're least sure about.
> > > The sensors in scope for this work are called out as dependent (in their
> > > DSDT entry's _DEP) on a device with _HID INT3472. These come in at least
> > > 2 kinds; those with an I2cSerialBusV2 entry (which we presume therefore
> > > are legitimate tps68470 PMICs that need handling by those drivers - work
> > > on that in the future). And those without an I2C device. For those without
> > > an I2C device they instead have an array of GPIO pins defined in _CRS. So
> > > for example, my Lenovo Miix 510's OVTI2680 sensor is dependent on one of
> > > the _latter_ kind of INT3472 devices, with this _CRS:
> > > 
> > > Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
> > > {
> > >     Name (SBUF, ResourceTemplate ()
> > >     {
> > >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > > 	    0x00, ResourceConsumer, ,
> > >             )
> > >             {   // Pin list
> > >                 0x0079
> > >             }
> > >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > > 	    0x00, ResourceConsumer, ,
> > >             )
> > >             {   // Pin list
> > >                 0x007A
> > >             }
> > >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > > 	    0x00, ResourceConsumer, ,
> > >             )
> > >             {   // Pin list
> > >                 0x008F
> > >             }
> > >     })
> > >     Return (SBUF) /* \_SB_.PCI0.PMI1._CRS.SBUF */
> > > }
> > > 
> > > and the same device has a _DSM Method, which returns 32-bit ints where
> > > the second lowest byte we noticed to match the pin numbers of the GPIO
> > > lines:
> > > 
> > > Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
> > > {
> > >     If ((Arg0 == ToUUID ("79234640-9e10-4fea-a5c1-b5aa8b19756f")))
> > >     {
> > >         If ((Arg2 == One))
> > >         {
> > >             Return (0x03)
> > >         }
> > > 
> > >         If ((Arg2 == 0x02))
> > >         {
> > >             Return (0x01007900)
> > >         }
> > > 
> > >         If ((Arg2 == 0x03))
> > >         {
> > >             Return (0x01007A0C)
> > >         }
> > > 
> > >         If ((Arg2 == 0x04))
> > >         {
> > >             Return (0x01008F01)
> > >         }
> > >     }
> > > 
> > >     Return (Zero)
> > > }
> > > 
> > > We know that at least some of those pins have to be toggled active for the
> > > sensor devices to be available in i2c, so the conclusion we came to was
> > > that those GPIO entries assigned to the INT3472 device actually represent
> > > GPIOs and regulators to be consumed by the sensors themselves. Tsuchiya
> > > noticed that the lowest byte in the return values of the _DSM method
> > > seemed to represent the type or function of the GPIO line, and we
> > > confirmed that by testing on each surface device that GPIO lines where the
> > > low byte in the _DSM entry for that pin was 0x0d controlled the privacy
> > > LED of the cameras.
> > > 
> > > We're guessing as to the exact meaning of the function byte, but I
> > > conclude they're something like this:
> > > 
> > > 0x00 - probably a reset GPIO
> > > 0x01 - regulator for the sensor
> > > 0x0c - regulator for the sensor
> > > 0x0b - regulator again, but for a VCM or EEPROM
> > > 0x0d - privacy led (only one we're totally confident of since we can see
> > >        it happen!)
> > 
> > It's solely Windows driver design...
> > Luckily I found some information and can clarify above table:
> > 
> > 0x00 Reset
> > 0x01 Power down
> > 0x0b Power enable
> > 0x0c Clock enable
> > 0x0d LED (active high)
> 
> That's very useful information ! Thank you.
> 
> > The above text perhaps should go somewhere under Documentation.
> 
> Or in the driver source code, but definitely somewhere else than in the
> commit message.
> 
> > > After much internal debate I decided to write this as a standalone
> > > acpi_driver. Alternative options we considered:
> > > 
> > > 1. Squash all this into the cio2-bridge code, which I did originally write
> > > but decided I didn't like.
> > > 2. Extend the existing tps68470 mfd driver...they share an ACPI ID so this
> > > kinda makes sense, but ultimately given there is no actual physical
> > > tps68470 in the scenario this patch handles I decided I didn't like this
> > > either.
> > 
> > Looking to this I think the best is to create a module that can be consumed by tps68470 and separately.
> > So, something near to it rather than under ipu3 hood.
> > 
> > You may use same ID's in both drivers (in PMIC less case it can be simple
> > platform and thus they won't conflict), but both of them should provide GPIO
> > resources for consumption.
> > 
> > So, something like
> > 
> >  tps68470.h with API to consume
> >  split tps68470 to -core, -i2c parts
> >  add int3472, which will serve for above and be standalone platform driver
> >  update cio2-bridge accordingly
> > 
> > Would it be feasible?
> 
> Given that INT3472 means Intel camera power management device (that's
> more or less the wording in Windows, I can double-check), would the
> following make sense ?
> 
> A top-level module named intel-camera-pmic (or int3472, or ...) would
> register two drivers, a platform driver and an I2C driver, to
> accommodate for both cases ("discrete PMIC" that doesn't have an
> I2cSerialBusV2, and TPS64870 or uP6641Q that are I2C devices). The probe
> function would perform the following:
> 
> - If there's no CLDB, then the device uses the Chrome OS "ACPI
>   bindings", and refers to a TPS64870. The code that exists in the
>   kernel today (registering GPIOs, and registering an OpRegion to
>   communicate with the power management code in the DSDT) would be
>   activated.
> 
> - If there's a CLDB, then the device type would be retrieved from it:
> 
>   - If the device is a "discrete PMIC", the driver would register clocks
>     and regulators controlled by GPIOs, and create clock, regulator and
>     GPIO lookup entries for the sensor device that references the PMIC.
> 
>   - If the device is a TPS64870, the code that exists in the kernel
>     today to register GPIOs would be activated, and new code would need
>     to be written to register regulators and clocks.
> 
>   - If the device is a uP6641Q, a new driver will need to be written (I
>     don't know on which devices this PMIC is used, so this can probably
>     be deferred).
> 
> We can split this in multiple files and/or modules.

That's what I thought of, too, as one option, but with some more detail.
This would be indeed the cleanest option.

I think it'd be nice if the CLDB stuff (apart from checking whether it's
there) would be in a different module to avoid cluttering up the real
tps68470 driver.

-- 
Regards,

Sakari Ailus

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

* Re: [PATCH 06/18] software_node: amend software_node_unregister_node_group() to perform unregistration of array in reverse order to be consistent with software_node_unregister_nodes()
  2020-11-30 13:31 ` [PATCH 06/18] software_node: amend software_node_unregister_node_group() to perform unregistration of array in reverse order to be consistent with software_node_unregister_nodes() Daniel Scally
  2020-11-30 16:17   ` Laurent Pinchart
  2020-11-30 17:19   ` kernel test robot
@ 2020-12-01 18:18   ` Dan Carpenter
  2 siblings, 0 replies; 144+ messages in thread
From: Dan Carpenter @ 2020-12-01 18:18 UTC (permalink / raw)
  To: kbuild, Daniel Scally, linux-kernel, linux-acpi, linux-gpio,
	linux-i2c, linux-media, devel
  Cc: lkp, kbuild-all, rjw, lenb, gregkh, mika.westerberg

[-- Attachment #1: Type: text/plain, Size: 1937 bytes --]

Hi Daniel,

url:    https://github.com/0day-ci/linux/commits/Daniel-Scally/Add-functionality-to-ipu3-cio2-driver-allowing-software_node-connections-to-sensors-on-platforms-designed-for-Windows/20201130-214014
base:   git://linuxtv.org/media_tree.git master
config: i386-randconfig-m021-20201130 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>

smatch warnings:
drivers/base/swnode.c:785 software_node_unregister_node_group() error: uninitialized symbol 'i'.

vim +/i +785 drivers/base/swnode.c

02094d54870590a Andy Shevchenko 2020-04-08  778  void software_node_unregister_node_group(const struct software_node **node_group)
02094d54870590a Andy Shevchenko 2020-04-08  779  {
02094d54870590a Andy Shevchenko 2020-04-08  780  	unsigned int i;
02094d54870590a Andy Shevchenko 2020-04-08  781  
02094d54870590a Andy Shevchenko 2020-04-08  782  	if (!node_group)
02094d54870590a Andy Shevchenko 2020-04-08  783  		return;
02094d54870590a Andy Shevchenko 2020-04-08  784  
7c7577c82672f0a Daniel Scally   2020-11-30 @785  	while (node_group[i]->name)
                                                                          ^
The "i" is never initialized.

7c7577c82672f0a Daniel Scally   2020-11-30  786  		i++;
7c7577c82672f0a Daniel Scally   2020-11-30  787  
7c7577c82672f0a Daniel Scally   2020-11-30  788  	while (i--)
9dcbac84244f32e Andy Shevchenko 2020-06-22  789  		software_node_unregister(node_group[i]);

It's a strange thing that they can only be unregistered in reverse
order...  Walter Harms is right when he points out that programmers are
notoriously bad at counting backwards.

02094d54870590a Andy Shevchenko 2020-04-08  790  }

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 32286 bytes --]

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 23:20     ` Dan Scally
@ 2020-12-01 18:31       ` Andy Shevchenko
  2020-12-01 18:36         ` Laurent Pinchart
  0 siblings, 1 reply; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-01 18:31 UTC (permalink / raw)
  To: Dan Scally
  Cc: Jean-Michel Hautbois, linux-kernel, linux-acpi, linux-gpio,
	linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	sakari.ailus, bingbu.cao, tian.shu.qiu, mchehab, robert.moore,
	erik.kaneda, pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

On Mon, Nov 30, 2020 at 11:20:55PM +0000, Dan Scally wrote:
> On 30/11/2020 16:17, Jean-Michel Hautbois wrote:

...

> but the ACPI table doesn't define an I2CSerialBusV2 for it. Instead it's
> rolled under the sensor's entry, there's a second entry in _CRS for the
> sensor that matches the address of the new device:
> 
> 
>             Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
>             {
>                 Name (SBUF, ResourceTemplate ()
>                 {
>                     I2cSerialBusV2 (0x0036, ControllerInitiated, 0x00061A80,
>                         AddressingMode7Bit, "\\_SB.PCI0.I2C2",
>                         0x00, ResourceConsumer, , Exclusive,
>                         )
>                     I2cSerialBusV2 (0x000C, ControllerInitiated, 0x00061A80,
>                         AddressingMode7Bit, "\\_SB.PCI0.I2C2",
>                         0x00, ResourceConsumer, , Exclusive,
>                         )
>                 })
>                 Return (SBUF) /* \_SB_.PCI0.CAM0._CRS.SBUF */
>             }
> 
> So that's another thing we need to work on. At the moment it doesn't
> exist as far as the kernel is concerned.

Maybe something along i2c-multi-instantiate can help here (maybe not).

P.S. Dan, can you drop unrelated text when replying?

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 18:31       ` Andy Shevchenko
@ 2020-12-01 18:36         ` Laurent Pinchart
  2020-12-01 18:51           ` Andy Shevchenko
  0 siblings, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-12-01 18:36 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Dan Scally, Jean-Michel Hautbois, linux-kernel, linux-acpi,
	linux-gpio, linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	sakari.ailus, bingbu.cao, tian.shu.qiu, mchehab, robert.moore,
	erik.kaneda, pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Andy,

On Tue, Dec 01, 2020 at 08:31:39PM +0200, Andy Shevchenko wrote:
> On Mon, Nov 30, 2020 at 11:20:55PM +0000, Dan Scally wrote:
> > On 30/11/2020 16:17, Jean-Michel Hautbois wrote:
> 
> ...
> 
> > but the ACPI table doesn't define an I2CSerialBusV2 for it. Instead it's
> > rolled under the sensor's entry, there's a second entry in _CRS for the
> > sensor that matches the address of the new device:
> > 
> > 
> >             Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
> >             {
> >                 Name (SBUF, ResourceTemplate ()
> >                 {
> >                     I2cSerialBusV2 (0x0036, ControllerInitiated, 0x00061A80,
> >                         AddressingMode7Bit, "\\_SB.PCI0.I2C2",
> >                         0x00, ResourceConsumer, , Exclusive,
> >                         )
> >                     I2cSerialBusV2 (0x000C, ControllerInitiated, 0x00061A80,
> >                         AddressingMode7Bit, "\\_SB.PCI0.I2C2",
> >                         0x00, ResourceConsumer, , Exclusive,
> >                         )
> >                 })
> >                 Return (SBUF) /* \_SB_.PCI0.CAM0._CRS.SBUF */
> >             }
> > 
> > So that's another thing we need to work on. At the moment it doesn't
> > exist as far as the kernel is concerned.
> 
> Maybe something along i2c-multi-instantiate can help here (maybe not).

It's two different devices really. That's also one of the "annoyances"
related to this platform. The INT* HID for the camera sensor actually
refers to a camera module, with VCM, EEPROM, ... On Chrome OS devices,
the same HID refers to the camera sensor only. *sigh* :-(

> P.S. Dan, can you drop unrelated text when replying?

I find a full quote actually useful, as it saves me from having to dig
up original e-mails to read missing parts :-) It's a matter of
preference I suppose.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 15:55       ` Sakari Ailus
@ 2020-12-01 18:37         ` Laurent Pinchart
  2020-12-02 11:09           ` Sakari Ailus
  0 siblings, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-12-01 18:37 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Andy Shevchenko, Daniel Scally, linux-kernel, linux-acpi,
	linux-gpio, linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Sakari,

On Tue, Dec 01, 2020 at 05:55:13PM +0200, Sakari Ailus wrote:
> On Tue, Dec 01, 2020 at 01:32:32AM +0200, Laurent Pinchart wrote:
> > On Mon, Nov 30, 2020 at 10:07:19PM +0200, Andy Shevchenko wrote:
> > > On Mon, Nov 30, 2020 at 01:31:29PM +0000, Daniel Scally wrote:
> > > > On platforms where ACPI is designed for use with Windows, resources
> > > > that are intended to be consumed by sensor devices are sometimes in
> > > > the _CRS of a dummy INT3472 device upon which the sensor depends. This
> > > > driver binds to the dummy acpi device (which does not represent a
> > > 
> > > acpi device -> acpi_device
> > > 
> > > > physical PMIC) and maps them into GPIO lines and regulators for use by
> > > > the sensor device instead.
> > > 
> > > ...
> > > 
> > > > This patch contains the bits of this process that we're least sure about.
> > > > The sensors in scope for this work are called out as dependent (in their
> > > > DSDT entry's _DEP) on a device with _HID INT3472. These come in at least
> > > > 2 kinds; those with an I2cSerialBusV2 entry (which we presume therefore
> > > > are legitimate tps68470 PMICs that need handling by those drivers - work
> > > > on that in the future). And those without an I2C device. For those without
> > > > an I2C device they instead have an array of GPIO pins defined in _CRS. So
> > > > for example, my Lenovo Miix 510's OVTI2680 sensor is dependent on one of
> > > > the _latter_ kind of INT3472 devices, with this _CRS:
> > > > 
> > > > Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
> > > > {
> > > >     Name (SBUF, ResourceTemplate ()
> > > >     {
> > > >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > > > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > > > 	    0x00, ResourceConsumer, ,
> > > >             )
> > > >             {   // Pin list
> > > >                 0x0079
> > > >             }
> > > >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > > > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > > > 	    0x00, ResourceConsumer, ,
> > > >             )
> > > >             {   // Pin list
> > > >                 0x007A
> > > >             }
> > > >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > > > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > > > 	    0x00, ResourceConsumer, ,
> > > >             )
> > > >             {   // Pin list
> > > >                 0x008F
> > > >             }
> > > >     })
> > > >     Return (SBUF) /* \_SB_.PCI0.PMI1._CRS.SBUF */
> > > > }
> > > > 
> > > > and the same device has a _DSM Method, which returns 32-bit ints where
> > > > the second lowest byte we noticed to match the pin numbers of the GPIO
> > > > lines:
> > > > 
> > > > Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
> > > > {
> > > >     If ((Arg0 == ToUUID ("79234640-9e10-4fea-a5c1-b5aa8b19756f")))
> > > >     {
> > > >         If ((Arg2 == One))
> > > >         {
> > > >             Return (0x03)
> > > >         }
> > > > 
> > > >         If ((Arg2 == 0x02))
> > > >         {
> > > >             Return (0x01007900)
> > > >         }
> > > > 
> > > >         If ((Arg2 == 0x03))
> > > >         {
> > > >             Return (0x01007A0C)
> > > >         }
> > > > 
> > > >         If ((Arg2 == 0x04))
> > > >         {
> > > >             Return (0x01008F01)
> > > >         }
> > > >     }
> > > > 
> > > >     Return (Zero)
> > > > }
> > > > 
> > > > We know that at least some of those pins have to be toggled active for the
> > > > sensor devices to be available in i2c, so the conclusion we came to was
> > > > that those GPIO entries assigned to the INT3472 device actually represent
> > > > GPIOs and regulators to be consumed by the sensors themselves. Tsuchiya
> > > > noticed that the lowest byte in the return values of the _DSM method
> > > > seemed to represent the type or function of the GPIO line, and we
> > > > confirmed that by testing on each surface device that GPIO lines where the
> > > > low byte in the _DSM entry for that pin was 0x0d controlled the privacy
> > > > LED of the cameras.
> > > > 
> > > > We're guessing as to the exact meaning of the function byte, but I
> > > > conclude they're something like this:
> > > > 
> > > > 0x00 - probably a reset GPIO
> > > > 0x01 - regulator for the sensor
> > > > 0x0c - regulator for the sensor
> > > > 0x0b - regulator again, but for a VCM or EEPROM
> > > > 0x0d - privacy led (only one we're totally confident of since we can see
> > > >        it happen!)
> > > 
> > > It's solely Windows driver design...
> > > Luckily I found some information and can clarify above table:
> > > 
> > > 0x00 Reset
> > > 0x01 Power down
> > > 0x0b Power enable
> > > 0x0c Clock enable
> > > 0x0d LED (active high)
> > 
> > That's very useful information ! Thank you.
> > 
> > > The above text perhaps should go somewhere under Documentation.
> > 
> > Or in the driver source code, but definitely somewhere else than in the
> > commit message.
> > 
> > > > After much internal debate I decided to write this as a standalone
> > > > acpi_driver. Alternative options we considered:
> > > > 
> > > > 1. Squash all this into the cio2-bridge code, which I did originally write
> > > > but decided I didn't like.
> > > > 2. Extend the existing tps68470 mfd driver...they share an ACPI ID so this
> > > > kinda makes sense, but ultimately given there is no actual physical
> > > > tps68470 in the scenario this patch handles I decided I didn't like this
> > > > either.
> > > 
> > > Looking to this I think the best is to create a module that can be consumed by tps68470 and separately.
> > > So, something near to it rather than under ipu3 hood.
> > > 
> > > You may use same ID's in both drivers (in PMIC less case it can be simple
> > > platform and thus they won't conflict), but both of them should provide GPIO
> > > resources for consumption.
> > > 
> > > So, something like
> > > 
> > >  tps68470.h with API to consume
> > >  split tps68470 to -core, -i2c parts
> > >  add int3472, which will serve for above and be standalone platform driver
> > >  update cio2-bridge accordingly
> > > 
> > > Would it be feasible?
> > 
> > Given that INT3472 means Intel camera power management device (that's
> > more or less the wording in Windows, I can double-check), would the
> > following make sense ?
> > 
> > A top-level module named intel-camera-pmic (or int3472, or ...) would
> > register two drivers, a platform driver and an I2C driver, to
> > accommodate for both cases ("discrete PMIC" that doesn't have an
> > I2cSerialBusV2, and TPS64870 or uP6641Q that are I2C devices). The probe
> > function would perform the following:
> > 
> > - If there's no CLDB, then the device uses the Chrome OS "ACPI
> >   bindings", and refers to a TPS64870. The code that exists in the
> >   kernel today (registering GPIOs, and registering an OpRegion to
> >   communicate with the power management code in the DSDT) would be
> >   activated.
> > 
> > - If there's a CLDB, then the device type would be retrieved from it:
> > 
> >   - If the device is a "discrete PMIC", the driver would register clocks
> >     and regulators controlled by GPIOs, and create clock, regulator and
> >     GPIO lookup entries for the sensor device that references the PMIC.
> > 
> >   - If the device is a TPS64870, the code that exists in the kernel
> >     today to register GPIOs would be activated, and new code would need
> >     to be written to register regulators and clocks.
> > 
> >   - If the device is a uP6641Q, a new driver will need to be written (I
> >     don't know on which devices this PMIC is used, so this can probably
> >     be deferred).
> > 
> > We can split this in multiple files and/or modules.
> 
> That's what I thought of, too, as one option, but with some more detail.
> This would be indeed the cleanest option.
> 
> I think it'd be nice if the CLDB stuff (apart from checking whether it's
> there) would be in a different module to avoid cluttering up the real
> tps68470 driver.

Given the amount of code, and the fact that the driver should be
compiled as a module, I don't think it will make a huge difference in
the memory footprint.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 23:32     ` Laurent Pinchart
  2020-12-01 15:55       ` Sakari Ailus
@ 2020-12-01 18:49       ` Andy Shevchenko
  2020-12-01 20:59         ` Dan Scally
  2020-12-13 22:48         ` Daniel Scally
  1 sibling, 2 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-01 18:49 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Tue, Dec 01, 2020 at 01:32:32AM +0200, Laurent Pinchart wrote:
> On Mon, Nov 30, 2020 at 10:07:19PM +0200, Andy Shevchenko wrote:
> > On Mon, Nov 30, 2020 at 01:31:29PM +0000, Daniel Scally wrote:

...

> > So, something like
> > 
> >  tps68470.h with API to consume
> >  split tps68470 to -core, -i2c parts
> >  add int3472, which will serve for above and be standalone platform driver
> >  update cio2-bridge accordingly
> > 
> > Would it be feasible?
> 
> Given that INT3472 means Intel camera power management device (that's
> more or less the wording in Windows, I can double-check), would the
> following make sense ?
> 
> A top-level module named intel-camera-pmic (or int3472, or ...) would
> register two drivers, a platform driver and an I2C driver, to
> accommodate for both cases ("discrete PMIC" that doesn't have an
> I2cSerialBusV2, and TPS64870 or uP6641Q that are I2C devices). The probe
> function would perform the following:
> 
> - If there's no CLDB, then the device uses the Chrome OS "ACPI
>   bindings", and refers to a TPS64870. The code that exists in the
>   kernel today (registering GPIOs, and registering an OpRegion to
>   communicate with the power management code in the DSDT) would be
>   activated.
> 
> - If there's a CLDB, then the device type would be retrieved from it:
> 
>   - If the device is a "discrete PMIC", the driver would register clocks
>     and regulators controlled by GPIOs, and create clock, regulator and
>     GPIO lookup entries for the sensor device that references the PMIC.
> 
>   - If the device is a TPS64870, the code that exists in the kernel
>     today to register GPIOs would be activated, and new code would need
>     to be written to register regulators and clocks.
> 
>   - If the device is a uP6641Q, a new driver will need to be written (I
>     don't know on which devices this PMIC is used, so this can probably
>     be deferred).
> 
> We can split this in multiple files and/or modules.

Seems we can do this, by locating intel_int3472.c under PDx86 hood and dropping
ACPI ID table from TPS68470 MFD driver. The PMIC can be instantiated via
i2c_acpi_new_device() (IIRC the API name).

And actually it makes more sense since it's not and MFD and should not be there.

(Dan, patch wise the one creates intel_int3472.c followed by another one that
 moves ACPI ID from PMIC and introduces its instantiation via I²C board info
 structure)

...

> > > +	table_entry = (struct gpiod_lookup)GPIO_LOOKUP_IDX(acpi_dev_name(adev),
> > > +							   ares->data.gpio.pin_table[0],
> > > +							   func, 0, GPIO_ACTIVE_HIGH);
> > 
> > You won't need this if you have regular INT3472 platform driver.
> > Simple call there _DSM to map resources to the type and use devm_gpiod_get on
> > consumer behalf. Thus, previous patch is not needed.
> 
> How does the consumer (the camera sensor) retrieve the GPIO though ? The
> _DSM is in the PMIC device object, while the real consumer is the camera
> sensor.

1. A GPIO proxy
2. A custom GPIO lookup tables
3. An fwnode passing to the sensor (via swnodes graph)

First may issue deferred probe, while second needs some ordering tricks I guess.
Third one should also provide an ACPI GPIO mapping table or so to make the
consumer rely on names rather than custom numbers.

Perhaps someone may propose other solutions.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 18:36         ` Laurent Pinchart
@ 2020-12-01 18:51           ` Andy Shevchenko
  0 siblings, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-01 18:51 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Dan Scally, Jean-Michel Hautbois, linux-kernel, linux-acpi,
	linux-gpio, linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	sakari.ailus, bingbu.cao, tian.shu.qiu, mchehab, robert.moore,
	erik.kaneda, pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Tue, Dec 01, 2020 at 08:36:16PM +0200, Laurent Pinchart wrote:
> On Tue, Dec 01, 2020 at 08:31:39PM +0200, Andy Shevchenko wrote:
> > On Mon, Nov 30, 2020 at 11:20:55PM +0000, Dan Scally wrote:
> > > On 30/11/2020 16:17, Jean-Michel Hautbois wrote:

...

> > > but the ACPI table doesn't define an I2CSerialBusV2 for it. Instead it's
> > > rolled under the sensor's entry, there's a second entry in _CRS for the
> > > sensor that matches the address of the new device:
> > > 
> > > 
> > >             Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
> > >             {
> > >                 Name (SBUF, ResourceTemplate ()
> > >                 {
> > >                     I2cSerialBusV2 (0x0036, ControllerInitiated, 0x00061A80,
> > >                         AddressingMode7Bit, "\\_SB.PCI0.I2C2",
> > >                         0x00, ResourceConsumer, , Exclusive,
> > >                         )
> > >                     I2cSerialBusV2 (0x000C, ControllerInitiated, 0x00061A80,
> > >                         AddressingMode7Bit, "\\_SB.PCI0.I2C2",
> > >                         0x00, ResourceConsumer, , Exclusive,
> > >                         )
> > >                 })
> > >                 Return (SBUF) /* \_SB_.PCI0.CAM0._CRS.SBUF */
> > >             }
> > > 
> > > So that's another thing we need to work on. At the moment it doesn't
> > > exist as far as the kernel is concerned.
> > 
> > Maybe something along i2c-multi-instantiate can help here (maybe not).
> 
> It's two different devices really. That's also one of the "annoyances"
> related to this platform. The INT* HID for the camera sensor actually
> refers to a camera module, with VCM, EEPROM, ... On Chrome OS devices,
> the same HID refers to the camera sensor only. *sigh* :-(

But it's not a problem for i2c-multi-instantiate. It's kinda MFD approach for
I²C peripheral devices.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01  8:30     ` Dan Scally
@ 2020-12-01 18:54       ` Andy Shevchenko
  2020-12-01 18:55         ` Laurent Pinchart
  0 siblings, 1 reply; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-01 18:54 UTC (permalink / raw)
  To: Dan Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus, Laurent Pinchart

On Tue, Dec 01, 2020 at 08:30:03AM +0000, Dan Scally wrote:
> On 30/11/2020 20:07, Andy Shevchenko wrote:

...

> >> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
> >> +	{ "GNDF140809R", 2, miix_510_ov2680 },
> >> +	{ "YHCU", 2, surface_go2_ov5693 },
> >> +	{ "MSHW0070", 2, surface_book_ov5693 },
> >> +};
> > Hmm... Usual way is to use DMI for that. I'm not sure above will not give us
> > false positive matches.
> I considered DMI too, no problem to switch to that if it's a better choice.

I prefer DMI as it's a standard way to describe platform quirks in x86 world.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 18:54       ` Andy Shevchenko
@ 2020-12-01 18:55         ` Laurent Pinchart
  2020-12-01 19:05           ` Andy Shevchenko
  0 siblings, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-12-01 18:55 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Dan Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Andy,

On Tue, Dec 01, 2020 at 08:54:17PM +0200, Andy Shevchenko wrote:
> On Tue, Dec 01, 2020 at 08:30:03AM +0000, Dan Scally wrote:
> > On 30/11/2020 20:07, Andy Shevchenko wrote:
> 
> ...
> 
> > >> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
> > >> +	{ "GNDF140809R", 2, miix_510_ov2680 },
> > >> +	{ "YHCU", 2, surface_go2_ov5693 },
> > >> +	{ "MSHW0070", 2, surface_book_ov5693 },
> > >> +};
> > >
> > > Hmm... Usual way is to use DMI for that. I'm not sure above will not give us
> > > false positive matches.
> >
> > I considered DMI too, no problem to switch to that if it's a better choice.
> 
> I prefer DMI as it's a standard way to describe platform quirks in x86 world.

Do you think the Windows driver would use DMI ? That seems quite
unlikely to me, given how they would have to release a new driver binary
for every machine. I'm pretty sure that a different mechanism is used to
identify camera integration, and I think it would make sense to follow
the same approach. That would allow us to avoid large tables of DMI
identifiers that would need to be constently updated, potentially making
user experience better.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 23:06     ` Dan Scally
  2020-11-30 23:21       ` Laurent Pinchart
  2020-12-01  6:44       ` Sakari Ailus
@ 2020-12-01 18:55       ` Andy Shevchenko
  2 siblings, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-01 18:55 UTC (permalink / raw)
  To: Dan Scally
  Cc: Sakari Ailus, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

On Mon, Nov 30, 2020 at 11:06:03PM +0000, Dan Scally wrote:
> On 30/11/2020 20:52, Sakari Ailus wrote:
> >> +static const struct acpi_device_id int3472_device_id[] = {
> >> +	{ "INT3472", 0 },
> > The INT3472 _HID is really allocated for the tps68470 PMIC chip. It may not
> > be used by other drivers; people will want to build kernels where both of
> > these ACPI table layouts are functional.
> >
> > Instead, I propose, that you add this as an option to the tps68470 driver
> > that figures out whether the ACPI device for the tps68470 device actually
> > describes something else, in a similar fashion you do with the cio2-bridge
> > driver. I think it may need a separate Kconfig option albeit this and
> > cio2-bridge cannot be used separately.
> 
> It actually occurs to me that that may not work (I know I called that
> out as an option we considered, but that was a while ago actually). The
> reason I wasn't worried about the existing tps68470 driver binding to
> these devices is that it's an i2c driver, and these dummy devices don't
> have an I2cSerialBusV2, so no I2C device is created by them the kernel.
> 
> 
> Won't that mean the tps68470 driver won't ever be probed for these devices?

It won't be probed by kernel as long as it stays pure I²C driver..

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 12:48             ` Dan Scally
@ 2020-12-01 19:01               ` Andy Shevchenko
  0 siblings, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-01 19:01 UTC (permalink / raw)
  To: Dan Scally
  Cc: Sakari Ailus, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Laurent Pinchart

On Tue, Dec 01, 2020 at 12:48:28PM +0000, Dan Scally wrote:
> On 01/12/2020 12:32, Sakari Ailus wrote:

...

> Sorry, clarification here: The INT3472 driver in patch #18 runs probe()
> for the device representing a physical tps68470, but then -EINVAL's. The
> existing tps68470 mfd driver doesn't probe() for the dummy INT3472 device.

As I said in the other subthread, we need to take ACPI ID from MFD and move it
to platform driver. I like the idea what Laurent proposed there.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 18:55         ` Laurent Pinchart
@ 2020-12-01 19:05           ` Andy Shevchenko
  2020-12-01 19:06             ` Laurent Pinchart
  0 siblings, 1 reply; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-01 19:05 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Dan Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Tue, Dec 01, 2020 at 08:55:48PM +0200, Laurent Pinchart wrote:
> On Tue, Dec 01, 2020 at 08:54:17PM +0200, Andy Shevchenko wrote:
> > On Tue, Dec 01, 2020 at 08:30:03AM +0000, Dan Scally wrote:
> > > On 30/11/2020 20:07, Andy Shevchenko wrote:

...

> > > >> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
> > > >> +	{ "GNDF140809R", 2, miix_510_ov2680 },
> > > >> +	{ "YHCU", 2, surface_go2_ov5693 },
> > > >> +	{ "MSHW0070", 2, surface_book_ov5693 },
> > > >> +};
> > > >
> > > > Hmm... Usual way is to use DMI for that. I'm not sure above will not give us
> > > > false positive matches.
> > >
> > > I considered DMI too, no problem to switch to that if it's a better choice.
> > 
> > I prefer DMI as it's a standard way to describe platform quirks in x86 world.
> 
> Do you think the Windows driver would use DMI ?

Linux is using DMI for quirks.

> That seems quite
> unlikely to me, given how they would have to release a new driver binary
> for every machine. I'm pretty sure that a different mechanism is used to
> identify camera integration, and I think it would make sense to follow
> the same approach. That would allow us to avoid large tables of DMI
> identifiers that would need to be constently updated, potentially making
> user experience better.

All Surface family can be matched in a way as Apple machines [1].

[1]: https://lkml.org/lkml/2020/4/15/1198

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 19:05           ` Andy Shevchenko
@ 2020-12-01 19:06             ` Laurent Pinchart
  2020-12-01 19:21               ` Andy Shevchenko
  0 siblings, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-12-01 19:06 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Dan Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Tue, Dec 01, 2020 at 09:05:23PM +0200, Andy Shevchenko wrote:
> On Tue, Dec 01, 2020 at 08:55:48PM +0200, Laurent Pinchart wrote:
> > On Tue, Dec 01, 2020 at 08:54:17PM +0200, Andy Shevchenko wrote:
> > > On Tue, Dec 01, 2020 at 08:30:03AM +0000, Dan Scally wrote:
> > > > On 30/11/2020 20:07, Andy Shevchenko wrote:
> 
> ...
> 
> > > > >> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
> > > > >> +	{ "GNDF140809R", 2, miix_510_ov2680 },
> > > > >> +	{ "YHCU", 2, surface_go2_ov5693 },
> > > > >> +	{ "MSHW0070", 2, surface_book_ov5693 },
> > > > >> +};
> > > > >
> > > > > Hmm... Usual way is to use DMI for that. I'm not sure above will not give us
> > > > > false positive matches.
> > > >
> > > > I considered DMI too, no problem to switch to that if it's a better choice.
> > > 
> > > I prefer DMI as it's a standard way to describe platform quirks in x86 world.
> > 
> > Do you think the Windows driver would use DMI ?
> 
> Linux is using DMI for quirks.
> 
> > That seems quite
> > unlikely to me, given how they would have to release a new driver binary
> > for every machine. I'm pretty sure that a different mechanism is used to
> > identify camera integration, and I think it would make sense to follow
> > the same approach. That would allow us to avoid large tables of DMI
> > identifiers that would need to be constently updated, potentially making
> > user experience better.
> 
> All Surface family can be matched in a way as Apple machines [1].
> 
> [1]: https://lkml.org/lkml/2020/4/15/1198

But not all Surface machines necessarily have the same camera
architecture. My point is that there seems to be identifiers reported in
ACPI for the exact purpose of identifying the camera architecture. If we
used DMI instead, we would have to handle each machine individually.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 19:06             ` Laurent Pinchart
@ 2020-12-01 19:21               ` Andy Shevchenko
  2020-12-01 20:34                 ` Hans de Goede
  2020-12-01 21:05                 ` Dan Scally
  0 siblings, 2 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-01 19:21 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Dan Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Hans de Goede

On Tue, Dec 01, 2020 at 09:06:38PM +0200, Laurent Pinchart wrote:
> On Tue, Dec 01, 2020 at 09:05:23PM +0200, Andy Shevchenko wrote:
> > On Tue, Dec 01, 2020 at 08:55:48PM +0200, Laurent Pinchart wrote:
> > > On Tue, Dec 01, 2020 at 08:54:17PM +0200, Andy Shevchenko wrote:
> > > > On Tue, Dec 01, 2020 at 08:30:03AM +0000, Dan Scally wrote:
> > > > > On 30/11/2020 20:07, Andy Shevchenko wrote:
> > 
> > ...
> > 
> > > > > >> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
> > > > > >> +	{ "GNDF140809R", 2, miix_510_ov2680 },
> > > > > >> +	{ "YHCU", 2, surface_go2_ov5693 },
> > > > > >> +	{ "MSHW0070", 2, surface_book_ov5693 },
> > > > > >> +};
> > > > > >
> > > > > > Hmm... Usual way is to use DMI for that. I'm not sure above will not give us
> > > > > > false positive matches.
> > > > >
> > > > > I considered DMI too, no problem to switch to that if it's a better choice.
> > > > 
> > > > I prefer DMI as it's a standard way to describe platform quirks in x86 world.
> > > 
> > > Do you think the Windows driver would use DMI ?
> > 
> > Linux is using DMI for quirks.
> > 
> > > That seems quite
> > > unlikely to me, given how they would have to release a new driver binary
> > > for every machine. I'm pretty sure that a different mechanism is used to
> > > identify camera integration, and I think it would make sense to follow
> > > the same approach. That would allow us to avoid large tables of DMI
> > > identifiers that would need to be constently updated, potentially making
> > > user experience better.
> > 
> > All Surface family can be matched in a way as Apple machines [1].
> > 
> > [1]: https://lkml.org/lkml/2020/4/15/1198
> 
> But not all Surface machines necessarily have the same camera
> architecture. My point is that there seems to be identifiers reported in
> ACPI for the exact purpose of identifying the camera architecture. If we
> used DMI instead, we would have to handle each machine individually.

With help of DMI we may narrow down the search.

But again, we are talking about uncertainity. It may be your way (a lot of
platforms that have different settings), or mine (only a few with more or less
standard sets of settings).

DMI is simply standard in Linux (people usually easier can grep for quirks for
a specific platform).

I would rather ask Hans' opinion since he has quite an expertise with DMI for
good and bad.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 19:21               ` Andy Shevchenko
@ 2020-12-01 20:34                 ` Hans de Goede
  2020-12-01 20:46                   ` Andy Shevchenko
  2020-12-02 12:48                   ` Laurent Pinchart
  2020-12-01 21:05                 ` Dan Scally
  1 sibling, 2 replies; 144+ messages in thread
From: Hans de Goede @ 2020-12-01 20:34 UTC (permalink / raw)
  To: Andy Shevchenko, Laurent Pinchart
  Cc: Dan Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi,

On 12/1/20 8:21 PM, Andy Shevchenko wrote:
> On Tue, Dec 01, 2020 at 09:06:38PM +0200, Laurent Pinchart wrote:
>> On Tue, Dec 01, 2020 at 09:05:23PM +0200, Andy Shevchenko wrote:
>>> On Tue, Dec 01, 2020 at 08:55:48PM +0200, Laurent Pinchart wrote:
>>>> On Tue, Dec 01, 2020 at 08:54:17PM +0200, Andy Shevchenko wrote:
>>>>> On Tue, Dec 01, 2020 at 08:30:03AM +0000, Dan Scally wrote:
>>>>>> On 30/11/2020 20:07, Andy Shevchenko wrote:
>>>
>>> ...
>>>
>>>>>>>> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
>>>>>>>> +	{ "GNDF140809R", 2, miix_510_ov2680 },
>>>>>>>> +	{ "YHCU", 2, surface_go2_ov5693 },
>>>>>>>> +	{ "MSHW0070", 2, surface_book_ov5693 },
>>>>>>>> +};
>>>>>>>
>>>>>>> Hmm... Usual way is to use DMI for that. I'm not sure above will not give us
>>>>>>> false positive matches.
>>>>>>
>>>>>> I considered DMI too, no problem to switch to that if it's a better choice.
>>>>>
>>>>> I prefer DMI as it's a standard way to describe platform quirks in x86 world.
>>>>
>>>> Do you think the Windows driver would use DMI ?
>>>
>>> Linux is using DMI for quirks.
>>>
>>>> That seems quite
>>>> unlikely to me, given how they would have to release a new driver binary
>>>> for every machine. I'm pretty sure that a different mechanism is used to
>>>> identify camera integration, and I think it would make sense to follow
>>>> the same approach. That would allow us to avoid large tables of DMI
>>>> identifiers that would need to be constently updated, potentially making
>>>> user experience better.
>>>
>>> All Surface family can be matched in a way as Apple machines [1].
>>>
>>> [1]: https://lkml.org/lkml/2020/4/15/1198
>>
>> But not all Surface machines necessarily have the same camera
>> architecture. My point is that there seems to be identifiers reported in
>> ACPI for the exact purpose of identifying the camera architecture. If we
>> used DMI instead, we would have to handle each machine individually.
> 
> With help of DMI we may narrow down the search.
> 
> But again, we are talking about uncertainity. It may be your way (a lot of
> platforms that have different settings), or mine (only a few with more or less
> standard sets of settings).
> 
> DMI is simply standard in Linux (people usually easier can grep for quirks for
> a specific platform).
> 
> I would rather ask Hans' opinion since he has quite an expertise with DMI for
> good and bad.

So generally there are 2 ways how things like this can go:

1) There is sufficient information in the ACPI table and we use data from the
ACPI tables

2) There is unsufficient info in the ACPI tables (or we don't know how to
get / interpret the data) and we use DMI quirks

Although we do often also use a combination, getting what we can from ACPI,
combined with a set of defaults for what we cannot get from ACPI
based on what reference designs use (IOW what most devices seem to have
copy and pasted). Combined with DMI quirks for when the defaults do not
work (which is quite often).

Depending on if "not working because of wrong defaults" has bad side effects,
another option is also to only allow the driver to load on devices which
have the necessary info provided through a DMI match.

I hope this helps.

Regards,

Hans


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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 20:34                 ` Hans de Goede
@ 2020-12-01 20:46                   ` Andy Shevchenko
  2020-12-02 12:48                   ` Laurent Pinchart
  1 sibling, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-01 20:46 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Andy Shevchenko, Laurent Pinchart, Dan Scally,
	Linux Kernel Mailing List, ACPI Devel Maling List,
	open list:GPIO SUBSYSTEM, linux-i2c, Linux Media Mailing List,
	devel, Rafael J. Wysocki, Len Brown, Greg Kroah-Hartman,
	Mika Westerberg, Linus Walleij, Bartosz Golaszewski,
	Wolfram Sang, Yong Zhi, Sakari Ailus, Bingbu Cao, Tian Shu Qiu,
	Mauro Carvalho Chehab, Robert Moore, Erik Kaneda, Petr Mladek,
	Steven Rostedt, Sergey Senozhatsky, Rasmus Villemoes,
	kieran.bingham+renesas, Jacopo Mondi, laurent.pinchart+renesas,
	jorhand, Tsuchiya Yuto, Krogerus, Heikki

On Tue, Dec 1, 2020 at 10:39 PM Hans de Goede <hdegoede@redhat.com> wrote:
> On 12/1/20 8:21 PM, Andy Shevchenko wrote:
> > On Tue, Dec 01, 2020 at 09:06:38PM +0200, Laurent Pinchart wrote:
> >> On Tue, Dec 01, 2020 at 09:05:23PM +0200, Andy Shevchenko wrote:
> >>> On Tue, Dec 01, 2020 at 08:55:48PM +0200, Laurent Pinchart wrote:
> >>>> On Tue, Dec 01, 2020 at 08:54:17PM +0200, Andy Shevchenko wrote:
> >>>>> On Tue, Dec 01, 2020 at 08:30:03AM +0000, Dan Scally wrote:
> >>>>>> On 30/11/2020 20:07, Andy Shevchenko wrote:

...

> >>>>>>>> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
> >>>>>>>> +      { "GNDF140809R", 2, miix_510_ov2680 },
> >>>>>>>> +      { "YHCU", 2, surface_go2_ov5693 },
> >>>>>>>> +      { "MSHW0070", 2, surface_book_ov5693 },
> >>>>>>>> +};
> >>>>>>>
> >>>>>>> Hmm... Usual way is to use DMI for that. I'm not sure above will not give us
> >>>>>>> false positive matches.
> >>>>>>
> >>>>>> I considered DMI too, no problem to switch to that if it's a better choice.
> >>>>>
> >>>>> I prefer DMI as it's a standard way to describe platform quirks in x86 world.
> >>>>
> >>>> Do you think the Windows driver would use DMI ?
> >>>
> >>> Linux is using DMI for quirks.
> >>>
> >>>> That seems quite
> >>>> unlikely to me, given how they would have to release a new driver binary
> >>>> for every machine. I'm pretty sure that a different mechanism is used to
> >>>> identify camera integration, and I think it would make sense to follow
> >>>> the same approach. That would allow us to avoid large tables of DMI
> >>>> identifiers that would need to be constently updated, potentially making
> >>>> user experience better.
> >>>
> >>> All Surface family can be matched in a way as Apple machines [1].
> >>>
> >>> [1]: https://lkml.org/lkml/2020/4/15/1198
> >>
> >> But not all Surface machines necessarily have the same camera
> >> architecture. My point is that there seems to be identifiers reported in
> >> ACPI for the exact purpose of identifying the camera architecture. If we
> >> used DMI instead, we would have to handle each machine individually.
> >
> > With help of DMI we may narrow down the search.
> >
> > But again, we are talking about uncertainity. It may be your way (a lot of
> > platforms that have different settings), or mine (only a few with more or less
> > standard sets of settings).
> >
> > DMI is simply standard in Linux (people usually easier can grep for quirks for
> > a specific platform).
> >
> > I would rather ask Hans' opinion since he has quite an expertise with DMI for
> > good and bad.
>
> So generally there are 2 ways how things like this can go:
>
> 1) There is sufficient information in the ACPI table and we use data from the
> ACPI tables
>
> 2) There is unsufficient info in the ACPI tables (or we don't know how to
> get / interpret the data) and we use DMI quirks
>
> Although we do often also use a combination, getting what we can from ACPI,
> combined with a set of defaults for what we cannot get from ACPI
> based on what reference designs use (IOW what most devices seem to have
> copy and pasted). Combined with DMI quirks for when the defaults do not
> work (which is quite often).
>
> Depending on if "not working because of wrong defaults" has bad side effects,
> another option is also to only allow the driver to load on devices which
> have the necessary info provided through a DMI match.
>
> I hope this helps.

Thanks! Yes, it sounds to me as a useful input!

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 18:49       ` Andy Shevchenko
@ 2020-12-01 20:59         ` Dan Scally
  2020-12-02  9:39           ` Andy Shevchenko
  2020-12-13 22:48         ` Daniel Scally
  1 sibling, 1 reply; 144+ messages in thread
From: Dan Scally @ 2020-12-01 20:59 UTC (permalink / raw)
  To: Andy Shevchenko, Laurent Pinchart
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

Hi Andy

On 01/12/2020 18:49, Andy Shevchenko wrote:

>  P.S. Dan, can you drop unrelated text when replying?

Ah - sure, sorry.
> Seems we can do this, by locating intel_int3472.c under PDx86 hood and dropping
> ACPI ID table from TPS68470 MFD driver. The PMIC can be instantiated via
> i2c_acpi_new_device() (IIRC the API name).
>
> And actually it makes more sense since it's not and MFD and should not be there.
>
> (Dan, patch wise the one creates intel_int3472.c followed by another one that
>  moves ACPI ID from PMIC and introduces its instantiation via I²C board info
>  structure)

I'm mostly following this, but why would we need an i2c_board_info or
i2c_acpi_new_device()? The INT3472 entries that refer to actual tps68470
devices do have an I2cSerialBusV2 enumerated in _CRS so in their case
there's an i2c device registered with the kernel already.


I think we need those things when we get round to handling the
VCM/EEPROM that's hidden within the sensor's ACPI entry, but I've not
done any work on that yet at all.



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 19:21               ` Andy Shevchenko
  2020-12-01 20:34                 ` Hans de Goede
@ 2020-12-01 21:05                 ` Dan Scally
  2020-12-02  9:42                   ` Andy Shevchenko
  1 sibling, 1 reply; 144+ messages in thread
From: Dan Scally @ 2020-12-01 21:05 UTC (permalink / raw)
  To: Andy Shevchenko, Laurent Pinchart
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus, Hans de Goede


On 01/12/2020 19:21, Andy Shevchenko wrote:
> On Tue, Dec 01, 2020 at 09:06:38PM +0200, Laurent Pinchart wrote:
>> On Tue, Dec 01, 2020 at 09:05:23PM +0200, Andy Shevchenko wrote:
>>> On Tue, Dec 01, 2020 at 08:55:48PM +0200, Laurent Pinchart wrote:
>>>
>>>> Do you think the Windows driver would use DMI ?
>>> Linux is using DMI for quirks.
>>>
>>>> That seems quite
>>>> unlikely to me, given how they would have to release a new driver binary
>>>> for every machine. I'm pretty sure that a different mechanism is used to
>>>> identify camera integration, and I think it would make sense to follow
>>>> the same approach. That would allow us to avoid large tables of DMI
>>>> identifiers that would need to be constently updated, potentially making
>>>> user experience better.
>>> All Surface family can be matched in a way as Apple machines [1].
>>>
>>> [1]: https://lkml.org/lkml/2020/4/15/1198
>> But not all Surface machines necessarily have the same camera
>> architecture. My point is that there seems to be identifiers reported in
>> ACPI for the exact purpose of identifying the camera architecture. If we
>> used DMI instead, we would have to handle each machine individually.
> With help of DMI we may narrow down the search.
>
> But again, we are talking about uncertainity. It may be your way (a lot of
> platforms that have different settings), or mine (only a few with more or less
> standard sets of settings).
>
> DMI is simply standard in Linux (people usually easier can grep for quirks for
> a specific platform).
>
> I would rather ask Hans' opinion since he has quite an expertise with DMI for
> good and bad.
>
I have no real preference as to the current method or DMI, but thoughts
that come to mind are:


1. given your info that low byte 0x0c means clock enable, we need to
register a clock too. Do we need to extend this device specific section
to map a clock name, or is it acceptable for them to be nameless (ISTR
that the API will let you fetch a clock using devm_clock_get(dev, NULL);)

2. Given only 0x0b pin is actually a regulator and it's controlling
multiple devices, my plan when we got round to adding the VCM / EEPROM
support was simply to extend those mapping tables so that those
supplementary devices were also able to get that regulator...and the two
would share it. I think, from reading the regulator code and
documentation, that that's all fine - and it won't actually be disabled
until both drivers disable it. Does that sound about right?


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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-30 17:09   ` Laurent Pinchart
  2020-11-30 18:14     ` Andy Shevchenko
@ 2020-12-01 22:08     ` Dan Scally
  2020-12-01 22:11       ` Dan Scally
  2020-12-01 22:30       ` Laurent Pinchart
  1 sibling, 2 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-01 22:08 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Laurent - thanks for reviewing

On 30/11/2020 17:09, Laurent Pinchart wrote:
> Hi Daniel,
> 
> Thank you for the patch.
> 
> On Mon, Nov 30, 2020 at 01:31:24PM +0000, Daniel Scally wrote:
>> Currently on platforms designed for Windows, connections between CIO2 and
>> sensors are not properly defined in DSDT. This patch extends the ipu3-cio2
>> driver to compensate by building software_node connections, parsing the
>> connection properties from the sensor's SSDB buffer.
>>
>> Suggested-by: Jordan Hand <jorhand@linux.microsoft.com>
>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>> ---
>> Changes since RFC v3:
>>
>> 	- Removed almost all global variables, dynamically allocated
>> 	the cio2_bridge structure, plus a bunch of associated changes
>> 	like 
>> 	- Added a new function to ipu3-cio2-main.c to check for an 
>> 	existing fwnode_graph before calling cio2_bridge_init()
>> 	- Prefixed cio2_bridge_ to any variables and functions that
>> 	lacked it
>> 	- Assigned the new fwnode directly to the sensor's ACPI device
>> 	fwnode as secondary. This removes the requirement to delay until
>> 	the I2C devices are instantiated before ipu3-cio2 can probe, but
>> 	it has a side effect, which is that those devices then grab a ref
>> 	to the new software_node. This effectively prevents us from
>> 	unloading the driver, because we can't free the memory that they
>> 	live in whilst the device holds a reference to them. The work
>> 	around at the moment is to _not_ unregister the software_nodes
>> 	when ipu3-cio2 is unloaded; this becomes a one-time 'patch', that
>> 	is simply skipped if the module is reloaded.
>> 	- Moved the sensor's SSDB struct to be a member of cio2_sensor
>> 	- Replaced ints with unsigned ints where appropriate
>> 	- Iterated over all ACPI devices of a matching _HID rather than
>> 	just the first to ensure we handle a device with multiple sensors
>> 	of the same model.
>>
>>  MAINTAINERS                                   |   1 +
>>  drivers/media/pci/intel/ipu3/Kconfig          |  18 ++
>>  drivers/media/pci/intel/ipu3/Makefile         |   1 +
>>  drivers/media/pci/intel/ipu3/cio2-bridge.c    | 260 ++++++++++++++++++
>>  drivers/media/pci/intel/ipu3/cio2-bridge.h    | 108 ++++++++
>>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  27 ++
>>  drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   6 +
>>  7 files changed, 421 insertions(+)
>>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
>>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 9702b886d6a4..188559a0a610 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -8927,6 +8927,7 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
>>  M:	Yong Zhi <yong.zhi@intel.com>
>>  M:	Sakari Ailus <sakari.ailus@linux.intel.com>
>>  M:	Bingbu Cao <bingbu.cao@intel.com>
>> +M:	Dan Scally <djrscally@gmail.com>
>>  R:	Tianshu Qiu <tian.shu.qiu@intel.com>
>>  L:	linux-media@vger.kernel.org
>>  S:	Maintained
>> diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
>> index 82d7f17e6a02..2b3350d042be 100644
>> --- a/drivers/media/pci/intel/ipu3/Kconfig
>> +++ b/drivers/media/pci/intel/ipu3/Kconfig
>> @@ -16,3 +16,21 @@ config VIDEO_IPU3_CIO2
>>  	  Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2
>>  	  connected camera.
>>  	  The module will be called ipu3-cio2.
>> +
>> +config CIO2_BRIDGE
>> +	bool "IPU3 CIO2 Sensors Bridge"
>> +	depends on VIDEO_IPU3_CIO2
>> +	help
>> +	  This extension provides an API for the ipu3-cio2 driver to create
>> +	  connections to cameras that are hidden in SSDB buffer in ACPI. It
>> +	  can be used to enable support for cameras in detachable / hybrid
>> +	  devices that ship with Windows.
>> +
>> +	  Say Y here if your device is a detachable / hybrid laptop that comes
>> +	  with Windows installed by the OEM, for example:
>> +
>> +	  	- Microsoft Surface models (except Surface Pro 3)
>> +		- The Lenovo Miix line (for example the 510, 520, 710 and 720)
>> +		- Dell 7285
>> +
>> +	  If in doubt, say N here.
>> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
>> index 429d516452e4..933777e6ea8a 100644
>> --- a/drivers/media/pci/intel/ipu3/Makefile
>> +++ b/drivers/media/pci/intel/ipu3/Makefile
>> @@ -2,3 +2,4 @@
>>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
>>  
>>  ipu3-cio2-y += ipu3-cio2-main.o
>> +ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
>> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
>> new file mode 100644
>> index 000000000000..fd3f8ba07274
>> --- /dev/null
>> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
>> @@ -0,0 +1,260 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/* Author: Dan Scally <djrscally@gmail.com> */
> 
> Could you please add a blank line here ?

Yes
>> +#include <linux/acpi.h>
>> +#include <linux/device.h>
>> +#include <linux/i2c.h>
> 
> Is this header needed ?
> 
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
> 
> And this one ?
> 
>> +#include <linux/pci.h>
>> +#include <linux/property.h>
>> +#include <media/v4l2-subdev.h>
> 
> And this one ?

Ah yes - bit sloppy, they're orphaned from earlier versions, sorry about
that.

>> +
>> +#include "cio2-bridge.h"
>> +
>> +/*
>> + * Extend this array with ACPI Hardware ID's of devices known to be working.
>> + * Do not add a HID for a sensor that is not actually supported.
>> + */
>> +static const char * const cio2_supported_devices[] = {
> 
> Maybe cio2_supported_sensors ?

Sure

>> +	"INT33BE",
>> +	"OVTI2680",
>> +};
>> +
>> +static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id,
>> +					void *data, u32 size)
>> +{
>> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
>> +	union acpi_object *obj;
>> +	acpi_status status;
>> +	int ret;
>> +
>> +	status = acpi_evaluate_object(adev->handle, id, NULL, &buffer);
>> +	if (ACPI_FAILURE(status))
>> +		return -ENODEV;
>> +
>> +	obj = buffer.pointer;
>> +	if (!obj) {
>> +		dev_err(&adev->dev, "Couldn't locate ACPI buffer\n");
>> +		return -ENODEV;
>> +	}
>> +
>> +	if (obj->type != ACPI_TYPE_BUFFER) {
>> +		dev_err(&adev->dev, "Not an ACPI buffer\n");
>> +		ret = -ENODEV;
>> +		goto out_free_buff;
>> +	}
>> +
>> +	if (obj->buffer.length > size) {
>> +		dev_err(&adev->dev, "Given buffer is too small\n");
>> +		ret = -EINVAL;
>> +		goto out_free_buff;
>> +	}
>> +
>> +	memcpy(data, obj->buffer.pointer, obj->buffer.length);
>> +	ret = obj->buffer.length;
>> +
>> +out_free_buff:
>> +	kfree(buffer.pointer);
>> +	return ret;
>> +}
>> +
>> +static void cio2_bridge_init_property_names(struct cio2_sensor *sensor)
>> +{
>> +	strcpy(sensor->prop_names.clock_frequency, "clock-frequency");
>> +	strcpy(sensor->prop_names.rotation, "rotation");
>> +	strcpy(sensor->prop_names.bus_type, "bus-type");
>> +	strcpy(sensor->prop_names.data_lanes, "data-lanes");
>> +	strcpy(sensor->prop_names.remote_endpoint, "remote-endpoint");
> 
> This is a bit fragile, as there's no len check. How about the following
> ?
> static const struct cio2_property_names prop_names = {
> 	.clock_frequency = "clock-frequency",
> 	.rotation = "rotation",
> 	.bus_type = "bus-type",
> 	.data_lanes = "data-lanes",
> 	.remote_endpoint = "remote-endpoint",
> };
> 
> static void cio2_bridge_init_property_names(struct cio2_sensor *sensor)
> {
> 	sensor->prop_names = prop_names;
> }
> 
> This shoudl generate a compilation warning if the string is too long.
> 
> You could even inline that line in
> cio2_bridge_create_fwnode_properties().

Yes, I like that, thanks - I'll make the change.

>> +}
>> +
>> +static void cio2_bridge_create_fwnode_properties(struct cio2_sensor *sensor)
>> +{
>> +	unsigned int i;
>> +
>> +	cio2_bridge_init_property_names(sensor);
>> +
>> +	for (i = 0; i < 4; i++)
>> +		sensor->data_lanes[i] = i + 1;
> 
> Is there no provision in the SSDB for data lane remapping ?

Sorry; don't follow what you mean by data lane remapping here.

>> +
>> +	/*
>> +	 * Can't use PROPERTY_ENTRY_REF because it creates a new variable to
>> +	 * point to, which doesn't survive the function.
>> +	 */
>> +	sensor->local_ref[0] = (struct software_node_ref_args){
>> +		.node = &sensor->swnodes[SWNODE_CIO2_ENDPOINT]
>> +		};
> 
> I'd remove one tab here. Or just write
> 
> 	sensor->local_ref[0].node = &sensor->swnodes[SWNODE_CIO2_ENDPOINT];

Yep, changed.

>> +	sensor->remote_ref[0] = (struct software_node_ref_args){
>> +		.node = &sensor->swnodes[SWNODE_SENSOR_ENDPOINT]
>> +		};
>> +
>> +	sensor->dev_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.clock_frequency,
>> +						       sensor->ssdb.mclkspeed);
>> +	sensor->dev_properties[1] = PROPERTY_ENTRY_U8(sensor->prop_names.rotation,
>> +						      sensor->ssdb.degree);
>> +
>> +	sensor->ep_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.bus_type, 5);
>> +	sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes,
>> +								sensor->data_lanes,
>> +								sensor->ssdb.lanes);
>> +	sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint,
>> +							    sensor->local_ref);
>> +
>> +	sensor->cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes,
>> +								  sensor->data_lanes,
>> +								  sensor->ssdb.lanes);
>> +	sensor->cio2_properties[1] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint,
>> +							      sensor->remote_ref);
>> +}
>> +
>> +static void cio2_bridge_init_swnode_names(struct cio2_sensor *sensor)
>> +{
>> +	snprintf(sensor->node_names.remote_port, 6, "port%u", sensor->ssdb.link);
>> +	strcpy(sensor->node_names.port, "port0");
>> +	strcpy(sensor->node_names.endpoint, "endpoint0");
>> +}
>> +
>> +static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge,
>> +						  struct cio2_sensor *sensor)
>> +{
>> +	struct software_node *nodes = sensor->swnodes;
>> +
>> +	cio2_bridge_init_swnode_names(sensor);
>> +
>> +	nodes[SWNODE_SENSOR_HID] = NODE_SENSOR(sensor->name,
>> +					       sensor->dev_properties);
>> +	nodes[SWNODE_SENSOR_PORT] = NODE_PORT(sensor->node_names.port,
>> +					      &nodes[SWNODE_SENSOR_HID]);
>> +	nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint,
>> +						      &nodes[SWNODE_SENSOR_PORT],
>> +						      sensor->ep_properties);
>> +	nodes[SWNODE_CIO2_PORT] = NODE_PORT(sensor->node_names.remote_port,
>> +					    &bridge->cio2_hid_node);
>> +	nodes[SWNODE_CIO2_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint,
>> +						    &nodes[SWNODE_CIO2_PORT],
>> +						    sensor->cio2_properties);
>> +}
>> +
>> +static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge)
>> +{
>> +	struct cio2_sensor *sensor;
>> +	unsigned int i;
>> +
>> +	for (i = 0; i < bridge->n_sensors; i++) {
>> +		sensor = &bridge->sensors[i];
>> +		software_node_unregister_nodes(sensor->swnodes);
>> +		acpi_dev_put(sensor->adev);
>> +	}
>> +}
>> +
>> +static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge)
>> +{
>> +	struct fwnode_handle *fwnode;
>> +	struct cio2_sensor *sensor;
>> +	struct acpi_device *adev;
>> +	unsigned int i;
>> +	int ret = 0;
>> +
>> +	for (i = 0; i < ARRAY_SIZE(cio2_supported_devices); i++) {
>> +		const char *this_device = cio2_supported_devices[i];
> 
> s/this_device/name/ (or sensor_name, ...) ?

I went for hid as Andy suggested.
> 
>> +
>> +		for_each_acpi_dev_match(adev, this_device, NULL, -1) {
>> +			if (!adev || !(adev->status.present && adev->status.enabled))
> 
> 			if (!adev || !adev->status.present || !adev->status.enabled))
> 
> may be a bit more readable. Does for_each_acpi_dev_match() return NULL
> devices though ? If no, you could drop the !adev check. You may also be
> able to drop the !present check, as I don't think ACPI allows !present
> && enabled.

You're right, the spec mandates enabled be 0 if present is 0. The
iterator will return NULL when the previous return value was the last
matching device, so that part needs to stay, but it can become:

if (!adev || !adev->status.enabled)

>> +				continue;
>> +
>> +			sensor = &bridge->sensors[bridge->n_sensors];
>> +			sensor->adev = adev;
>> +			strscpy(sensor->name, this_device, sizeof(sensor->name));
>> +
>> +			ret = cio2_bridge_read_acpi_buffer(adev, "SSDB",
>> +							   &sensor->ssdb,
>> +							   sizeof(sensor->ssdb));
>> +			if (ret < 0)
>> +				goto err_put_adev;
>> +
>> +			if (sensor->ssdb.lanes > 4) {
>> +				dev_err(&adev->dev,
>> +					"Number of lanes in SSDB is invalid\n");
>> +				goto err_put_adev;
>> +			}
>> +
>> +			cio2_bridge_create_fwnode_properties(sensor);
>> +			cio2_bridge_create_connection_swnodes(bridge, sensor);
>> +
>> +			ret = software_node_register_nodes(sensor->swnodes);
>> +			if (ret)
>> +				goto err_put_adev;
>> +
>> +			fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR_HID]);
>> +			if (!fwnode) {
>> +				ret = -ENODEV;
>> +				goto err_free_swnodes;
>> +			}
>> +
>> +			adev->fwnode.secondary = fwnode;
>> +
>> +			dev_info(&bridge->cio2->dev,
>> +				 "Found supported sensor %s\n",
>> +				 acpi_dev_name(adev));
>> +
>> +			bridge->n_sensors++;
> 
> We probably want a check here to avoid overflowing bridge->sensors. The
> other option is to make bridge->sensors a struct list_head and allocate
> sensors dynamically.

Err - agree on a check. There's only 4 ports in a CIO2 device, so that's
the maximum. Seems easier to just do a check, unless the wasted memory
is enough that it's worth allocating dynamically. I don't mind either
approach.

>> +		}
>> +	}
>> +
>> +	return ret;
>> +
>> +err_free_swnodes:
>> +	software_node_unregister_nodes(sensor->swnodes);
>> +err_put_adev:
>> +	acpi_dev_put(sensor->adev);
>> +
>> +	return ret;
>> +}
>> +
>> +int cio2_bridge_init(struct pci_dev *cio2)
>> +{
>> +	struct device *dev = &cio2->dev;
>> +	struct fwnode_handle *fwnode;
>> +	struct cio2_bridge *bridge;
>> +	int ret;
>> +
>> +	bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
>> +	if (!bridge)
>> +		return -ENOMEM;
>> +
>> +	strscpy(bridge->cio2_node_name, CIO2_HID, sizeof(bridge->cio2_node_name));
>> +	bridge->cio2_hid_node = (const struct software_node){ bridge->cio2_node_name };
> 
> Maybe just
> 
> 	bridge->cio2_hid_node.name = bridge->cio2_node_name;
> 
> as the rest is already zeroed by the kzalloc() call ?
> 
>> +	bridge->cio2 = pci_dev_get(cio2);
> 
> As the cio2 pointer is only used to print a message in
> cio2_bridge_connect_sensors(), do we need to store it in the bridge
> structure, and take a reference to the device ?
> 
>> +
>> +	ret = software_node_register(&bridge->cio2_hid_node);
>> +	if (ret < 0) {
>> +		dev_err(dev, "Failed to register the CIO2 HID node\n");
>> +		goto err_put_cio2;
>> +	}
>> +
>> +	ret = cio2_bridge_connect_sensors(bridge);
>> +	if (ret || bridge->n_sensors == 0)
>> +		goto err_unregister_cio2;
>> +
>> +	dev_info(dev, "Connected %d cameras\n", bridge->n_sensors);
>> +
>> +	fwnode = software_node_fwnode(&bridge->cio2_hid_node);
>> +	if (!fwnode) {
>> +		dev_err(dev, "Error getting fwnode from cio2 software_node\n");
>> +		ret = -ENODEV;
>> +		goto err_unregister_sensors;
> 
> Can this happen ?

It _shouldn't_ happen, as long as nothing else is touching the swnodes
I've registered or anything. I've never seen it happen. That didn't feel
like quite enough to say it can't ever happen - but I'm happy to skip
the check if you think thats ok.

>> +	}
>> +
>> +	set_secondary_fwnode(dev, fwnode);
>> +
>> +	return 0;
>> +
>> +err_unregister_sensors:
>> +	cio2_bridge_unregister_sensors(bridge);
>> +err_unregister_cio2:
>> +	software_node_unregister(&bridge->cio2_hid_node);
>> +err_put_cio2:
>> +	pci_dev_put(bridge->cio2);
>> +
>> +	kfree(bridge);
>> +	return ret;
>> +}
>> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h
>> new file mode 100644
>> index 000000000000..96f5c8a12be0
>> --- /dev/null
>> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h
> 
> This file is only included by cio2-bridge.c, so you could inline it
> there. Up to you.

I think I like them separate


>> @@ -0,0 +1,108 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/* Author: Dan Scally <djrscally@gmail.com> */
>> +#ifndef __CIO2_BRIDGE_H
>> +#define __CIO2_BRIDGE_H
>> +
>> +#include <linux/property.h>
>> +
>> +#define CIO2_HID				"INT343E"
>> +#define CIO2_NUM_PORTS			  4
> 
> There are a few rogue spaces before '4'.

Argh, thanks, this is the curse of using VS code on multiple machines...
> 
>> +
>> +#define NODE_SENSOR(_HID, _PROPS)		\
>> +	((const struct software_node) {		\
>> +		.name = _HID,			\
>> +		.properties = _PROPS,		\
>> +	})
>> +
>> +#define NODE_PORT(_PORT, _SENSOR_NODE)		\
>> +	((const struct software_node) {		\
>> +		_PORT,				\
>> +		_SENSOR_NODE,			\
>> +	})
>> +
>> +#define NODE_ENDPOINT(_EP, _PORT, _PROPS)	\
>> +	((const struct software_node) {		\
>> +		_EP,				\
>> +		_PORT,				\
>> +		_PROPS,				\
>> +	})
>> +
>> +enum cio2_sensor_swnodes {
>> +	SWNODE_SENSOR_HID,
>> +	SWNODE_SENSOR_PORT,
>> +	SWNODE_SENSOR_ENDPOINT,
>> +	SWNODE_CIO2_PORT,
>> +	SWNODE_CIO2_ENDPOINT,
>> +	NR_OF_SENSOR_SWNODES
>> +};
>> +
>> +/* Data representation as it is in ACPI SSDB buffer */
>> +struct cio2_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 cio2_property_names {
>> +	char clock_frequency[16];
>> +	char rotation[9];
>> +	char bus_type[9];
>> +	char data_lanes[11];
>> +	char remote_endpoint[16];
>> +};
>> +
>> +struct cio2_node_names {
>> +	char port[6];
>> +	char endpoint[10];
>> +	char remote_port[6];
>> +};
>> +
>> +struct cio2_sensor {
>> +	char name[ACPI_ID_LEN];
>> +	struct acpi_device *adev;
>> +
>> +	struct software_node swnodes[6];
>> +	struct cio2_node_names node_names;
>> +
>> +	u32 data_lanes[4];
>> +	struct cio2_sensor_ssdb ssdb;
>> +	struct cio2_property_names prop_names;
>> +	struct property_entry ep_properties[4];
>> +	struct property_entry dev_properties[3];
>> +	struct property_entry cio2_properties[3];
>> +	struct software_node_ref_args local_ref[1];
>> +	struct software_node_ref_args remote_ref[1];
>> +};
>> +
>> +struct cio2_bridge {
>> +	struct pci_dev *cio2;
>> +	char cio2_node_name[ACPI_ID_LEN];
>> +	struct software_node cio2_hid_node;
>> +	unsigned int n_sensors;
>> +	struct cio2_sensor sensors[CIO2_NUM_PORTS];
>> +};
>> +
>> +#endif
>> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
>> index 36e354ecf71e..0d69b593e9f0 100644
>> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
>> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
>> @@ -1702,6 +1702,22 @@ static void cio2_queues_exit(struct cio2_device *cio2)
>>  		cio2_queue_exit(cio2, &cio2->queue[i]);
>>  }
>>  
>> +static bool cio2_check_fwnode_graph(struct fwnode_handle *fwnode)
>> +{
>> +	struct fwnode_handle *endpoint;
>> +
>> +	if (IS_ERR_OR_NULL(fwnode))
>> +		return false;
>> +
>> +	endpoint = fwnode_graph_get_next_endpoint(fwnode, NULL);
>> +	if (endpoint) {
>> +		fwnode_handle_put(endpoint);
>> +		return true;
>> +	}
>> +
>> +	return cio2_check_fwnode_graph(fwnode->secondary);
> 
> If we have a fwnode->secondary and this check fails there's something
> seriously wrong, I wonder if we should print an error message.

Yes, probably a good thought, since nothing will work in that case. I'll
add something appropriate.

> 
> Overall this is nice. I think the next version will get my ack :-)

Excellent :)

>> +}
>> +
>>  /**************** PCI interface ****************/
>>  
>>  static int cio2_pci_probe(struct pci_dev *pci_dev,
>> @@ -1715,6 +1731,17 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
>>  		return -ENOMEM;
>>  	cio2->pci_dev = pci_dev;
>>  
>> +	/*
>> +	 * On some platforms no connections to sensors are defined in firmware,
>> +	 * if the device has no endpoints then we can try to build those as
>> +	 * software_nodes parsed from SSDB.
>> +	 */
>> +	if (!cio2_check_fwnode_graph(dev_fwnode(&pci_dev->dev))) {
>> +		r = cio2_bridge_init(pci_dev);
>> +		if (r)
>> +			return r;
>> +	}
>> +
>>  	r = pcim_enable_device(pci_dev);
>>  	if (r) {
>>  		dev_err(&pci_dev->dev, "failed to enable device (%d)\n", r);
>> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.h b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
>> index ccf0b85ae36f..520a27c9cdad 100644
>> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.h
>> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
>> @@ -437,4 +437,10 @@ static inline struct cio2_queue *vb2q_to_cio2_queue(struct vb2_queue *vq)
>>  	return container_of(vq, struct cio2_queue, vbq);
>>  }
>>  
>> +#if IS_ENABLED(CONFIG_CIO2_BRIDGE)
>> +int cio2_bridge_init(struct pci_dev *cio2);
>> +#else
>> +int cio2_bridge_init(struct pci_dev *cio2) { return 0; }
>> +#endif
>> +
>>  #endif
> 


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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-12-01 22:08     ` Dan Scally
@ 2020-12-01 22:11       ` Dan Scally
  2020-12-01 22:30       ` Laurent Pinchart
  1 sibling, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-01 22:11 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus


On 01/12/2020 22:08, Dan Scally wrote:
>>> +
>>> +		for_each_acpi_dev_match(adev, this_device, NULL, -1) {
>>> +			if (!adev || !(adev->status.present && adev->status.enabled))
>> 			if (!adev || !adev->status.present || !adev->status.enabled))
>>
>> may be a bit more readable. Does for_each_acpi_dev_match() return NULL
>> devices though ? If no, you could drop the !adev check. You may also be
>> able to drop the !present check, as I don't think ACPI allows !present
>> && enabled.
> You're right, the spec mandates enabled be 0 if present is 0. The
> iterator will return NULL when the previous return value was the last
> matching device, so that part needs to stay, but it can become:
>
> if (!adev || !adev->status.enabled)
>
Wait, that's silly, the loop won't start if the check is null so you're
right of course.

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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-12-01 22:08     ` Dan Scally
  2020-12-01 22:11       ` Dan Scally
@ 2020-12-01 22:30       ` Laurent Pinchart
  2020-12-01 23:15         ` Dan Scally
  2020-12-02 10:38         ` Sakari Ailus
  1 sibling, 2 replies; 144+ messages in thread
From: Laurent Pinchart @ 2020-12-01 22:30 UTC (permalink / raw)
  To: Dan Scally
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Daniel,

On Tue, Dec 01, 2020 at 10:08:25PM +0000, Dan Scally wrote:
> On 30/11/2020 17:09, Laurent Pinchart wrote:
> > On Mon, Nov 30, 2020 at 01:31:24PM +0000, Daniel Scally wrote:
> >> Currently on platforms designed for Windows, connections between CIO2 and
> >> sensors are not properly defined in DSDT. This patch extends the ipu3-cio2
> >> driver to compensate by building software_node connections, parsing the
> >> connection properties from the sensor's SSDB buffer.
> >>
> >> Suggested-by: Jordan Hand <jorhand@linux.microsoft.com>
> >> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> >> ---
> >> Changes since RFC v3:
> >>
> >> 	- Removed almost all global variables, dynamically allocated
> >> 	the cio2_bridge structure, plus a bunch of associated changes
> >> 	like 
> >> 	- Added a new function to ipu3-cio2-main.c to check for an 
> >> 	existing fwnode_graph before calling cio2_bridge_init()
> >> 	- Prefixed cio2_bridge_ to any variables and functions that
> >> 	lacked it
> >> 	- Assigned the new fwnode directly to the sensor's ACPI device
> >> 	fwnode as secondary. This removes the requirement to delay until
> >> 	the I2C devices are instantiated before ipu3-cio2 can probe, but
> >> 	it has a side effect, which is that those devices then grab a ref
> >> 	to the new software_node. This effectively prevents us from
> >> 	unloading the driver, because we can't free the memory that they
> >> 	live in whilst the device holds a reference to them. The work
> >> 	around at the moment is to _not_ unregister the software_nodes
> >> 	when ipu3-cio2 is unloaded; this becomes a one-time 'patch', that
> >> 	is simply skipped if the module is reloaded.
> >> 	- Moved the sensor's SSDB struct to be a member of cio2_sensor
> >> 	- Replaced ints with unsigned ints where appropriate
> >> 	- Iterated over all ACPI devices of a matching _HID rather than
> >> 	just the first to ensure we handle a device with multiple sensors
> >> 	of the same model.
> >>
> >>  MAINTAINERS                                   |   1 +
> >>  drivers/media/pci/intel/ipu3/Kconfig          |  18 ++
> >>  drivers/media/pci/intel/ipu3/Makefile         |   1 +
> >>  drivers/media/pci/intel/ipu3/cio2-bridge.c    | 260 ++++++++++++++++++
> >>  drivers/media/pci/intel/ipu3/cio2-bridge.h    | 108 ++++++++
> >>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  27 ++
> >>  drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   6 +
> >>  7 files changed, 421 insertions(+)
> >>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
> >>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h
> >>
> >> diff --git a/MAINTAINERS b/MAINTAINERS
> >> index 9702b886d6a4..188559a0a610 100644
> >> --- a/MAINTAINERS
> >> +++ b/MAINTAINERS
> >> @@ -8927,6 +8927,7 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
> >>  M:	Yong Zhi <yong.zhi@intel.com>
> >>  M:	Sakari Ailus <sakari.ailus@linux.intel.com>
> >>  M:	Bingbu Cao <bingbu.cao@intel.com>
> >> +M:	Dan Scally <djrscally@gmail.com>
> >>  R:	Tianshu Qiu <tian.shu.qiu@intel.com>
> >>  L:	linux-media@vger.kernel.org
> >>  S:	Maintained
> >> diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
> >> index 82d7f17e6a02..2b3350d042be 100644
> >> --- a/drivers/media/pci/intel/ipu3/Kconfig
> >> +++ b/drivers/media/pci/intel/ipu3/Kconfig
> >> @@ -16,3 +16,21 @@ config VIDEO_IPU3_CIO2
> >>  	  Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2
> >>  	  connected camera.
> >>  	  The module will be called ipu3-cio2.
> >> +
> >> +config CIO2_BRIDGE
> >> +	bool "IPU3 CIO2 Sensors Bridge"
> >> +	depends on VIDEO_IPU3_CIO2
> >> +	help
> >> +	  This extension provides an API for the ipu3-cio2 driver to create
> >> +	  connections to cameras that are hidden in SSDB buffer in ACPI. It
> >> +	  can be used to enable support for cameras in detachable / hybrid
> >> +	  devices that ship with Windows.
> >> +
> >> +	  Say Y here if your device is a detachable / hybrid laptop that comes
> >> +	  with Windows installed by the OEM, for example:
> >> +
> >> +	  	- Microsoft Surface models (except Surface Pro 3)
> >> +		- The Lenovo Miix line (for example the 510, 520, 710 and 720)
> >> +		- Dell 7285
> >> +
> >> +	  If in doubt, say N here.
> >> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
> >> index 429d516452e4..933777e6ea8a 100644
> >> --- a/drivers/media/pci/intel/ipu3/Makefile
> >> +++ b/drivers/media/pci/intel/ipu3/Makefile
> >> @@ -2,3 +2,4 @@
> >>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
> >>  
> >>  ipu3-cio2-y += ipu3-cio2-main.o
> >> +ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
> >> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> >> new file mode 100644
> >> index 000000000000..fd3f8ba07274
> >> --- /dev/null
> >> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> >> @@ -0,0 +1,260 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/* Author: Dan Scally <djrscally@gmail.com> */
> > 
> > Could you please add a blank line here ?
> 
> Yes
>
> >> +#include <linux/acpi.h>
> >> +#include <linux/device.h>
> >> +#include <linux/i2c.h>
> > 
> > Is this header needed ?
> > 
> >> +#include <linux/kernel.h>
> >> +#include <linux/module.h>
> > 
> > And this one ?
> > 
> >> +#include <linux/pci.h>
> >> +#include <linux/property.h>
> >> +#include <media/v4l2-subdev.h>
> > 
> > And this one ?
> 
> Ah yes - bit sloppy, they're orphaned from earlier versions, sorry about
> that.
> 
> >> +
> >> +#include "cio2-bridge.h"
> >> +
> >> +/*
> >> + * Extend this array with ACPI Hardware ID's of devices known to be working.
> >> + * Do not add a HID for a sensor that is not actually supported.
> >> + */
> >> +static const char * const cio2_supported_devices[] = {
> > 
> > Maybe cio2_supported_sensors ?
> 
> Sure
> 
> >> +	"INT33BE",
> >> +	"OVTI2680",
> >> +};
> >> +
> >> +static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id,
> >> +					void *data, u32 size)
> >> +{
> >> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> >> +	union acpi_object *obj;
> >> +	acpi_status status;
> >> +	int ret;
> >> +
> >> +	status = acpi_evaluate_object(adev->handle, id, NULL, &buffer);
> >> +	if (ACPI_FAILURE(status))
> >> +		return -ENODEV;
> >> +
> >> +	obj = buffer.pointer;
> >> +	if (!obj) {
> >> +		dev_err(&adev->dev, "Couldn't locate ACPI buffer\n");
> >> +		return -ENODEV;
> >> +	}
> >> +
> >> +	if (obj->type != ACPI_TYPE_BUFFER) {
> >> +		dev_err(&adev->dev, "Not an ACPI buffer\n");
> >> +		ret = -ENODEV;
> >> +		goto out_free_buff;
> >> +	}
> >> +
> >> +	if (obj->buffer.length > size) {
> >> +		dev_err(&adev->dev, "Given buffer is too small\n");
> >> +		ret = -EINVAL;
> >> +		goto out_free_buff;
> >> +	}
> >> +
> >> +	memcpy(data, obj->buffer.pointer, obj->buffer.length);
> >> +	ret = obj->buffer.length;
> >> +
> >> +out_free_buff:
> >> +	kfree(buffer.pointer);
> >> +	return ret;
> >> +}
> >> +
> >> +static void cio2_bridge_init_property_names(struct cio2_sensor *sensor)
> >> +{
> >> +	strcpy(sensor->prop_names.clock_frequency, "clock-frequency");
> >> +	strcpy(sensor->prop_names.rotation, "rotation");
> >> +	strcpy(sensor->prop_names.bus_type, "bus-type");
> >> +	strcpy(sensor->prop_names.data_lanes, "data-lanes");
> >> +	strcpy(sensor->prop_names.remote_endpoint, "remote-endpoint");
> > 
> > This is a bit fragile, as there's no len check. How about the following
> > ?
> > static const struct cio2_property_names prop_names = {
> > 	.clock_frequency = "clock-frequency",
> > 	.rotation = "rotation",
> > 	.bus_type = "bus-type",
> > 	.data_lanes = "data-lanes",
> > 	.remote_endpoint = "remote-endpoint",
> > };
> > 
> > static void cio2_bridge_init_property_names(struct cio2_sensor *sensor)
> > {
> > 	sensor->prop_names = prop_names;
> > }
> > 
> > This shoudl generate a compilation warning if the string is too long.
> > 
> > You could even inline that line in
> > cio2_bridge_create_fwnode_properties().
> 
> Yes, I like that, thanks - I'll make the change.
> 
> >> +}
> >> +
> >> +static void cio2_bridge_create_fwnode_properties(struct cio2_sensor *sensor)
> >> +{
> >> +	unsigned int i;
> >> +
> >> +	cio2_bridge_init_property_names(sensor);
> >> +
> >> +	for (i = 0; i < 4; i++)
> >> +		sensor->data_lanes[i] = i + 1;
> > 
> > Is there no provision in the SSDB for data lane remapping ?
> 
> Sorry; don't follow what you mean by data lane remapping here.

Some CSI-2 receivers can remap data lanes. The routing inside the SoC
from the data lane input pins to the PHYs is configurable. This makes
board design easier as you can route the data lanes to any of the
inputs. That's why the data lanes DT property is a list of lane numbers
instead of a number of lanes. I'm actually not sure if the CIO2 supports
this.
 
> >> +
> >> +	/*
> >> +	 * Can't use PROPERTY_ENTRY_REF because it creates a new variable to
> >> +	 * point to, which doesn't survive the function.
> >> +	 */
> >> +	sensor->local_ref[0] = (struct software_node_ref_args){
> >> +		.node = &sensor->swnodes[SWNODE_CIO2_ENDPOINT]
> >> +		};
> > 
> > I'd remove one tab here. Or just write
> > 
> > 	sensor->local_ref[0].node = &sensor->swnodes[SWNODE_CIO2_ENDPOINT];
> 
> Yep, changed.
> 
> >> +	sensor->remote_ref[0] = (struct software_node_ref_args){
> >> +		.node = &sensor->swnodes[SWNODE_SENSOR_ENDPOINT]
> >> +		};
> >> +
> >> +	sensor->dev_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.clock_frequency,
> >> +						       sensor->ssdb.mclkspeed);
> >> +	sensor->dev_properties[1] = PROPERTY_ENTRY_U8(sensor->prop_names.rotation,
> >> +						      sensor->ssdb.degree);
> >> +
> >> +	sensor->ep_properties[0] = PROPERTY_ENTRY_U32(sensor->prop_names.bus_type, 5);
> >> +	sensor->ep_properties[1] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes,
> >> +								sensor->data_lanes,
> >> +								sensor->ssdb.lanes);
> >> +	sensor->ep_properties[2] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint,
> >> +							    sensor->local_ref);
> >> +
> >> +	sensor->cio2_properties[0] = PROPERTY_ENTRY_U32_ARRAY_LEN(sensor->prop_names.data_lanes,
> >> +								  sensor->data_lanes,
> >> +								  sensor->ssdb.lanes);
> >> +	sensor->cio2_properties[1] = PROPERTY_ENTRY_REF_ARRAY(sensor->prop_names.remote_endpoint,
> >> +							      sensor->remote_ref);
> >> +}
> >> +
> >> +static void cio2_bridge_init_swnode_names(struct cio2_sensor *sensor)
> >> +{
> >> +	snprintf(sensor->node_names.remote_port, 6, "port%u", sensor->ssdb.link);
> >> +	strcpy(sensor->node_names.port, "port0");
> >> +	strcpy(sensor->node_names.endpoint, "endpoint0");
> >> +}
> >> +
> >> +static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge,
> >> +						  struct cio2_sensor *sensor)
> >> +{
> >> +	struct software_node *nodes = sensor->swnodes;
> >> +
> >> +	cio2_bridge_init_swnode_names(sensor);
> >> +
> >> +	nodes[SWNODE_SENSOR_HID] = NODE_SENSOR(sensor->name,
> >> +					       sensor->dev_properties);
> >> +	nodes[SWNODE_SENSOR_PORT] = NODE_PORT(sensor->node_names.port,
> >> +					      &nodes[SWNODE_SENSOR_HID]);
> >> +	nodes[SWNODE_SENSOR_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint,
> >> +						      &nodes[SWNODE_SENSOR_PORT],
> >> +						      sensor->ep_properties);
> >> +	nodes[SWNODE_CIO2_PORT] = NODE_PORT(sensor->node_names.remote_port,
> >> +					    &bridge->cio2_hid_node);
> >> +	nodes[SWNODE_CIO2_ENDPOINT] = NODE_ENDPOINT(sensor->node_names.endpoint,
> >> +						    &nodes[SWNODE_CIO2_PORT],
> >> +						    sensor->cio2_properties);
> >> +}
> >> +
> >> +static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge)
> >> +{
> >> +	struct cio2_sensor *sensor;
> >> +	unsigned int i;
> >> +
> >> +	for (i = 0; i < bridge->n_sensors; i++) {
> >> +		sensor = &bridge->sensors[i];
> >> +		software_node_unregister_nodes(sensor->swnodes);
> >> +		acpi_dev_put(sensor->adev);
> >> +	}
> >> +}
> >> +
> >> +static int cio2_bridge_connect_sensors(struct cio2_bridge *bridge)
> >> +{
> >> +	struct fwnode_handle *fwnode;
> >> +	struct cio2_sensor *sensor;
> >> +	struct acpi_device *adev;
> >> +	unsigned int i;
> >> +	int ret = 0;
> >> +
> >> +	for (i = 0; i < ARRAY_SIZE(cio2_supported_devices); i++) {
> >> +		const char *this_device = cio2_supported_devices[i];
> > 
> > s/this_device/name/ (or sensor_name, ...) ?
> 
> I went for hid as Andy suggested.
>
> > 
> >> +
> >> +		for_each_acpi_dev_match(adev, this_device, NULL, -1) {
> >> +			if (!adev || !(adev->status.present && adev->status.enabled))
> > 
> > 			if (!adev || !adev->status.present || !adev->status.enabled))
> > 
> > may be a bit more readable. Does for_each_acpi_dev_match() return NULL
> > devices though ? If no, you could drop the !adev check. You may also be
> > able to drop the !present check, as I don't think ACPI allows !present
> > && enabled.
> 
> You're right, the spec mandates enabled be 0 if present is 0. The
> iterator will return NULL when the previous return value was the last
> matching device, so that part needs to stay, but it can become:
> 
> if (!adev || !adev->status.enabled)

As you've commented out in a reply, the loop will stop when adev is NULL
:-)

> >> +				continue;
> >> +
> >> +			sensor = &bridge->sensors[bridge->n_sensors];
> >> +			sensor->adev = adev;
> >> +			strscpy(sensor->name, this_device, sizeof(sensor->name));
> >> +
> >> +			ret = cio2_bridge_read_acpi_buffer(adev, "SSDB",
> >> +							   &sensor->ssdb,
> >> +							   sizeof(sensor->ssdb));
> >> +			if (ret < 0)
> >> +				goto err_put_adev;
> >> +
> >> +			if (sensor->ssdb.lanes > 4) {
> >> +				dev_err(&adev->dev,
> >> +					"Number of lanes in SSDB is invalid\n");
> >> +				goto err_put_adev;
> >> +			}
> >> +
> >> +			cio2_bridge_create_fwnode_properties(sensor);
> >> +			cio2_bridge_create_connection_swnodes(bridge, sensor);
> >> +
> >> +			ret = software_node_register_nodes(sensor->swnodes);
> >> +			if (ret)
> >> +				goto err_put_adev;
> >> +
> >> +			fwnode = software_node_fwnode(&sensor->swnodes[SWNODE_SENSOR_HID]);
> >> +			if (!fwnode) {
> >> +				ret = -ENODEV;
> >> +				goto err_free_swnodes;
> >> +			}
> >> +
> >> +			adev->fwnode.secondary = fwnode;
> >> +
> >> +			dev_info(&bridge->cio2->dev,
> >> +				 "Found supported sensor %s\n",
> >> +				 acpi_dev_name(adev));
> >> +
> >> +			bridge->n_sensors++;
> > 
> > We probably want a check here to avoid overflowing bridge->sensors. The
> > other option is to make bridge->sensors a struct list_head and allocate
> > sensors dynamically.
> 
> Err - agree on a check. There's only 4 ports in a CIO2 device, so that's
> the maximum. Seems easier to just do a check, unless the wasted memory
> is enough that it's worth allocating dynamically. I don't mind either
> approach.

In theory we could route multiple sensors to the same receiver, as long
as only one of them drives the lanes at any given time. It's one way to
support multiple sensors in cheap designs. I doubt we'll ever encounter
that with the IPU3, so we could just limit the count to 4.

> >> +		}
> >> +	}
> >> +
> >> +	return ret;
> >> +
> >> +err_free_swnodes:
> >> +	software_node_unregister_nodes(sensor->swnodes);
> >> +err_put_adev:
> >> +	acpi_dev_put(sensor->adev);
> >> +
> >> +	return ret;
> >> +}
> >> +
> >> +int cio2_bridge_init(struct pci_dev *cio2)
> >> +{
> >> +	struct device *dev = &cio2->dev;
> >> +	struct fwnode_handle *fwnode;
> >> +	struct cio2_bridge *bridge;
> >> +	int ret;
> >> +
> >> +	bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
> >> +	if (!bridge)
> >> +		return -ENOMEM;
> >> +
> >> +	strscpy(bridge->cio2_node_name, CIO2_HID, sizeof(bridge->cio2_node_name));
> >> +	bridge->cio2_hid_node = (const struct software_node){ bridge->cio2_node_name };
> > 
> > Maybe just
> > 
> > 	bridge->cio2_hid_node.name = bridge->cio2_node_name;
> > 
> > as the rest is already zeroed by the kzalloc() call ?
> > 
> >> +	bridge->cio2 = pci_dev_get(cio2);
> > 
> > As the cio2 pointer is only used to print a message in
> > cio2_bridge_connect_sensors(), do we need to store it in the bridge
> > structure, and take a reference to the device ?
> > 
> >> +
> >> +	ret = software_node_register(&bridge->cio2_hid_node);
> >> +	if (ret < 0) {
> >> +		dev_err(dev, "Failed to register the CIO2 HID node\n");
> >> +		goto err_put_cio2;
> >> +	}
> >> +
> >> +	ret = cio2_bridge_connect_sensors(bridge);
> >> +	if (ret || bridge->n_sensors == 0)
> >> +		goto err_unregister_cio2;
> >> +
> >> +	dev_info(dev, "Connected %d cameras\n", bridge->n_sensors);
> >> +
> >> +	fwnode = software_node_fwnode(&bridge->cio2_hid_node);
> >> +	if (!fwnode) {
> >> +		dev_err(dev, "Error getting fwnode from cio2 software_node\n");
> >> +		ret = -ENODEV;
> >> +		goto err_unregister_sensors;
> > 
> > Can this happen ?
> 
> It _shouldn't_ happen, as long as nothing else is touching the swnodes
> I've registered or anything. I've never seen it happen. That didn't feel
> like quite enough to say it can't ever happen - but I'm happy to skip
> the check if you think thats ok.

It seems a bit overkill to me, but I'm not a swnode specialist :-)

> >> +	}
> >> +
> >> +	set_secondary_fwnode(dev, fwnode);
> >> +
> >> +	return 0;
> >> +
> >> +err_unregister_sensors:
> >> +	cio2_bridge_unregister_sensors(bridge);
> >> +err_unregister_cio2:
> >> +	software_node_unregister(&bridge->cio2_hid_node);
> >> +err_put_cio2:
> >> +	pci_dev_put(bridge->cio2);
> >> +
> >> +	kfree(bridge);
> >> +	return ret;
> >> +}
> >> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.h b/drivers/media/pci/intel/ipu3/cio2-bridge.h
> >> new file mode 100644
> >> index 000000000000..96f5c8a12be0
> >> --- /dev/null
> >> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.h
> > 
> > This file is only included by cio2-bridge.c, so you could inline it
> > there. Up to you.
> 
> I think I like them separate
> 
> >> @@ -0,0 +1,108 @@
> >> +/* SPDX-License-Identifier: GPL-2.0 */
> >> +/* Author: Dan Scally <djrscally@gmail.com> */
> >> +#ifndef __CIO2_BRIDGE_H
> >> +#define __CIO2_BRIDGE_H
> >> +
> >> +#include <linux/property.h>
> >> +
> >> +#define CIO2_HID				"INT343E"
> >> +#define CIO2_NUM_PORTS			  4
> > 
> > There are a few rogue spaces before '4'.
> 
> Argh, thanks, this is the curse of using VS code on multiple machines...

I recommend vim ;-)

> >> +
> >> +#define NODE_SENSOR(_HID, _PROPS)		\
> >> +	((const struct software_node) {		\
> >> +		.name = _HID,			\
> >> +		.properties = _PROPS,		\
> >> +	})
> >> +
> >> +#define NODE_PORT(_PORT, _SENSOR_NODE)		\
> >> +	((const struct software_node) {		\
> >> +		_PORT,				\
> >> +		_SENSOR_NODE,			\
> >> +	})
> >> +
> >> +#define NODE_ENDPOINT(_EP, _PORT, _PROPS)	\
> >> +	((const struct software_node) {		\
> >> +		_EP,				\
> >> +		_PORT,				\
> >> +		_PROPS,				\
> >> +	})
> >> +
> >> +enum cio2_sensor_swnodes {
> >> +	SWNODE_SENSOR_HID,
> >> +	SWNODE_SENSOR_PORT,
> >> +	SWNODE_SENSOR_ENDPOINT,
> >> +	SWNODE_CIO2_PORT,
> >> +	SWNODE_CIO2_ENDPOINT,
> >> +	NR_OF_SENSOR_SWNODES
> >> +};
> >> +
> >> +/* Data representation as it is in ACPI SSDB buffer */
> >> +struct cio2_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 cio2_property_names {
> >> +	char clock_frequency[16];
> >> +	char rotation[9];
> >> +	char bus_type[9];
> >> +	char data_lanes[11];
> >> +	char remote_endpoint[16];
> >> +};
> >> +
> >> +struct cio2_node_names {
> >> +	char port[6];
> >> +	char endpoint[10];
> >> +	char remote_port[6];
> >> +};
> >> +
> >> +struct cio2_sensor {
> >> +	char name[ACPI_ID_LEN];
> >> +	struct acpi_device *adev;
> >> +
> >> +	struct software_node swnodes[6];
> >> +	struct cio2_node_names node_names;
> >> +
> >> +	u32 data_lanes[4];
> >> +	struct cio2_sensor_ssdb ssdb;
> >> +	struct cio2_property_names prop_names;
> >> +	struct property_entry ep_properties[4];
> >> +	struct property_entry dev_properties[3];
> >> +	struct property_entry cio2_properties[3];
> >> +	struct software_node_ref_args local_ref[1];
> >> +	struct software_node_ref_args remote_ref[1];
> >> +};
> >> +
> >> +struct cio2_bridge {
> >> +	struct pci_dev *cio2;
> >> +	char cio2_node_name[ACPI_ID_LEN];
> >> +	struct software_node cio2_hid_node;
> >> +	unsigned int n_sensors;
> >> +	struct cio2_sensor sensors[CIO2_NUM_PORTS];
> >> +};
> >> +
> >> +#endif
> >> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> >> index 36e354ecf71e..0d69b593e9f0 100644
> >> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> >> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
> >> @@ -1702,6 +1702,22 @@ static void cio2_queues_exit(struct cio2_device *cio2)
> >>  		cio2_queue_exit(cio2, &cio2->queue[i]);
> >>  }
> >>  
> >> +static bool cio2_check_fwnode_graph(struct fwnode_handle *fwnode)
> >> +{
> >> +	struct fwnode_handle *endpoint;
> >> +
> >> +	if (IS_ERR_OR_NULL(fwnode))
> >> +		return false;
> >> +
> >> +	endpoint = fwnode_graph_get_next_endpoint(fwnode, NULL);
> >> +	if (endpoint) {
> >> +		fwnode_handle_put(endpoint);
> >> +		return true;
> >> +	}
> >> +
> >> +	return cio2_check_fwnode_graph(fwnode->secondary);
> > 
> > If we have a fwnode->secondary and this check fails there's something
> > seriously wrong, I wonder if we should print an error message.
> 
> Yes, probably a good thought, since nothing will work in that case. I'll
> add something appropriate.
> 
> > Overall this is nice. I think the next version will get my ack :-)
> 
> Excellent :)
> 
> >> +}
> >> +
> >>  /**************** PCI interface ****************/
> >>  
> >>  static int cio2_pci_probe(struct pci_dev *pci_dev,
> >> @@ -1715,6 +1731,17 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
> >>  		return -ENOMEM;
> >>  	cio2->pci_dev = pci_dev;
> >>  
> >> +	/*
> >> +	 * On some platforms no connections to sensors are defined in firmware,
> >> +	 * if the device has no endpoints then we can try to build those as
> >> +	 * software_nodes parsed from SSDB.
> >> +	 */
> >> +	if (!cio2_check_fwnode_graph(dev_fwnode(&pci_dev->dev))) {
> >> +		r = cio2_bridge_init(pci_dev);
> >> +		if (r)
> >> +			return r;
> >> +	}
> >> +
> >>  	r = pcim_enable_device(pci_dev);
> >>  	if (r) {
> >>  		dev_err(&pci_dev->dev, "failed to enable device (%d)\n", r);
> >> diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.h b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
> >> index ccf0b85ae36f..520a27c9cdad 100644
> >> --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.h
> >> +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.h
> >> @@ -437,4 +437,10 @@ static inline struct cio2_queue *vb2q_to_cio2_queue(struct vb2_queue *vq)
> >>  	return container_of(vq, struct cio2_queue, vbq);
> >>  }
> >>  
> >> +#if IS_ENABLED(CONFIG_CIO2_BRIDGE)
> >> +int cio2_bridge_init(struct pci_dev *cio2);
> >> +#else
> >> +int cio2_bridge_init(struct pci_dev *cio2) { return 0; }
> >> +#endif
> >> +
> >>  #endif

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-12-01 22:30       ` Laurent Pinchart
@ 2020-12-01 23:15         ` Dan Scally
  2020-12-02 10:38         ` Sakari Ailus
  1 sibling, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-01 23:15 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Laurent
On 01/12/2020 22:30, Laurent Pinchart wrote:
>>>> +}
>>>> +
>>>> +static void cio2_bridge_create_fwnode_properties(struct cio2_sensor *sensor)
>>>> +{
>>>> +	unsigned int i;
>>>> +
>>>> +	cio2_bridge_init_property_names(sensor);
>>>> +
>>>> +	for (i = 0; i < 4; i++)
>>>> +		sensor->data_lanes[i] = i + 1;
>>> Is there no provision in the SSDB for data lane remapping ?
>> Sorry; don't follow what you mean by data lane remapping here.
> Some CSI-2 receivers can remap data lanes. The routing inside the SoC
> from the data lane input pins to the PHYs is configurable. This makes
> board design easier as you can route the data lanes to any of the
> inputs. That's why the data lanes DT property is a list of lane numbers
> instead of a number of lanes. I'm actually not sure if the CIO2 supports
> this.

I don't see anything in the SSDB that might refer to that, though of
course we're lacking documentation for it so it could be a part that we
don't understand yet.


>>>> +			dev_info(&bridge->cio2->dev,
>>>> +				 "Found supported sensor %s\n",
>>>> +				 acpi_dev_name(adev));
>>>> +
>>>> +			bridge->n_sensors++;
>>> We probably want a check here to avoid overflowing bridge->sensors. The
>>> other option is to make bridge->sensors a struct list_head and allocate
>>> sensors dynamically.
>> Err - agree on a check. There's only 4 ports in a CIO2 device, so that's
>> the maximum. Seems easier to just do a check, unless the wasted memory
>> is enough that it's worth allocating dynamically. I don't mind either
>> approach.
> In theory we could route multiple sensors to the same receiver, as long
> as only one of them drives the lanes at any given time. It's one way to
> support multiple sensors in cheap designs. I doubt we'll ever encounter
> that with the IPU3, so we could just limit the count to 4.
Ah, that's neat though. But I'll leave it at a check at the top of the
loop for now.
>>>> +
>>>> +	fwnode = software_node_fwnode(&bridge->cio2_hid_node);
>>>> +	if (!fwnode) {
>>>> +		dev_err(dev, "Error getting fwnode from cio2 software_node\n");
>>>> +		ret = -ENODEV;
>>>> +		goto err_unregister_sensors;
>>> Can this happen ?
>> It _shouldn't_ happen, as long as nothing else is touching the swnodes
>> I've registered or anything. I've never seen it happen. That didn't feel
>> like quite enough to say it can't ever happen - but I'm happy to skip
>> the check if you think thats ok.
> It seems a bit overkill to me, but I'm not a swnode specialist :-)
I'm going to keep it, if you have no strong feelings, partly through
caution but also because the other place swnodes are most heavily used
(drivers/platform/x86/intel_cht_int33fe_typec.c) _does_ perform the
check, so consistency too.
>>>> @@ -0,0 +1,108 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>>> +/* Author: Dan Scally <djrscally@gmail.com> */
>>>> +#ifndef __CIO2_BRIDGE_H
>>>> +#define __CIO2_BRIDGE_H
>>>> +
>>>> +#include <linux/property.h>
>>>> +
>>>> +#define CIO2_HID				"INT343E"
>>>> +#define CIO2_NUM_PORTS			  4
>>> There are a few rogue spaces before '4'.
>> Argh, thanks, this is the curse of using VS code on multiple machines...
> I recommend vim ;-)
You're not the only one - maybe I need to spend the time and it'll save
time in the future

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

* Re: [PATCH 05/18] software_node: Alter software_node_unregister_nodes() to unregister the array in reverse order
  2020-11-30 17:45   ` Andy Shevchenko
@ 2020-12-01 23:36     ` Dan Scally
  0 siblings, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-01 23:36 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

Hi Andy

On 30/11/2020 17:45, Andy Shevchenko wrote:
> On Mon, Nov 30, 2020 at 01:31:16PM +0000, Daniel Scally wrote:
>> Software nodes that are children of another software node should be
>> unregistered before their parent. To allow easy unregistering of an array
>> of software_nodes ordered parent to child, reverse the order in which
>> this function unregisters software_nodes.
> 
> Should be folded in the previous patch. Otherwise we will have a history point
> where register() behaves differently to unregister().

OK sure, I'll squash them - and thanks for your comments on the previous
patch, I condensed the conditionals as you suggest

> ...
> 
>> + * @nodes: Zero terminated array of software nodes to be unregistered. If
>> + * parent pointers are set up in any of the software nodes then the array
>> + * MUST be ordered such that parents come before their children.
> 
> Please, leave field description short. Rather add another note to the
> Description below.

Ack

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

* Re: [PATCH 16/18] i2c: i2c-core-base: Use the new i2c_acpi_dev_name() in i2c_set_dev_name()
  2020-11-30 17:12   ` Laurent Pinchart
  2020-11-30 19:18     ` Andy Shevchenko
@ 2020-12-01 23:50     ` Dan Scally
  1 sibling, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-01 23:50 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On 30/11/2020 17:12, Laurent Pinchart wrote:
> Hi Daniel,
> 
> Thank you for the patch.
> 
> On Mon, Nov 30, 2020 at 01:31:27PM +0000, Daniel Scally wrote:
>> From: Dan Scally <djrscally@gmail.com>
>>
>> To make sure the new i2c_acpi_dev_name() always reflects the name of i2c
>> devices sourced from ACPI, use it in i2c_set_dev_name().
>>
>> Signed-off-by: Dan Scally <djrscally@gmail.com>
> 
> I'd squash this with 15/18, which would make it clear there's a memory
> leak :-)

Ah - that was sloppy...switched from devm_ and forgot to go fix that.
I'll add the kfree into i2c_unregister_device() and squash to 15/18

>> ---
>> Changes since RFC v3:
>>
>> 	- Patch introduced
>>
>>  drivers/i2c/i2c-core-base.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
>> index 573b5da145d1..a6d4ceb01077 100644
>> --- a/drivers/i2c/i2c-core-base.c
>> +++ b/drivers/i2c/i2c-core-base.c
>> @@ -814,7 +814,7 @@ static void i2c_dev_set_name(struct i2c_adapter *adap,
>>  	}
>>  
>>  	if (adev) {
>> -		dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev));
>> +		dev_set_name(&client->dev, i2c_acpi_dev_name(adev));
>>  		return;
>>  	}
>>  
> 


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

* Re: [PATCH 16/18] i2c: i2c-core-base: Use the new i2c_acpi_dev_name() in i2c_set_dev_name()
  2020-11-30 19:18     ` Andy Shevchenko
@ 2020-12-02  9:35       ` Andy Shevchenko
  2020-12-02  9:49         ` Dan Scally
  0 siblings, 1 reply; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-02  9:35 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Daniel Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Dan, does this mail among other my replies reach you?
It seems you answered to Laurent's mails and leaving mine ignored. Just
wondering if our servers have an issue again...

On Mon, Nov 30, 2020 at 09:18:56PM +0200, Andy Shevchenko wrote:
> On Mon, Nov 30, 2020 at 07:12:41PM +0200, Laurent Pinchart wrote:
> > On Mon, Nov 30, 2020 at 01:31:27PM +0000, Daniel Scally wrote:
> > > From: Dan Scally <djrscally@gmail.com>
> > > 
> > > To make sure the new i2c_acpi_dev_name() always reflects the name of i2c
> > > devices sourced from ACPI, use it in i2c_set_dev_name().
> > > 
> > > Signed-off-by: Dan Scally <djrscally@gmail.com>
> > 
> > I'd squash this with 15/18, which would make it clear there's a memory
> > leak :-)
> 
> ...
> 
> > >  	if (adev) {
> > > -		dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev));
> > > +		dev_set_name(&client->dev, i2c_acpi_dev_name(adev));
> > >  		return;
> 
> But you split pattern used in i2c_dev_set_name().
> What you need is to provide something like this
> 
> #define I2C_DEV_NAME_FORMAT	"i2c-%s"
> 
> const char *i2c_acpi_get_dev_name(...)
> {
> 	return kasprintf(..., I2C_DEV_NAME_FORMAT, ...);
> }
> 
> (Possible in the future if anybody needs
>   const char *i2c_dev_get_name_by_bus_and_addr(int bus, unsigned short addr)
> )
> 
> And here
> 
> -		dev_set_name(&client->dev, "i2c-%s", info->dev_name);
> +		dev_set_name(&client->dev, I2C_DEV_NAME_FORMAT, info->dev_name);
> 
> -		dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev));
> +		dev_set_name(&client->dev, I2C_DEV_NAME_FORMAT, acpi_dev_name(adev));
> 
> -- 
> With Best Regards,
> Andy Shevchenko;
> 
> 

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 20:59         ` Dan Scally
@ 2020-12-02  9:39           ` Andy Shevchenko
  2020-12-02 12:35             ` Laurent Pinchart
  2020-12-03 12:25             ` Dan Scally
  0 siblings, 2 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-02  9:39 UTC (permalink / raw)
  To: Dan Scally
  Cc: Laurent Pinchart, linux-kernel, linux-acpi, linux-gpio,
	linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	sakari.ailus, bingbu.cao, tian.shu.qiu, mchehab, robert.moore,
	erik.kaneda, pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Tue, Dec 01, 2020 at 08:59:53PM +0000, Dan Scally wrote:
> On 01/12/2020 18:49, Andy Shevchenko wrote:

...

> > Seems we can do this, by locating intel_int3472.c under PDx86 hood and dropping
> > ACPI ID table from TPS68470 MFD driver. The PMIC can be instantiated via
> > i2c_acpi_new_device() (IIRC the API name).
> >
> > And actually it makes more sense since it's not and MFD and should not be there.
> >
> > (Dan, patch wise the one creates intel_int3472.c followed by another one that
> >  moves ACPI ID from PMIC and introduces its instantiation via I²C board info
> >  structure)
> 
> I'm mostly following this, but why would we need an i2c_board_info or
> i2c_acpi_new_device()? The INT3472 entries that refer to actual tps68470
> devices do have an I2cSerialBusV2 enumerated in _CRS so in their case
> there's an i2c device registered with the kernel already.

Because as we discussed already we can't have two drivers for the same ID
without a big disruption in the driver(s).

If you have a single point of enumeration, it will make things much easier
(refer to the same intel_cht_int33fe driver you mentioned earlier).

I just realize that the name of int3472 should follow the same pattern, i.e.
intel_skl_int3472.c

> I think we need those things when we get round to handling the
> VCM/EEPROM that's hidden within the sensor's ACPI entry, but I've not
> done any work on that yet at all.

Let's consider this later — one step at a time.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 21:05                 ` Dan Scally
@ 2020-12-02  9:42                   ` Andy Shevchenko
  0 siblings, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-02  9:42 UTC (permalink / raw)
  To: Dan Scally
  Cc: Laurent Pinchart, linux-kernel, linux-acpi, linux-gpio,
	linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	sakari.ailus, bingbu.cao, tian.shu.qiu, mchehab, robert.moore,
	erik.kaneda, pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus, Hans de Goede

On Tue, Dec 01, 2020 at 09:05:11PM +0000, Dan Scally wrote:
> On 01/12/2020 19:21, Andy Shevchenko wrote:
> > On Tue, Dec 01, 2020 at 09:06:38PM +0200, Laurent Pinchart wrote:

...

> > I would rather ask Hans' opinion since he has quite an expertise with DMI for
> > good and bad.
> >
> I have no real preference as to the current method or DMI, but thoughts
> that come to mind are:
> 
> 
> 1. given your info that low byte 0x0c means clock enable, we need to
> register a clock too. Do we need to extend this device specific section
> to map a clock name, or is it acceptable for them to be nameless (ISTR
> that the API will let you fetch a clock using devm_clock_get(dev, NULL);)
> 
> 2. Given only 0x0b pin is actually a regulator and it's controlling
> multiple devices, my plan when we got round to adding the VCM / EEPROM
> support was simply to extend those mapping tables so that those
> supplementary devices were also able to get that regulator...and the two
> would share it. I think, from reading the regulator code and
> documentation, that that's all fine - and it won't actually be disabled
> until both drivers disable it. Does that sound about right?

Sounds right. Next step is to see the code. :-)

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 16/18] i2c: i2c-core-base: Use the new i2c_acpi_dev_name() in i2c_set_dev_name()
  2020-12-02  9:35       ` Andy Shevchenko
@ 2020-12-02  9:49         ` Dan Scally
  0 siblings, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-02  9:49 UTC (permalink / raw)
  To: Andy Shevchenko, Laurent Pinchart
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

On 02/12/2020 09:35, Andy Shevchenko wrote:
> Dan, does this mail among other my replies reach you?
> It seems you answered to Laurent's mails and leaving mine ignored. Just
> wondering if our servers have an issue again...
Morning - I got it, sorry. I just read Laurent's first and then called
it a night
> On Mon, Nov 30, 2020 at 09:18:56PM +0200, Andy Shevchenko wrote:
>> On Mon, Nov 30, 2020 at 07:12:41PM +0200, Laurent Pinchart wrote:
>>> On Mon, Nov 30, 2020 at 01:31:27PM +0000, Daniel Scally wrote:
>>>> From: Dan Scally <djrscally@gmail.com>
>>>>
>>>> To make sure the new i2c_acpi_dev_name() always reflects the name of i2c
>>>> devices sourced from ACPI, use it in i2c_set_dev_name().
>>>>
>>>> Signed-off-by: Dan Scally <djrscally@gmail.com>
>>> I'd squash this with 15/18, which would make it clear there's a memory
>>> leak :-)
>> ...
>>
>>>>  	if (adev) {
>>>> -		dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev));
>>>> +		dev_set_name(&client->dev, i2c_acpi_dev_name(adev));
>>>>  		return;
>> But you split pattern used in i2c_dev_set_name().
>> What you need is to provide something like this
>>
>> #define I2C_DEV_NAME_FORMAT	"i2c-%s"
>>
>> const char *i2c_acpi_get_dev_name(...)
>> {
>> 	return kasprintf(..., I2C_DEV_NAME_FORMAT, ...);
>> }
>>
>> (Possible in the future if anybody needs
>>   const char *i2c_dev_get_name_by_bus_and_addr(int bus, unsigned short addr)
>> )
>>
>> And here
>>
>> -		dev_set_name(&client->dev, "i2c-%s", info->dev_name);
>> +		dev_set_name(&client->dev, I2C_DEV_NAME_FORMAT, info->dev_name);
>>
>> -		dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev));
>> +		dev_set_name(&client->dev, I2C_DEV_NAME_FORMAT, acpi_dev_name(adev));
>>
Yeah ok, I like this approach much better, I'll switch to that.

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

* Re: [PATCH 06/18] software_node: amend software_node_unregister_node_group() to perform unregistration of array in reverse order to be consistent with software_node_unregister_nodes()
  2020-11-30 17:47     ` Andy Shevchenko
@ 2020-12-02 10:04       ` Dan Scally
  0 siblings, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-02 10:04 UTC (permalink / raw)
  To: Andy Shevchenko, Laurent Pinchart
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

On 30/11/2020 17:47, Andy Shevchenko wrote:
> On Mon, Nov 30, 2020 at 06:17:16PM +0200, Laurent Pinchart wrote:
>> Hi Daniel,
>>
>> Thank you for the patch.
>>
>> The subject line is very long. We try to keep it within a 72 characters
>> limit in the kernel. That can be a challenge sometimes, and expections
>> can be accepted, but this one is reaaaally long.
>>
>> (The same comment holds for other patches in the series)
> 
> +1.

My bad; I'll go through the series and condense them down as much as
possible.

>> On Mon, Nov 30, 2020 at 01:31:17PM +0000, Daniel Scally wrote:
>>> To maintain consistency with software_node_unregister_nodes(), reverse
>>> the order in which the software_node_unregister_node_group() function
>>> unregisters nodes.
>>>
>>> Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>>
>> I"d squash this with the previous patch to avoid introducing an
>> inconsistency.
> 
> It's different to previous. It touches not complementary API, but different
> one. However, I would follow your comment about documenting the behaviour of
> these two APIs as well…

I'll update the documentation for this function too.



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

* Re: [PATCH 02/18] property: Add support for calling fwnode_graph_get_endpoint_by_id() for fwnode->secondary
  2020-11-30 17:29   ` Andy Shevchenko
  2020-11-30 17:28     ` Laurent Pinchart
@ 2020-12-02 10:13     ` Dan Scally
  1 sibling, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-02 10:13 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

On 30/11/2020 17:29, Andy Shevchenko wrote:
> On Mon, Nov 30, 2020 at 01:31:13PM +0000, Daniel Scally wrote:
>> This function is used to find fwnode endpoints against a device. In
>> some instances those endpoints are software nodes which are children of
>> fwnode->secondary. Add support to fwnode_graph_get_endpoint_by_id() to
>> find those endpoints by recursively calling itself passing the ptr to
>> fwnode->secondary in the event no endpoint is found for the primary.
> 
> One nit below, after addressing:
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> 
> ...
> 
>> +	if (!best_ep && fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
>> +		return fwnode_graph_get_endpoint_by_id(fwnode->secondary, port,
>> +						       endpoint, flags);
> 
>>  	return best_ep;
> 
> Can we, please, do
> 
> 	if (best_ep)
> 		return best_ep;
> 
> 	if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
> 		return fwnode_graph_get_endpoint_by_id(fwnode->secondary, port,
> 						       endpoint, flags);
> 
> 	return NULL;
> 
> ?
> 
> This 'if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary))' becomes kinda
> idiomatic to the cases when we need to proceed primary followed by the
> secondary in cases where it's not already done.

Thanks - I made this change too

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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-12-01 22:30       ` Laurent Pinchart
  2020-12-01 23:15         ` Dan Scally
@ 2020-12-02 10:38         ` Sakari Ailus
  2020-12-02 10:53           ` Dan Scally
  2020-12-02 12:01           ` Andy Shevchenko
  1 sibling, 2 replies; 144+ messages in thread
From: Sakari Ailus @ 2020-12-02 10:38 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Dan Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	andriy.shevchenko, linus.walleij, bgolaszewski, wsa, yong.zhi,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Laurent,

On Wed, Dec 02, 2020 at 12:30:53AM +0200, Laurent Pinchart wrote:
> Hi Daniel,
> 
> On Tue, Dec 01, 2020 at 10:08:25PM +0000, Dan Scally wrote:
> > On 30/11/2020 17:09, Laurent Pinchart wrote:
> > > On Mon, Nov 30, 2020 at 01:31:24PM +0000, Daniel Scally wrote:
> > >> Currently on platforms designed for Windows, connections between CIO2 and
> > >> sensors are not properly defined in DSDT. This patch extends the ipu3-cio2
> > >> driver to compensate by building software_node connections, parsing the
> > >> connection properties from the sensor's SSDB buffer.
> > >>
> > >> Suggested-by: Jordan Hand <jorhand@linux.microsoft.com>
> > >> Signed-off-by: Daniel Scally <djrscally@gmail.com>
> > >> ---
> > >> Changes since RFC v3:
> > >>
> > >> 	- Removed almost all global variables, dynamically allocated
> > >> 	the cio2_bridge structure, plus a bunch of associated changes
> > >> 	like 
> > >> 	- Added a new function to ipu3-cio2-main.c to check for an 
> > >> 	existing fwnode_graph before calling cio2_bridge_init()
> > >> 	- Prefixed cio2_bridge_ to any variables and functions that
> > >> 	lacked it
> > >> 	- Assigned the new fwnode directly to the sensor's ACPI device
> > >> 	fwnode as secondary. This removes the requirement to delay until
> > >> 	the I2C devices are instantiated before ipu3-cio2 can probe, but
> > >> 	it has a side effect, which is that those devices then grab a ref
> > >> 	to the new software_node. This effectively prevents us from
> > >> 	unloading the driver, because we can't free the memory that they
> > >> 	live in whilst the device holds a reference to them. The work
> > >> 	around at the moment is to _not_ unregister the software_nodes
> > >> 	when ipu3-cio2 is unloaded; this becomes a one-time 'patch', that
> > >> 	is simply skipped if the module is reloaded.
> > >> 	- Moved the sensor's SSDB struct to be a member of cio2_sensor
> > >> 	- Replaced ints with unsigned ints where appropriate
> > >> 	- Iterated over all ACPI devices of a matching _HID rather than
> > >> 	just the first to ensure we handle a device with multiple sensors
> > >> 	of the same model.
> > >>
> > >>  MAINTAINERS                                   |   1 +
> > >>  drivers/media/pci/intel/ipu3/Kconfig          |  18 ++
> > >>  drivers/media/pci/intel/ipu3/Makefile         |   1 +
> > >>  drivers/media/pci/intel/ipu3/cio2-bridge.c    | 260 ++++++++++++++++++
> > >>  drivers/media/pci/intel/ipu3/cio2-bridge.h    | 108 ++++++++
> > >>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  27 ++
> > >>  drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   6 +
> > >>  7 files changed, 421 insertions(+)
> > >>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
> > >>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h
> > >>
> > >> diff --git a/MAINTAINERS b/MAINTAINERS
> > >> index 9702b886d6a4..188559a0a610 100644
> > >> --- a/MAINTAINERS
> > >> +++ b/MAINTAINERS
> > >> @@ -8927,6 +8927,7 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
> > >>  M:	Yong Zhi <yong.zhi@intel.com>
> > >>  M:	Sakari Ailus <sakari.ailus@linux.intel.com>
> > >>  M:	Bingbu Cao <bingbu.cao@intel.com>
> > >> +M:	Dan Scally <djrscally@gmail.com>
> > >>  R:	Tianshu Qiu <tian.shu.qiu@intel.com>
> > >>  L:	linux-media@vger.kernel.org
> > >>  S:	Maintained
> > >> diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
> > >> index 82d7f17e6a02..2b3350d042be 100644
> > >> --- a/drivers/media/pci/intel/ipu3/Kconfig
> > >> +++ b/drivers/media/pci/intel/ipu3/Kconfig
> > >> @@ -16,3 +16,21 @@ config VIDEO_IPU3_CIO2
> > >>  	  Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2
> > >>  	  connected camera.
> > >>  	  The module will be called ipu3-cio2.
> > >> +
> > >> +config CIO2_BRIDGE
> > >> +	bool "IPU3 CIO2 Sensors Bridge"
> > >> +	depends on VIDEO_IPU3_CIO2
> > >> +	help
> > >> +	  This extension provides an API for the ipu3-cio2 driver to create
> > >> +	  connections to cameras that are hidden in SSDB buffer in ACPI. It
> > >> +	  can be used to enable support for cameras in detachable / hybrid
> > >> +	  devices that ship with Windows.
> > >> +
> > >> +	  Say Y here if your device is a detachable / hybrid laptop that comes
> > >> +	  with Windows installed by the OEM, for example:
> > >> +
> > >> +	  	- Microsoft Surface models (except Surface Pro 3)
> > >> +		- The Lenovo Miix line (for example the 510, 520, 710 and 720)
> > >> +		- Dell 7285
> > >> +
> > >> +	  If in doubt, say N here.
> > >> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
> > >> index 429d516452e4..933777e6ea8a 100644
> > >> --- a/drivers/media/pci/intel/ipu3/Makefile
> > >> +++ b/drivers/media/pci/intel/ipu3/Makefile
> > >> @@ -2,3 +2,4 @@
> > >>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
> > >>  
> > >>  ipu3-cio2-y += ipu3-cio2-main.o
> > >> +ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
> > >> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> > >> new file mode 100644
> > >> index 000000000000..fd3f8ba07274
> > >> --- /dev/null
> > >> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> > >> @@ -0,0 +1,260 @@
> > >> +// SPDX-License-Identifier: GPL-2.0
> > >> +/* Author: Dan Scally <djrscally@gmail.com> */
> > > 
> > > Could you please add a blank line here ?
> > 
> > Yes
> >
> > >> +#include <linux/acpi.h>
> > >> +#include <linux/device.h>
> > >> +#include <linux/i2c.h>
> > > 
> > > Is this header needed ?
> > > 
> > >> +#include <linux/kernel.h>
> > >> +#include <linux/module.h>
> > > 
> > > And this one ?
> > > 
> > >> +#include <linux/pci.h>
> > >> +#include <linux/property.h>
> > >> +#include <media/v4l2-subdev.h>
> > > 
> > > And this one ?
> > 
> > Ah yes - bit sloppy, they're orphaned from earlier versions, sorry about
> > that.
> > 
> > >> +
> > >> +#include "cio2-bridge.h"
> > >> +
> > >> +/*
> > >> + * Extend this array with ACPI Hardware ID's of devices known to be working.
> > >> + * Do not add a HID for a sensor that is not actually supported.
> > >> + */
> > >> +static const char * const cio2_supported_devices[] = {
> > > 
> > > Maybe cio2_supported_sensors ?
> > 
> > Sure
> > 
> > >> +	"INT33BE",
> > >> +	"OVTI2680",
> > >> +};
> > >> +
> > >> +static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id,
> > >> +					void *data, u32 size)
> > >> +{
> > >> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> > >> +	union acpi_object *obj;
> > >> +	acpi_status status;
> > >> +	int ret;
> > >> +
> > >> +	status = acpi_evaluate_object(adev->handle, id, NULL, &buffer);
> > >> +	if (ACPI_FAILURE(status))
> > >> +		return -ENODEV;
> > >> +
> > >> +	obj = buffer.pointer;
> > >> +	if (!obj) {
> > >> +		dev_err(&adev->dev, "Couldn't locate ACPI buffer\n");
> > >> +		return -ENODEV;
> > >> +	}
> > >> +
> > >> +	if (obj->type != ACPI_TYPE_BUFFER) {
> > >> +		dev_err(&adev->dev, "Not an ACPI buffer\n");
> > >> +		ret = -ENODEV;
> > >> +		goto out_free_buff;
> > >> +	}
> > >> +
> > >> +	if (obj->buffer.length > size) {
> > >> +		dev_err(&adev->dev, "Given buffer is too small\n");
> > >> +		ret = -EINVAL;
> > >> +		goto out_free_buff;
> > >> +	}
> > >> +
> > >> +	memcpy(data, obj->buffer.pointer, obj->buffer.length);
> > >> +	ret = obj->buffer.length;
> > >> +
> > >> +out_free_buff:
> > >> +	kfree(buffer.pointer);
> > >> +	return ret;
> > >> +}
> > >> +
> > >> +static void cio2_bridge_init_property_names(struct cio2_sensor *sensor)
> > >> +{
> > >> +	strcpy(sensor->prop_names.clock_frequency, "clock-frequency");
> > >> +	strcpy(sensor->prop_names.rotation, "rotation");
> > >> +	strcpy(sensor->prop_names.bus_type, "bus-type");
> > >> +	strcpy(sensor->prop_names.data_lanes, "data-lanes");
> > >> +	strcpy(sensor->prop_names.remote_endpoint, "remote-endpoint");
> > > 
> > > This is a bit fragile, as there's no len check. How about the following
> > > ?
> > > static const struct cio2_property_names prop_names = {
> > > 	.clock_frequency = "clock-frequency",
> > > 	.rotation = "rotation",
> > > 	.bus_type = "bus-type",
> > > 	.data_lanes = "data-lanes",
> > > 	.remote_endpoint = "remote-endpoint",
> > > };
> > > 
> > > static void cio2_bridge_init_property_names(struct cio2_sensor *sensor)
> > > {
> > > 	sensor->prop_names = prop_names;
> > > }
> > > 
> > > This shoudl generate a compilation warning if the string is too long.
> > > 
> > > You could even inline that line in
> > > cio2_bridge_create_fwnode_properties().
> > 
> > Yes, I like that, thanks - I'll make the change.
> > 
> > >> +}
> > >> +
> > >> +static void cio2_bridge_create_fwnode_properties(struct cio2_sensor *sensor)
> > >> +{
> > >> +	unsigned int i;
> > >> +
> > >> +	cio2_bridge_init_property_names(sensor);
> > >> +
> > >> +	for (i = 0; i < 4; i++)
> > >> +		sensor->data_lanes[i] = i + 1;
> > > 
> > > Is there no provision in the SSDB for data lane remapping ?
> > 
> > Sorry; don't follow what you mean by data lane remapping here.
> 
> Some CSI-2 receivers can remap data lanes. The routing inside the SoC
> from the data lane input pins to the PHYs is configurable. This makes
> board design easier as you can route the data lanes to any of the
> inputs. That's why the data lanes DT property is a list of lane numbers
> instead of a number of lanes. I'm actually not sure if the CIO2 supports
> this.

To my knowledge it does not. Only the number of lanes allocated to
different ports matters.

...

> > >> @@ -0,0 +1,108 @@
> > >> +/* SPDX-License-Identifier: GPL-2.0 */
> > >> +/* Author: Dan Scally <djrscally@gmail.com> */
> > >> +#ifndef __CIO2_BRIDGE_H
> > >> +#define __CIO2_BRIDGE_H
> > >> +
> > >> +#include <linux/property.h>
> > >> +
> > >> +#define CIO2_HID				"INT343E"
> > >> +#define CIO2_NUM_PORTS			  4
> > > 
> > > There are a few rogue spaces before '4'.
> > 
> > Argh, thanks, this is the curse of using VS code on multiple machines...
> 
> I recommend vim ;-)

What is VS code? Very Serious Code?

I can recommend Emacs; that could help, too.

-- 
Kind regards,

Sakari Ailus

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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-12-02 10:38         ` Sakari Ailus
@ 2020-12-02 10:53           ` Dan Scally
  2020-12-02 12:02             ` Andy Shevchenko
  2020-12-02 12:01           ` Andy Shevchenko
  1 sibling, 1 reply; 144+ messages in thread
From: Dan Scally @ 2020-12-02 10:53 UTC (permalink / raw)
  To: Sakari Ailus, Laurent Pinchart
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus


On 02/12/2020 10:38, Sakari Ailus wrote:
> Hi Laurent,
>
> On Wed, Dec 02, 2020 at 12:30:53AM +0200, Laurent Pinchart wrote:
>> Hi Daniel,
>>
>> On Tue, Dec 01, 2020 at 10:08:25PM +0000, Dan Scally wrote:
>>> On 30/11/2020 17:09, Laurent Pinchart wrote:
>>>> On Mon, Nov 30, 2020 at 01:31:24PM +0000, Daniel Scally wrote:
>>>>> Currently on platforms designed for Windows, connections between CIO2 and
>>>>> sensors are not properly defined in DSDT. This patch extends the ipu3-cio2
>>>>> driver to compensate by building software_node connections, parsing the
>>>>> connection properties from the sensor's SSDB buffer.
>>>>>
>>>>> Suggested-by: Jordan Hand <jorhand@linux.microsoft.com>
>>>>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>>>>> ---
>>>>> Changes since RFC v3:
>>>>>
>>>>> 	- Removed almost all global variables, dynamically allocated
>>>>> 	the cio2_bridge structure, plus a bunch of associated changes
>>>>> 	like 
>>>>> 	- Added a new function to ipu3-cio2-main.c to check for an 
>>>>> 	existing fwnode_graph before calling cio2_bridge_init()
>>>>> 	- Prefixed cio2_bridge_ to any variables and functions that
>>>>> 	lacked it
>>>>> 	- Assigned the new fwnode directly to the sensor's ACPI device
>>>>> 	fwnode as secondary. This removes the requirement to delay until
>>>>> 	the I2C devices are instantiated before ipu3-cio2 can probe, but
>>>>> 	it has a side effect, which is that those devices then grab a ref
>>>>> 	to the new software_node. This effectively prevents us from
>>>>> 	unloading the driver, because we can't free the memory that they
>>>>> 	live in whilst the device holds a reference to them. The work
>>>>> 	around at the moment is to _not_ unregister the software_nodes
>>>>> 	when ipu3-cio2 is unloaded; this becomes a one-time 'patch', that
>>>>> 	is simply skipped if the module is reloaded.
>>>>> 	- Moved the sensor's SSDB struct to be a member of cio2_sensor
>>>>> 	- Replaced ints with unsigned ints where appropriate
>>>>> 	- Iterated over all ACPI devices of a matching _HID rather than
>>>>> 	just the first to ensure we handle a device with multiple sensors
>>>>> 	of the same model.
>>>>>
>>>>>  MAINTAINERS                                   |   1 +
>>>>>  drivers/media/pci/intel/ipu3/Kconfig          |  18 ++
>>>>>  drivers/media/pci/intel/ipu3/Makefile         |   1 +
>>>>>  drivers/media/pci/intel/ipu3/cio2-bridge.c    | 260 ++++++++++++++++++
>>>>>  drivers/media/pci/intel/ipu3/cio2-bridge.h    | 108 ++++++++
>>>>>  drivers/media/pci/intel/ipu3/ipu3-cio2-main.c |  27 ++
>>>>>  drivers/media/pci/intel/ipu3/ipu3-cio2.h      |   6 +
>>>>>  7 files changed, 421 insertions(+)
>>>>>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.c
>>>>>  create mode 100644 drivers/media/pci/intel/ipu3/cio2-bridge.h
>>>>>
>>>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>>>> index 9702b886d6a4..188559a0a610 100644
>>>>> --- a/MAINTAINERS
>>>>> +++ b/MAINTAINERS
>>>>> @@ -8927,6 +8927,7 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
>>>>>  M:	Yong Zhi <yong.zhi@intel.com>
>>>>>  M:	Sakari Ailus <sakari.ailus@linux.intel.com>
>>>>>  M:	Bingbu Cao <bingbu.cao@intel.com>
>>>>> +M:	Dan Scally <djrscally@gmail.com>
>>>>>  R:	Tianshu Qiu <tian.shu.qiu@intel.com>
>>>>>  L:	linux-media@vger.kernel.org
>>>>>  S:	Maintained
>>>>> diff --git a/drivers/media/pci/intel/ipu3/Kconfig b/drivers/media/pci/intel/ipu3/Kconfig
>>>>> index 82d7f17e6a02..2b3350d042be 100644
>>>>> --- a/drivers/media/pci/intel/ipu3/Kconfig
>>>>> +++ b/drivers/media/pci/intel/ipu3/Kconfig
>>>>> @@ -16,3 +16,21 @@ config VIDEO_IPU3_CIO2
>>>>>  	  Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2
>>>>>  	  connected camera.
>>>>>  	  The module will be called ipu3-cio2.
>>>>> +
>>>>> +config CIO2_BRIDGE
>>>>> +	bool "IPU3 CIO2 Sensors Bridge"
>>>>> +	depends on VIDEO_IPU3_CIO2
>>>>> +	help
>>>>> +	  This extension provides an API for the ipu3-cio2 driver to create
>>>>> +	  connections to cameras that are hidden in SSDB buffer in ACPI. It
>>>>> +	  can be used to enable support for cameras in detachable / hybrid
>>>>> +	  devices that ship with Windows.
>>>>> +
>>>>> +	  Say Y here if your device is a detachable / hybrid laptop that comes
>>>>> +	  with Windows installed by the OEM, for example:
>>>>> +
>>>>> +	  	- Microsoft Surface models (except Surface Pro 3)
>>>>> +		- The Lenovo Miix line (for example the 510, 520, 710 and 720)
>>>>> +		- Dell 7285
>>>>> +
>>>>> +	  If in doubt, say N here.
>>>>> diff --git a/drivers/media/pci/intel/ipu3/Makefile b/drivers/media/pci/intel/ipu3/Makefile
>>>>> index 429d516452e4..933777e6ea8a 100644
>>>>> --- a/drivers/media/pci/intel/ipu3/Makefile
>>>>> +++ b/drivers/media/pci/intel/ipu3/Makefile
>>>>> @@ -2,3 +2,4 @@
>>>>>  obj-$(CONFIG_VIDEO_IPU3_CIO2) += ipu3-cio2.o
>>>>>  
>>>>>  ipu3-cio2-y += ipu3-cio2-main.o
>>>>> +ipu3-cio2-$(CONFIG_CIO2_BRIDGE) += cio2-bridge.o
>>>>> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
>>>>> new file mode 100644
>>>>> index 000000000000..fd3f8ba07274
>>>>> --- /dev/null
>>>>> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
>>>>> @@ -0,0 +1,260 @@
>>>>> +// SPDX-License-Identifier: GPL-2.0
>>>>> +/* Author: Dan Scally <djrscally@gmail.com> */
>>>> Could you please add a blank line here ?
>>> Yes
>>>
>>>>> +#include <linux/acpi.h>
>>>>> +#include <linux/device.h>
>>>>> +#include <linux/i2c.h>
>>>> Is this header needed ?
>>>>
>>>>> +#include <linux/kernel.h>
>>>>> +#include <linux/module.h>
>>>> And this one ?
>>>>
>>>>> +#include <linux/pci.h>
>>>>> +#include <linux/property.h>
>>>>> +#include <media/v4l2-subdev.h>
>>>> And this one ?
>>> Ah yes - bit sloppy, they're orphaned from earlier versions, sorry about
>>> that.
>>>
>>>>> +
>>>>> +#include "cio2-bridge.h"
>>>>> +
>>>>> +/*
>>>>> + * Extend this array with ACPI Hardware ID's of devices known to be working.
>>>>> + * Do not add a HID for a sensor that is not actually supported.
>>>>> + */
>>>>> +static const char * const cio2_supported_devices[] = {
>>>> Maybe cio2_supported_sensors ?
>>> Sure
>>>
>>>>> +	"INT33BE",
>>>>> +	"OVTI2680",
>>>>> +};
>>>>> +
>>>>> +static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id,
>>>>> +					void *data, u32 size)
>>>>> +{
>>>>> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
>>>>> +	union acpi_object *obj;
>>>>> +	acpi_status status;
>>>>> +	int ret;
>>>>> +
>>>>> +	status = acpi_evaluate_object(adev->handle, id, NULL, &buffer);
>>>>> +	if (ACPI_FAILURE(status))
>>>>> +		return -ENODEV;
>>>>> +
>>>>> +	obj = buffer.pointer;
>>>>> +	if (!obj) {
>>>>> +		dev_err(&adev->dev, "Couldn't locate ACPI buffer\n");
>>>>> +		return -ENODEV;
>>>>> +	}
>>>>> +
>>>>> +	if (obj->type != ACPI_TYPE_BUFFER) {
>>>>> +		dev_err(&adev->dev, "Not an ACPI buffer\n");
>>>>> +		ret = -ENODEV;
>>>>> +		goto out_free_buff;
>>>>> +	}
>>>>> +
>>>>> +	if (obj->buffer.length > size) {
>>>>> +		dev_err(&adev->dev, "Given buffer is too small\n");
>>>>> +		ret = -EINVAL;
>>>>> +		goto out_free_buff;
>>>>> +	}
>>>>> +
>>>>> +	memcpy(data, obj->buffer.pointer, obj->buffer.length);
>>>>> +	ret = obj->buffer.length;
>>>>> +
>>>>> +out_free_buff:
>>>>> +	kfree(buffer.pointer);
>>>>> +	return ret;
>>>>> +}
>>>>> +
>>>>> +static void cio2_bridge_init_property_names(struct cio2_sensor *sensor)
>>>>> +{
>>>>> +	strcpy(sensor->prop_names.clock_frequency, "clock-frequency");
>>>>> +	strcpy(sensor->prop_names.rotation, "rotation");
>>>>> +	strcpy(sensor->prop_names.bus_type, "bus-type");
>>>>> +	strcpy(sensor->prop_names.data_lanes, "data-lanes");
>>>>> +	strcpy(sensor->prop_names.remote_endpoint, "remote-endpoint");
>>>> This is a bit fragile, as there's no len check. How about the following
>>>> ?
>>>> static const struct cio2_property_names prop_names = {
>>>> 	.clock_frequency = "clock-frequency",
>>>> 	.rotation = "rotation",
>>>> 	.bus_type = "bus-type",
>>>> 	.data_lanes = "data-lanes",
>>>> 	.remote_endpoint = "remote-endpoint",
>>>> };
>>>>
>>>> static void cio2_bridge_init_property_names(struct cio2_sensor *sensor)
>>>> {
>>>> 	sensor->prop_names = prop_names;
>>>> }
>>>>
>>>> This shoudl generate a compilation warning if the string is too long.
>>>>
>>>> You could even inline that line in
>>>> cio2_bridge_create_fwnode_properties().
>>> Yes, I like that, thanks - I'll make the change.
>>>
>>>>> +}
>>>>> +
>>>>> +static void cio2_bridge_create_fwnode_properties(struct cio2_sensor *sensor)
>>>>> +{
>>>>> +	unsigned int i;
>>>>> +
>>>>> +	cio2_bridge_init_property_names(sensor);
>>>>> +
>>>>> +	for (i = 0; i < 4; i++)
>>>>> +		sensor->data_lanes[i] = i + 1;
>>>> Is there no provision in the SSDB for data lane remapping ?
>>> Sorry; don't follow what you mean by data lane remapping here.
>> Some CSI-2 receivers can remap data lanes. The routing inside the SoC
>> from the data lane input pins to the PHYs is configurable. This makes
>> board design easier as you can route the data lanes to any of the
>> inputs. That's why the data lanes DT property is a list of lane numbers
>> instead of a number of lanes. I'm actually not sure if the CIO2 supports
>> this.
> To my knowledge it does not. Only the number of lanes allocated to
> different ports matters.
>
So nothing to change here then I think?
>>>>> @@ -0,0 +1,108 @@
>>>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>>>> +/* Author: Dan Scally <djrscally@gmail.com> */
>>>>> +#ifndef __CIO2_BRIDGE_H
>>>>> +#define __CIO2_BRIDGE_H
>>>>> +
>>>>> +#include <linux/property.h>
>>>>> +
>>>>> +#define CIO2_HID				"INT343E"
>>>>> +#define CIO2_NUM_PORTS			  4
>>>> There are a few rogue spaces before '4'.
>>> Argh, thanks, this is the curse of using VS code on multiple machines...
>> I recommend vim ;-)
> What is VS code? Very Serious Code?

Visual Studio Code - it has some nice features, but the
facepalm-to-productivity ratio is a bit high.

> I can recommend Emacs; that could help, too.

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 18:37         ` Laurent Pinchart
@ 2020-12-02 11:09           ` Sakari Ailus
  2020-12-02 12:42             ` Laurent Pinchart
  0 siblings, 1 reply; 144+ messages in thread
From: Sakari Ailus @ 2020-12-02 11:09 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Andy Shevchenko, Daniel Scally, linux-kernel, linux-acpi,
	linux-gpio, linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Laurent,

On Tue, Dec 01, 2020 at 08:37:58PM +0200, Laurent Pinchart wrote:
> Hi Sakari,
> 
> On Tue, Dec 01, 2020 at 05:55:13PM +0200, Sakari Ailus wrote:
> > On Tue, Dec 01, 2020 at 01:32:32AM +0200, Laurent Pinchart wrote:
> > > On Mon, Nov 30, 2020 at 10:07:19PM +0200, Andy Shevchenko wrote:
> > > > On Mon, Nov 30, 2020 at 01:31:29PM +0000, Daniel Scally wrote:
> > > > > On platforms where ACPI is designed for use with Windows, resources
> > > > > that are intended to be consumed by sensor devices are sometimes in
> > > > > the _CRS of a dummy INT3472 device upon which the sensor depends. This
> > > > > driver binds to the dummy acpi device (which does not represent a
> > > > 
> > > > acpi device -> acpi_device
> > > > 
> > > > > physical PMIC) and maps them into GPIO lines and regulators for use by
> > > > > the sensor device instead.
> > > > 
> > > > ...
> > > > 
> > > > > This patch contains the bits of this process that we're least sure about.
> > > > > The sensors in scope for this work are called out as dependent (in their
> > > > > DSDT entry's _DEP) on a device with _HID INT3472. These come in at least
> > > > > 2 kinds; those with an I2cSerialBusV2 entry (which we presume therefore
> > > > > are legitimate tps68470 PMICs that need handling by those drivers - work
> > > > > on that in the future). And those without an I2C device. For those without
> > > > > an I2C device they instead have an array of GPIO pins defined in _CRS. So
> > > > > for example, my Lenovo Miix 510's OVTI2680 sensor is dependent on one of
> > > > > the _latter_ kind of INT3472 devices, with this _CRS:
> > > > > 
> > > > > Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
> > > > > {
> > > > >     Name (SBUF, ResourceTemplate ()
> > > > >     {
> > > > >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > > > > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > > > > 	    0x00, ResourceConsumer, ,
> > > > >             )
> > > > >             {   // Pin list
> > > > >                 0x0079
> > > > >             }
> > > > >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > > > > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > > > > 	    0x00, ResourceConsumer, ,
> > > > >             )
> > > > >             {   // Pin list
> > > > >                 0x007A
> > > > >             }
> > > > >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > > > > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > > > > 	    0x00, ResourceConsumer, ,
> > > > >             )
> > > > >             {   // Pin list
> > > > >                 0x008F
> > > > >             }
> > > > >     })
> > > > >     Return (SBUF) /* \_SB_.PCI0.PMI1._CRS.SBUF */
> > > > > }
> > > > > 
> > > > > and the same device has a _DSM Method, which returns 32-bit ints where
> > > > > the second lowest byte we noticed to match the pin numbers of the GPIO
> > > > > lines:
> > > > > 
> > > > > Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
> > > > > {
> > > > >     If ((Arg0 == ToUUID ("79234640-9e10-4fea-a5c1-b5aa8b19756f")))
> > > > >     {
> > > > >         If ((Arg2 == One))
> > > > >         {
> > > > >             Return (0x03)
> > > > >         }
> > > > > 
> > > > >         If ((Arg2 == 0x02))
> > > > >         {
> > > > >             Return (0x01007900)
> > > > >         }
> > > > > 
> > > > >         If ((Arg2 == 0x03))
> > > > >         {
> > > > >             Return (0x01007A0C)
> > > > >         }
> > > > > 
> > > > >         If ((Arg2 == 0x04))
> > > > >         {
> > > > >             Return (0x01008F01)
> > > > >         }
> > > > >     }
> > > > > 
> > > > >     Return (Zero)
> > > > > }
> > > > > 
> > > > > We know that at least some of those pins have to be toggled active for the
> > > > > sensor devices to be available in i2c, so the conclusion we came to was
> > > > > that those GPIO entries assigned to the INT3472 device actually represent
> > > > > GPIOs and regulators to be consumed by the sensors themselves. Tsuchiya
> > > > > noticed that the lowest byte in the return values of the _DSM method
> > > > > seemed to represent the type or function of the GPIO line, and we
> > > > > confirmed that by testing on each surface device that GPIO lines where the
> > > > > low byte in the _DSM entry for that pin was 0x0d controlled the privacy
> > > > > LED of the cameras.
> > > > > 
> > > > > We're guessing as to the exact meaning of the function byte, but I
> > > > > conclude they're something like this:
> > > > > 
> > > > > 0x00 - probably a reset GPIO
> > > > > 0x01 - regulator for the sensor
> > > > > 0x0c - regulator for the sensor
> > > > > 0x0b - regulator again, but for a VCM or EEPROM
> > > > > 0x0d - privacy led (only one we're totally confident of since we can see
> > > > >        it happen!)
> > > > 
> > > > It's solely Windows driver design...
> > > > Luckily I found some information and can clarify above table:
> > > > 
> > > > 0x00 Reset
> > > > 0x01 Power down
> > > > 0x0b Power enable
> > > > 0x0c Clock enable
> > > > 0x0d LED (active high)
> > > 
> > > That's very useful information ! Thank you.
> > > 
> > > > The above text perhaps should go somewhere under Documentation.
> > > 
> > > Or in the driver source code, but definitely somewhere else than in the
> > > commit message.
> > > 
> > > > > After much internal debate I decided to write this as a standalone
> > > > > acpi_driver. Alternative options we considered:
> > > > > 
> > > > > 1. Squash all this into the cio2-bridge code, which I did originally write
> > > > > but decided I didn't like.
> > > > > 2. Extend the existing tps68470 mfd driver...they share an ACPI ID so this
> > > > > kinda makes sense, but ultimately given there is no actual physical
> > > > > tps68470 in the scenario this patch handles I decided I didn't like this
> > > > > either.
> > > > 
> > > > Looking to this I think the best is to create a module that can be consumed by tps68470 and separately.
> > > > So, something near to it rather than under ipu3 hood.
> > > > 
> > > > You may use same ID's in both drivers (in PMIC less case it can be simple
> > > > platform and thus they won't conflict), but both of them should provide GPIO
> > > > resources for consumption.
> > > > 
> > > > So, something like
> > > > 
> > > >  tps68470.h with API to consume
> > > >  split tps68470 to -core, -i2c parts
> > > >  add int3472, which will serve for above and be standalone platform driver
> > > >  update cio2-bridge accordingly
> > > > 
> > > > Would it be feasible?
> > > 
> > > Given that INT3472 means Intel camera power management device (that's
> > > more or less the wording in Windows, I can double-check), would the
> > > following make sense ?
> > > 
> > > A top-level module named intel-camera-pmic (or int3472, or ...) would
> > > register two drivers, a platform driver and an I2C driver, to
> > > accommodate for both cases ("discrete PMIC" that doesn't have an
> > > I2cSerialBusV2, and TPS64870 or uP6641Q that are I2C devices). The probe
> > > function would perform the following:
> > > 
> > > - If there's no CLDB, then the device uses the Chrome OS "ACPI
> > >   bindings", and refers to a TPS64870. The code that exists in the
> > >   kernel today (registering GPIOs, and registering an OpRegion to
> > >   communicate with the power management code in the DSDT) would be
> > >   activated.
> > > 
> > > - If there's a CLDB, then the device type would be retrieved from it:
> > > 
> > >   - If the device is a "discrete PMIC", the driver would register clocks
> > >     and regulators controlled by GPIOs, and create clock, regulator and
> > >     GPIO lookup entries for the sensor device that references the PMIC.
> > > 
> > >   - If the device is a TPS64870, the code that exists in the kernel
> > >     today to register GPIOs would be activated, and new code would need
> > >     to be written to register regulators and clocks.
> > > 
> > >   - If the device is a uP6641Q, a new driver will need to be written (I
> > >     don't know on which devices this PMIC is used, so this can probably
> > >     be deferred).
> > > 
> > > We can split this in multiple files and/or modules.
> > 
> > That's what I thought of, too, as one option, but with some more detail.
> > This would be indeed the cleanest option.
> > 
> > I think it'd be nice if the CLDB stuff (apart from checking whether it's
> > there) would be in a different module to avoid cluttering up the real
> > tps68470 driver.
> 
> Given the amount of code, and the fact that the driver should be
> compiled as a module, I don't think it will make a huge difference in
> the memory footprint.

I'd still prefer to keep the ACPI hack support and the real driver well
separated. That way it'd be also easy to put them to their respective
modules. That's actually how the tps68470 MFD driver is currently arranged;
the GPIO and OP region drivers are separate from each other.

Could this be just one more platform device for each of the three cases (or
one for the two latter; I'm not quite sure yet)?

The GPIO regulator case is relatively safe, but the real PMICs require
regulator voltage control as well as enabling and disabling the regulators.
That probably requires either schematics or checking the register values at
runtime on Windows (i.e. finding out which system you're dealing with, at
runtime).

-- 
Kind regards,

Sakari Ailus

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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-12-02 10:38         ` Sakari Ailus
  2020-12-02 10:53           ` Dan Scally
@ 2020-12-02 12:01           ` Andy Shevchenko
  1 sibling, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-02 12:01 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Laurent Pinchart, Dan Scally, linux-kernel, linux-acpi,
	linux-gpio, linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Wed, Dec 02, 2020 at 12:38:51PM +0200, Sakari Ailus wrote:
> On Wed, Dec 02, 2020 at 12:30:53AM +0200, Laurent Pinchart wrote:
> > On Tue, Dec 01, 2020 at 10:08:25PM +0000, Dan Scally wrote:
> > > On 30/11/2020 17:09, Laurent Pinchart wrote:
> > > > On Mon, Nov 30, 2020 at 01:31:24PM +0000, Daniel Scally wrote:

...

> > > >> +#define CIO2_NUM_PORTS			  4
> > > > 
> > > > There are a few rogue spaces before '4'.
> > > 
> > > Argh, thanks, this is the curse of using VS code on multiple machines...
> > 
> > I recommend vim ;-)
> 
> What is VS code? Very Serious Code?

Visual Studio Code. Something good from MS (no sarcasm, btw).

> I can recommend Emacs; that could help, too.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-12-02 10:53           ` Dan Scally
@ 2020-12-02 12:02             ` Andy Shevchenko
  2020-12-02 22:44               ` Dan Scally
  0 siblings, 1 reply; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-02 12:02 UTC (permalink / raw)
  To: Dan Scally
  Cc: Sakari Ailus, Laurent Pinchart, linux-kernel, linux-acpi,
	linux-gpio, linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Wed, Dec 02, 2020 at 10:53:05AM +0000, Dan Scally wrote:
> On 02/12/2020 10:38, Sakari Ailus wrote:

...

> >>> Argh, thanks, this is the curse of using VS code on multiple machines...
> >> I recommend vim ;-)
> > What is VS code? Very Serious Code?
> 
> Visual Studio Code - it has some nice features, but the
> facepalm-to-productivity ratio is a bit high.

Perhaps you can submit an issue report on GitHub. I found VS Code pretty nice
to be with Linux kernel development.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-02  9:39           ` Andy Shevchenko
@ 2020-12-02 12:35             ` Laurent Pinchart
  2020-12-02 15:11               ` Andy Shevchenko
  2020-12-03 12:25             ` Dan Scally
  1 sibling, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-12-02 12:35 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Dan Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Wed, Dec 02, 2020 at 11:39:52AM +0200, Andy Shevchenko wrote:
> On Tue, Dec 01, 2020 at 08:59:53PM +0000, Dan Scally wrote:
> > On 01/12/2020 18:49, Andy Shevchenko wrote:
> 
> ...
> 
> > > Seems we can do this, by locating intel_int3472.c under PDx86 hood and dropping
> > > ACPI ID table from TPS68470 MFD driver. The PMIC can be instantiated via
> > > i2c_acpi_new_device() (IIRC the API name).
> > >
> > > And actually it makes more sense since it's not and MFD and should not be there.
> > >
> > > (Dan, patch wise the one creates intel_int3472.c followed by another one that
> > >  moves ACPI ID from PMIC and introduces its instantiation via I²C board info
> > >  structure)
> > 
> > I'm mostly following this, but why would we need an i2c_board_info or
> > i2c_acpi_new_device()? The INT3472 entries that refer to actual tps68470
> > devices do have an I2cSerialBusV2 enumerated in _CRS so in their case
> > there's an i2c device registered with the kernel already.
> 
> Because as we discussed already we can't have two drivers for the same ID
> without a big disruption in the driver(s).
> 
> If you have a single point of enumeration, it will make things much easier
> (refer to the same intel_cht_int33fe driver you mentioned earlier).
> 
> I just realize that the name of int3472 should follow the same pattern, i.e.
> intel_skl_int3472.c

We're mostly focussing on Kaby Lake here though. From what I understand
the ACPI infrastructure for camera support is mostly the same on Sky
Lake, but not identical. I think a single driver should be able to cover
both though.

> > I think we need those things when we get round to handling the
> > VCM/EEPROM that's hidden within the sensor's ACPI entry, but I've not
> > done any work on that yet at all.
> 
> Let's consider this later — one step at a time.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-02 11:09           ` Sakari Ailus
@ 2020-12-02 12:42             ` Laurent Pinchart
  2020-12-02 15:08               ` Andy Shevchenko
  0 siblings, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-12-02 12:42 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Andy Shevchenko, Daniel Scally, linux-kernel, linux-acpi,
	linux-gpio, linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Wed, Dec 02, 2020 at 01:09:56PM +0200, Sakari Ailus wrote:
> Hi Laurent,
> 
> On Tue, Dec 01, 2020 at 08:37:58PM +0200, Laurent Pinchart wrote:
> > Hi Sakari,
> > 
> > On Tue, Dec 01, 2020 at 05:55:13PM +0200, Sakari Ailus wrote:
> > > On Tue, Dec 01, 2020 at 01:32:32AM +0200, Laurent Pinchart wrote:
> > > > On Mon, Nov 30, 2020 at 10:07:19PM +0200, Andy Shevchenko wrote:
> > > > > On Mon, Nov 30, 2020 at 01:31:29PM +0000, Daniel Scally wrote:
> > > > > > On platforms where ACPI is designed for use with Windows, resources
> > > > > > that are intended to be consumed by sensor devices are sometimes in
> > > > > > the _CRS of a dummy INT3472 device upon which the sensor depends. This
> > > > > > driver binds to the dummy acpi device (which does not represent a
> > > > > 
> > > > > acpi device -> acpi_device
> > > > > 
> > > > > > physical PMIC) and maps them into GPIO lines and regulators for use by
> > > > > > the sensor device instead.
> > > > > 
> > > > > ...
> > > > > 
> > > > > > This patch contains the bits of this process that we're least sure about.
> > > > > > The sensors in scope for this work are called out as dependent (in their
> > > > > > DSDT entry's _DEP) on a device with _HID INT3472. These come in at least
> > > > > > 2 kinds; those with an I2cSerialBusV2 entry (which we presume therefore
> > > > > > are legitimate tps68470 PMICs that need handling by those drivers - work
> > > > > > on that in the future). And those without an I2C device. For those without
> > > > > > an I2C device they instead have an array of GPIO pins defined in _CRS. So
> > > > > > for example, my Lenovo Miix 510's OVTI2680 sensor is dependent on one of
> > > > > > the _latter_ kind of INT3472 devices, with this _CRS:
> > > > > > 
> > > > > > Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
> > > > > > {
> > > > > >     Name (SBUF, ResourceTemplate ()
> > > > > >     {
> > > > > >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > > > > > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > > > > > 	    0x00, ResourceConsumer, ,
> > > > > >             )
> > > > > >             {   // Pin list
> > > > > >                 0x0079
> > > > > >             }
> > > > > >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > > > > > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > > > > > 	    0x00, ResourceConsumer, ,
> > > > > >             )
> > > > > >             {   // Pin list
> > > > > >                 0x007A
> > > > > >             }
> > > > > >         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
> > > > > > 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
> > > > > > 	    0x00, ResourceConsumer, ,
> > > > > >             )
> > > > > >             {   // Pin list
> > > > > >                 0x008F
> > > > > >             }
> > > > > >     })
> > > > > >     Return (SBUF) /* \_SB_.PCI0.PMI1._CRS.SBUF */
> > > > > > }
> > > > > > 
> > > > > > and the same device has a _DSM Method, which returns 32-bit ints where
> > > > > > the second lowest byte we noticed to match the pin numbers of the GPIO
> > > > > > lines:
> > > > > > 
> > > > > > Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
> > > > > > {
> > > > > >     If ((Arg0 == ToUUID ("79234640-9e10-4fea-a5c1-b5aa8b19756f")))
> > > > > >     {
> > > > > >         If ((Arg2 == One))
> > > > > >         {
> > > > > >             Return (0x03)
> > > > > >         }
> > > > > > 
> > > > > >         If ((Arg2 == 0x02))
> > > > > >         {
> > > > > >             Return (0x01007900)
> > > > > >         }
> > > > > > 
> > > > > >         If ((Arg2 == 0x03))
> > > > > >         {
> > > > > >             Return (0x01007A0C)
> > > > > >         }
> > > > > > 
> > > > > >         If ((Arg2 == 0x04))
> > > > > >         {
> > > > > >             Return (0x01008F01)
> > > > > >         }
> > > > > >     }
> > > > > > 
> > > > > >     Return (Zero)
> > > > > > }
> > > > > > 
> > > > > > We know that at least some of those pins have to be toggled active for the
> > > > > > sensor devices to be available in i2c, so the conclusion we came to was
> > > > > > that those GPIO entries assigned to the INT3472 device actually represent
> > > > > > GPIOs and regulators to be consumed by the sensors themselves. Tsuchiya
> > > > > > noticed that the lowest byte in the return values of the _DSM method
> > > > > > seemed to represent the type or function of the GPIO line, and we
> > > > > > confirmed that by testing on each surface device that GPIO lines where the
> > > > > > low byte in the _DSM entry for that pin was 0x0d controlled the privacy
> > > > > > LED of the cameras.
> > > > > > 
> > > > > > We're guessing as to the exact meaning of the function byte, but I
> > > > > > conclude they're something like this:
> > > > > > 
> > > > > > 0x00 - probably a reset GPIO
> > > > > > 0x01 - regulator for the sensor
> > > > > > 0x0c - regulator for the sensor
> > > > > > 0x0b - regulator again, but for a VCM or EEPROM
> > > > > > 0x0d - privacy led (only one we're totally confident of since we can see
> > > > > >        it happen!)
> > > > > 
> > > > > It's solely Windows driver design...
> > > > > Luckily I found some information and can clarify above table:
> > > > > 
> > > > > 0x00 Reset
> > > > > 0x01 Power down
> > > > > 0x0b Power enable
> > > > > 0x0c Clock enable
> > > > > 0x0d LED (active high)
> > > > 
> > > > That's very useful information ! Thank you.
> > > > 
> > > > > The above text perhaps should go somewhere under Documentation.
> > > > 
> > > > Or in the driver source code, but definitely somewhere else than in the
> > > > commit message.
> > > > 
> > > > > > After much internal debate I decided to write this as a standalone
> > > > > > acpi_driver. Alternative options we considered:
> > > > > > 
> > > > > > 1. Squash all this into the cio2-bridge code, which I did originally write
> > > > > > but decided I didn't like.
> > > > > > 2. Extend the existing tps68470 mfd driver...they share an ACPI ID so this
> > > > > > kinda makes sense, but ultimately given there is no actual physical
> > > > > > tps68470 in the scenario this patch handles I decided I didn't like this
> > > > > > either.
> > > > > 
> > > > > Looking to this I think the best is to create a module that can be consumed by tps68470 and separately.
> > > > > So, something near to it rather than under ipu3 hood.
> > > > > 
> > > > > You may use same ID's in both drivers (in PMIC less case it can be simple
> > > > > platform and thus they won't conflict), but both of them should provide GPIO
> > > > > resources for consumption.
> > > > > 
> > > > > So, something like
> > > > > 
> > > > >  tps68470.h with API to consume
> > > > >  split tps68470 to -core, -i2c parts
> > > > >  add int3472, which will serve for above and be standalone platform driver
> > > > >  update cio2-bridge accordingly
> > > > > 
> > > > > Would it be feasible?
> > > > 
> > > > Given that INT3472 means Intel camera power management device (that's
> > > > more or less the wording in Windows, I can double-check), would the
> > > > following make sense ?
> > > > 
> > > > A top-level module named intel-camera-pmic (or int3472, or ...) would
> > > > register two drivers, a platform driver and an I2C driver, to
> > > > accommodate for both cases ("discrete PMIC" that doesn't have an
> > > > I2cSerialBusV2, and TPS64870 or uP6641Q that are I2C devices). The probe
> > > > function would perform the following:
> > > > 
> > > > - If there's no CLDB, then the device uses the Chrome OS "ACPI
> > > >   bindings", and refers to a TPS64870. The code that exists in the
> > > >   kernel today (registering GPIOs, and registering an OpRegion to
> > > >   communicate with the power management code in the DSDT) would be
> > > >   activated.
> > > > 
> > > > - If there's a CLDB, then the device type would be retrieved from it:
> > > > 
> > > >   - If the device is a "discrete PMIC", the driver would register clocks
> > > >     and regulators controlled by GPIOs, and create clock, regulator and
> > > >     GPIO lookup entries for the sensor device that references the PMIC.
> > > > 
> > > >   - If the device is a TPS64870, the code that exists in the kernel
> > > >     today to register GPIOs would be activated, and new code would need
> > > >     to be written to register regulators and clocks.
> > > > 
> > > >   - If the device is a uP6641Q, a new driver will need to be written (I
> > > >     don't know on which devices this PMIC is used, so this can probably
> > > >     be deferred).
> > > > 
> > > > We can split this in multiple files and/or modules.
> > > 
> > > That's what I thought of, too, as one option, but with some more detail.
> > > This would be indeed the cleanest option.
> > > 
> > > I think it'd be nice if the CLDB stuff (apart from checking whether it's
> > > there) would be in a different module to avoid cluttering up the real
> > > tps68470 driver.
> > 
> > Given the amount of code, and the fact that the driver should be
> > compiled as a module, I don't think it will make a huge difference in
> > the memory footprint.
> 
> I'd still prefer to keep the ACPI hack support and the real driver well
> separated. That way it'd be also easy to put them to their respective
> modules. That's actually how the tps68470 MFD driver is currently arranged;
> the GPIO and OP region drivers are separate from each other.

I think we should consider ACPI to be a hack in the first place :-)

> Could this be just one more platform device for each of the three cases (or
> one for the two latter; I'm not quite sure yet)?

Using MFD for this seems a bit overkill to me. I won't care much as I
won't maintain those drivers, but the current situation is complex
enough, it was hard for me to understand how things worked. Adding yet
another layer with another platform device won't make it any simpler.

If we want to split this in two, I'd rather have a tps68470 driver on
one side, without ACPI op region support, but registering regulators,
GPIOs and clocks (without using separate drivers and devices for these
three features), and an INT3472 driver on the other side, with all the
ACPI glue and hacks. The tps68470 code could possibly even be structured
in such a way that it would be used as a library by the INT3472 driver
instead of requiring a separate platform device.

> The GPIO regulator case is relatively safe, but the real PMICs require
> regulator voltage control as well as enabling and disabling the regulators.
> That probably requires either schematics or checking the register values at
> runtime on Windows (i.e. finding out which system you're dealing with, at
> runtime).

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 20:34                 ` Hans de Goede
  2020-12-01 20:46                   ` Andy Shevchenko
@ 2020-12-02 12:48                   ` Laurent Pinchart
  2020-12-02 15:15                     ` Andy Shevchenko
  1 sibling, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2020-12-02 12:48 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Andy Shevchenko, Dan Scally, linux-kernel, linux-acpi,
	linux-gpio, linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	sakari.ailus, bingbu.cao, tian.shu.qiu, mchehab, robert.moore,
	erik.kaneda, pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Hans,

On Tue, Dec 01, 2020 at 09:34:58PM +0100, Hans de Goede wrote:
> On 12/1/20 8:21 PM, Andy Shevchenko wrote:
> > On Tue, Dec 01, 2020 at 09:06:38PM +0200, Laurent Pinchart wrote:
> >> On Tue, Dec 01, 2020 at 09:05:23PM +0200, Andy Shevchenko wrote:
> >>> On Tue, Dec 01, 2020 at 08:55:48PM +0200, Laurent Pinchart wrote:
> >>>> On Tue, Dec 01, 2020 at 08:54:17PM +0200, Andy Shevchenko wrote:
> >>>>> On Tue, Dec 01, 2020 at 08:30:03AM +0000, Dan Scally wrote:
> >>>>>> On 30/11/2020 20:07, Andy Shevchenko wrote:
> >>>
> >>> ...
> >>>
> >>>>>>>> +static struct int3472_sensor_regulator_map int3472_sensor_regulator_maps[] = {
> >>>>>>>> +	{ "GNDF140809R", 2, miix_510_ov2680 },
> >>>>>>>> +	{ "YHCU", 2, surface_go2_ov5693 },
> >>>>>>>> +	{ "MSHW0070", 2, surface_book_ov5693 },
> >>>>>>>> +};
> >>>>>>>
> >>>>>>> Hmm... Usual way is to use DMI for that. I'm not sure above will not give us
> >>>>>>> false positive matches.
> >>>>>>
> >>>>>> I considered DMI too, no problem to switch to that if it's a better choice.
> >>>>>
> >>>>> I prefer DMI as it's a standard way to describe platform quirks in x86 world.
> >>>>
> >>>> Do you think the Windows driver would use DMI ?
> >>>
> >>> Linux is using DMI for quirks.
> >>>
> >>>> That seems quite
> >>>> unlikely to me, given how they would have to release a new driver binary
> >>>> for every machine. I'm pretty sure that a different mechanism is used to
> >>>> identify camera integration, and I think it would make sense to follow
> >>>> the same approach. That would allow us to avoid large tables of DMI
> >>>> identifiers that would need to be constently updated, potentially making
> >>>> user experience better.
> >>>
> >>> All Surface family can be matched in a way as Apple machines [1].
> >>>
> >>> [1]: https://lkml.org/lkml/2020/4/15/1198
> >>
> >> But not all Surface machines necessarily have the same camera
> >> architecture. My point is that there seems to be identifiers reported in
> >> ACPI for the exact purpose of identifying the camera architecture. If we
> >> used DMI instead, we would have to handle each machine individually.
> > 
> > With help of DMI we may narrow down the search.
> > 
> > But again, we are talking about uncertainity. It may be your way (a lot of
> > platforms that have different settings), or mine (only a few with more or less
> > standard sets of settings).
> > 
> > DMI is simply standard in Linux (people usually easier can grep for quirks for
> > a specific platform).
> > 
> > I would rather ask Hans' opinion since he has quite an expertise with DMI for
> > good and bad.
> 
> So generally there are 2 ways how things like this can go:
> 
> 1) There is sufficient information in the ACPI table and we use data from the
> ACPI tables
> 
> 2) There is unsufficient info in the ACPI tables (or we don't know how to
> get / interpret the data) and we use DMI quirks

And this specific case I believe there is sufficient data in the ACPI
tables, as I don't believe the Windows driver uses DMI quirks, or comes
in the form of machine-specific binaries. We however don't know how to
interpret all the data, but that should hopefully get better over time
(especially as we'll get more data points, with ACPI dumps from machines
whose schematics have leaked).

> Although we do often also use a combination, getting what we can from ACPI,
> combined with a set of defaults for what we cannot get from ACPI
> based on what reference designs use (IOW what most devices seem to have
> copy and pasted). Combined with DMI quirks for when the defaults do not
> work (which is quite often).
> 
> Depending on if "not working because of wrong defaults" has bad side effects,
> another option is also to only allow the driver to load on devices which
> have the necessary info provided through a DMI match.

Right now there shouldn't be bad side effects, but in the future we'll
need to setup a PMIC whose output voltages can be controlled, and
getting it wrong would be very bad. For that I'll definitely vote for
DMI match to start with, but I don't think that precludes using data
from ACPI. We could just prevent the driver from loading if the machine
isn't whitelisted in DMI matches, and still use ACPI data.

> I hope this helps.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-02 12:42             ` Laurent Pinchart
@ 2020-12-02 15:08               ` Andy Shevchenko
  2020-12-03 12:37                 ` Dan Scally
  0 siblings, 1 reply; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-02 15:08 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Sakari Ailus, Daniel Scally, linux-kernel, linux-acpi,
	linux-gpio, linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Wed, Dec 02, 2020 at 02:42:28PM +0200, Laurent Pinchart wrote:
> On Wed, Dec 02, 2020 at 01:09:56PM +0200, Sakari Ailus wrote:
> > On Tue, Dec 01, 2020 at 08:37:58PM +0200, Laurent Pinchart wrote:

...

> I think we should consider ACPI to be a hack in the first place :-)

I feel that about DT (and all chaos around it) but it's not a topic here.

> > Could this be just one more platform device for each of the three cases (or
> > one for the two latter; I'm not quite sure yet)?
> 
> Using MFD for this seems a bit overkill to me. I won't care much as I
> won't maintain those drivers, but the current situation is complex
> enough, it was hard for me to understand how things worked. Adding yet
> another layer with another platform device won't make it any simpler.
> 
> If we want to split this in two, I'd rather have a tps68470 driver on
> one side, without ACPI op region support, but registering regulators,
> GPIOs and clocks (without using separate drivers and devices for these
> three features), and an INT3472 driver on the other side, with all the
> ACPI glue and hacks. The tps68470 code could possibly even be structured
> in such a way that it would be used as a library by the INT3472 driver
> instead of requiring a separate platform device.

I'm afraid TPS68470 is MFD in hardware and its representation in the MFD is
fine. What we need is to move IN3472 pieces out from it.

And I agree with your proposal in general.

> > The GPIO regulator case is relatively safe, but the real PMICs require
> > regulator voltage control as well as enabling and disabling the regulators.
> > That probably requires either schematics or checking the register values at
> > runtime on Windows (i.e. finding out which system you're dealing with, at
> > runtime).

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-02 12:35             ` Laurent Pinchart
@ 2020-12-02 15:11               ` Andy Shevchenko
  0 siblings, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-02 15:11 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Dan Scally, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Wed, Dec 02, 2020 at 02:35:40PM +0200, Laurent Pinchart wrote:
> On Wed, Dec 02, 2020 at 11:39:52AM +0200, Andy Shevchenko wrote:
> > On Tue, Dec 01, 2020 at 08:59:53PM +0000, Dan Scally wrote:
> > > On 01/12/2020 18:49, Andy Shevchenko wrote:

...

> > I just realize that the name of int3472 should follow the same pattern, i.e.
> > intel_skl_int3472.c
> 
> We're mostly focussing on Kaby Lake here though. From what I understand
> the ACPI infrastructure for camera support is mostly the same on Sky
> Lake, but not identical. I think a single driver should be able to cover
> both though.

They (KBL and SKL) are sharing a lot, so I would name if after Skylake and use
for Kaby Lake as well.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-02 12:48                   ` Laurent Pinchart
@ 2020-12-02 15:15                     ` Andy Shevchenko
  0 siblings, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-02 15:15 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Hans de Goede, Dan Scally, linux-kernel, linux-acpi, linux-gpio,
	linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	sakari.ailus, bingbu.cao, tian.shu.qiu, mchehab, robert.moore,
	erik.kaneda, pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Wed, Dec 02, 2020 at 02:48:47PM +0200, Laurent Pinchart wrote:
> On Tue, Dec 01, 2020 at 09:34:58PM +0100, Hans de Goede wrote:
> > On 12/1/20 8:21 PM, Andy Shevchenko wrote:
> > > On Tue, Dec 01, 2020 at 09:06:38PM +0200, Laurent Pinchart wrote:

...

> > > I would rather ask Hans' opinion since he has quite an expertise with DMI for
> > > good and bad.
> > 
> > So generally there are 2 ways how things like this can go:
> > 
> > 1) There is sufficient information in the ACPI table and we use data from the
> > ACPI tables
> > 
> > 2) There is unsufficient info in the ACPI tables (or we don't know how to
> > get / interpret the data) and we use DMI quirks
> 
> And this specific case I believe there is sufficient data in the ACPI
> tables, as I don't believe the Windows driver uses DMI quirks, or comes
> in the form of machine-specific binaries. We however don't know how to
> interpret all the data, but that should hopefully get better over time
> (especially as we'll get more data points, with ACPI dumps from machines
> whose schematics have leaked).

I think you are too optimistic about this part of Windows drivers.
I would rather think about hardware stuck with the same frequencies which
simply are hard coded in the Windows driver.

I have description of ASL for this camera, but I don't see anything like this
you are describing.

> > Although we do often also use a combination, getting what we can from ACPI,
> > combined with a set of defaults for what we cannot get from ACPI
> > based on what reference designs use (IOW what most devices seem to have
> > copy and pasted). Combined with DMI quirks for when the defaults do not
> > work (which is quite often).
> > 
> > Depending on if "not working because of wrong defaults" has bad side effects,
> > another option is also to only allow the driver to load on devices which
> > have the necessary info provided through a DMI match.
> 
> Right now there shouldn't be bad side effects, but in the future we'll
> need to setup a PMIC whose output voltages can be controlled, and
> getting it wrong would be very bad. For that I'll definitely vote for
> DMI match to start with, but I don't think that precludes using data
> from ACPI. We could just prevent the driver from loading if the machine
> isn't whitelisted in DMI matches, and still use ACPI data.

I also think about DMI as a narrowing scope of supported platforms.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 15/18] i2c: i2c-core-acpi: Add i2c_acpi_dev_name()
  2020-11-30 17:11   ` Laurent Pinchart
@ 2020-12-02 22:44     ` Dan Scally
  0 siblings, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-02 22:44 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On 30/11/2020 17:11, Laurent Pinchart wrote:
> Hi Daniel,
> 
> Thank you for the patch.
> 
> On Mon, Nov 30, 2020 at 01:31:26PM +0000, Daniel Scally wrote:
>> Some places in the kernel allow users to map resources to a device
>> using device name (for example, gpiod_lookup_table). Currently
>> this involves waiting for the i2c_client to have been registered so we
>> can use dev_name(&client->dev). Adding this function means that we can
>> achieve the same thing without having to wait to the i2c device.
>>
>> Signed-off-by: Daniel Scally <djrscally@gmail.com>
>> ---
>> Changes since RFC v3:
>>
>> 	- Patch introduced
>>
>>  drivers/i2c/i2c-core-acpi.c | 14 ++++++++++++++
>>  include/linux/i2c.h         |  5 +++++
>>  2 files changed, 19 insertions(+)
>>
>> diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
>> index 37c510d9347a..d3a653eac79e 100644
>> --- a/drivers/i2c/i2c-core-acpi.c
>> +++ b/drivers/i2c/i2c-core-acpi.c
>> @@ -497,6 +497,20 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
>>  }
>>  EXPORT_SYMBOL_GPL(i2c_acpi_new_device);
>>  
>> +/**
>> + * i2c_acpi_dev_name - Construct i2c device name for devs sourced from ACPI
>> + * @adev:     ACPI device to construct the name for
>> + *
>> + * Prefixes "i2c-" to the ACPI device name, for use in i2c_dev_set_name() and
>> + * also anywhere else in the kernel that needs to refer to an i2c device by
>> + * name but before they have been instantiated.
> 
> The documentation should state that the caller must free the return
> value.

Updated to include that - thanks

>> + */
>> +char *i2c_acpi_dev_name(struct acpi_device *adev)
>> +{
>> +	return kasprintf(GFP_KERNEL, "i2c-%s", acpi_dev_name(adev));
>> +}
>> +EXPORT_SYMBOL_GPL(i2c_acpi_dev_name);
>> +
>>  #ifdef CONFIG_ACPI_I2C_OPREGION
>>  static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
>>  		u8 cmd, u8 *data, u8 data_len)
>> diff --git a/include/linux/i2c.h b/include/linux/i2c.h
>> index 56622658b215..ab0e505b2ca6 100644
>> --- a/include/linux/i2c.h
>> +++ b/include/linux/i2c.h
>> @@ -995,6 +995,7 @@ bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
>>  u32 i2c_acpi_find_bus_speed(struct device *dev);
>>  struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
>>  				       struct i2c_board_info *info);
>> +char *i2c_acpi_dev_name(struct acpi_device *adev);
>>  struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle);
>>  #else
>>  static inline bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
>> @@ -1011,6 +1012,10 @@ static inline struct i2c_client *i2c_acpi_new_device(struct device *dev,
>>  {
>>  	return ERR_PTR(-ENODEV);
>>  }
>> +static inline char *i2c_acpi_dev_name(struct acpi_device *adev)
>> +{
>> +	return NULL;
>> +}
>>  static inline struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle)
>>  {
>>  	return NULL;
> 


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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-12-02 12:02             ` Andy Shevchenko
@ 2020-12-02 22:44               ` Dan Scally
  0 siblings, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-02 22:44 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Sakari Ailus, Laurent Pinchart, linux-kernel, linux-acpi,
	linux-gpio, linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On 02/12/2020 12:02, Andy Shevchenko wrote:
> On Wed, Dec 02, 2020 at 10:53:05AM +0000, Dan Scally wrote:
>> On 02/12/2020 10:38, Sakari Ailus wrote:
> 
> ...
> 
>>>>> Argh, thanks, this is the curse of using VS code on multiple machines...
>>>> I recommend vim ;-)
>>> What is VS code? Very Serious Code?
>>
>> Visual Studio Code - it has some nice features, but the
>> facepalm-to-productivity ratio is a bit high.
> 
> Perhaps you can submit an issue report on GitHub. I found VS Code pretty nice
> to be with Linux kernel development.

Yeah I like it too; it's the one I've stuck with despite the annoyances
I find. It has some super handy features for someone who doesn't know
most of the kernel APIs very well yet. Writing up the issues is on my
to-do list but I hate to do it without at least putting some effort into
figuring out what the problem is and I so far didn't get round to that yet

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-02  9:39           ` Andy Shevchenko
  2020-12-02 12:35             ` Laurent Pinchart
@ 2020-12-03 12:25             ` Dan Scally
  1 sibling, 0 replies; 144+ messages in thread
From: Dan Scally @ 2020-12-03 12:25 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Laurent Pinchart, linux-kernel, linux-acpi, linux-gpio,
	linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	sakari.ailus, bingbu.cao, tian.shu.qiu, mchehab, robert.moore,
	erik.kaneda, pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On 02/12/2020 09:39, Andy Shevchenko wrote:
> On Tue, Dec 01, 2020 at 08:59:53PM +0000, Dan Scally wrote:
>> On 01/12/2020 18:49, Andy Shevchenko wrote:
> 
> ...
> 
>>> Seems we can do this, by locating intel_int3472.c under PDx86 hood and dropping
>>> ACPI ID table from TPS68470 MFD driver. The PMIC can be instantiated via
>>> i2c_acpi_new_device() (IIRC the API name).
>>>
>>> And actually it makes more sense since it's not and MFD and should not be there.
>>>
>>> (Dan, patch wise the one creates intel_int3472.c followed by another one that
>>>  moves ACPI ID from PMIC and introduces its instantiation via I²C board info
>>>  structure)
>>
>> I'm mostly following this, but why would we need an i2c_board_info or
>> i2c_acpi_new_device()? The INT3472 entries that refer to actual tps68470
>> devices do have an I2cSerialBusV2 enumerated in _CRS so in their case
>> there's an i2c device registered with the kernel already.
> 
> Because as we discussed already we can't have two drivers for the same ID
> without a big disruption in the driver(s).
> 
> If you have a single point of enumeration, it will make things much easier
> (refer to the same intel_cht_int33fe driver you mentioned earlier).
> 
> I just realize that the name of int3472 should follow the same pattern, i.e.
> intel_skl_int3472.c

Ah! I didn't read intel_cht_int33fe_common.c before, just the typec.c.
Having reviewed common I think I'm clear on the method now, thank you :)


>> I think we need those things when we get round to handling the
>> VCM/EEPROM that's hidden within the sensor's ACPI entry, but I've not
>> done any work on that yet at all.
> 
> Let's consider this later — one step at a time.

Agree!


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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-02 15:08               ` Andy Shevchenko
@ 2020-12-03 12:37                 ` Dan Scally
  2020-12-03 12:57                   ` Andy Shevchenko
  0 siblings, 1 reply; 144+ messages in thread
From: Dan Scally @ 2020-12-03 12:37 UTC (permalink / raw)
  To: Andy Shevchenko, Laurent Pinchart
  Cc: Sakari Ailus, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	linus.walleij, bgolaszewski, wsa, yong.zhi, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

On 02/12/2020 15:08, Andy Shevchenko wrote:
> On Wed, Dec 02, 2020 at 02:42:28PM +0200, Laurent Pinchart wrote:
>> On Wed, Dec 02, 2020 at 01:09:56PM +0200, Sakari Ailus wrote:
>>> On Tue, Dec 01, 2020 at 08:37:58PM +0200, Laurent Pinchart wrote:
> 
> ...
> 
>> I think we should consider ACPI to be a hack in the first place :-)
> 
> I feel that about DT (and all chaos around it) but it's not a topic here.
> 
>>> Could this be just one more platform device for each of the three cases (or
>>> one for the two latter; I'm not quite sure yet)?
>>
>> Using MFD for this seems a bit overkill to me. I won't care much as I
>> won't maintain those drivers, but the current situation is complex
>> enough, it was hard for me to understand how things worked. Adding yet
>> another layer with another platform device won't make it any simpler.
>>
>> If we want to split this in two, I'd rather have a tps68470 driver on
>> one side, without ACPI op region support, but registering regulators,
>> GPIOs and clocks (without using separate drivers and devices for these
>> three features), and an INT3472 driver on the other side, with all the
>> ACPI glue and hacks. The tps68470 code could possibly even be structured
>> in such a way that it would be used as a library by the INT3472 driver
>> instead of requiring a separate platform device.
> 
> I'm afraid TPS68470 is MFD in hardware and its representation in the MFD is
> fine. What we need is to move IN3472 pieces out from it.
> 
> And I agree with your proposal in general.

Way back when I first joined this project we thought we needed i2c
drivers for driving the tps68470's clks and regulators. Tsuchiya found
some in an old Intel tree; they needed some minor tweaks but nothing
drastic. And I think they're designed to work with the mfd driver that's
already in the kernel.

So, can we do this by just checking (in a new
platform/x86/intel_skl_int3472.c) for a CLDB buffer in the PMIC, and
calling devm_mfd_add_devices() with either the GPIO and OpRegion drivers
(if no CLDB buffer found) or with the GPIO, clk and regulator drivers
(If there's a CLDB and it's not a discrete PMIC). Or else, using the
code from this patch directly in the platform driver if the CLDB says
it's a discrete PMIC?

>>> The GPIO regulator case is relatively safe, but the real PMICs require
>>> regulator voltage control as well as enabling and disabling the regulators.
>>> That probably requires either schematics or checking the register values at
>>> runtime on Windows (i.e. finding out which system you're dealing with, at
>>> runtime).
> 


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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-03 12:37                 ` Dan Scally
@ 2020-12-03 12:57                   ` Andy Shevchenko
  0 siblings, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-03 12:57 UTC (permalink / raw)
  To: Dan Scally
  Cc: Laurent Pinchart, Sakari Ailus, linux-kernel, linux-acpi,
	linux-gpio, linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Thu, Dec 03, 2020 at 12:37:12PM +0000, Dan Scally wrote:
> On 02/12/2020 15:08, Andy Shevchenko wrote:
> > On Wed, Dec 02, 2020 at 02:42:28PM +0200, Laurent Pinchart wrote:
> >> On Wed, Dec 02, 2020 at 01:09:56PM +0200, Sakari Ailus wrote:
> >>> On Tue, Dec 01, 2020 at 08:37:58PM +0200, Laurent Pinchart wrote:
> > 
> > ...
> > 
> >> I think we should consider ACPI to be a hack in the first place :-)
> > 
> > I feel that about DT (and all chaos around it) but it's not a topic here.
> > 
> >>> Could this be just one more platform device for each of the three cases (or
> >>> one for the two latter; I'm not quite sure yet)?
> >>
> >> Using MFD for this seems a bit overkill to me. I won't care much as I
> >> won't maintain those drivers, but the current situation is complex
> >> enough, it was hard for me to understand how things worked. Adding yet
> >> another layer with another platform device won't make it any simpler.
> >>
> >> If we want to split this in two, I'd rather have a tps68470 driver on
> >> one side, without ACPI op region support, but registering regulators,
> >> GPIOs and clocks (without using separate drivers and devices for these
> >> three features), and an INT3472 driver on the other side, with all the
> >> ACPI glue and hacks. The tps68470 code could possibly even be structured
> >> in such a way that it would be used as a library by the INT3472 driver
> >> instead of requiring a separate platform device.
> > 
> > I'm afraid TPS68470 is MFD in hardware and its representation in the MFD is
> > fine. What we need is to move IN3472 pieces out from it.
> > 
> > And I agree with your proposal in general.
> 
> Way back when I first joined this project we thought we needed i2c
> drivers for driving the tps68470's clks and regulators. Tsuchiya found
> some in an old Intel tree; they needed some minor tweaks but nothing
> drastic. And I think they're designed to work with the mfd driver that's
> already in the kernel.
> 
> So, can we do this by just checking (in a new
> platform/x86/intel_skl_int3472.c) for a CLDB buffer in the PMIC, and
> calling devm_mfd_add_devices() with either the GPIO and OpRegion drivers
> (if no CLDB buffer found) or with the GPIO, clk and regulator drivers
> (If there's a CLDB and it's not a discrete PMIC). Or else, using the
> code from this patch directly in the platform driver if the CLDB says
> it's a discrete PMIC?

Lee, who is a maintainer of MFD, is quite sensitive about this.
I don't think he would approve this (however I see 8 drivers
that are using MFD API out of drivers/mfd).

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-01 18:49       ` Andy Shevchenko
  2020-12-01 20:59         ` Dan Scally
@ 2020-12-13 22:48         ` Daniel Scally
  2020-12-14 15:33           ` Andy Shevchenko
  1 sibling, 1 reply; 144+ messages in thread
From: Daniel Scally @ 2020-12-13 22:48 UTC (permalink / raw)
  To: Andy Shevchenko, Laurent Pinchart
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus

On 01/12/2020 18:49, Andy Shevchenko wrote:
>>>> +	table_entry = (struct gpiod_lookup)GPIO_LOOKUP_IDX(acpi_dev_name(adev),
>>>> +							   ares->data.gpio.pin_table[0],
>>>> +							   func, 0, GPIO_ACTIVE_HIGH);
>>>
>>> You won't need this if you have regular INT3472 platform driver.
>>> Simple call there _DSM to map resources to the type and use devm_gpiod_get on
>>> consumer behalf. Thus, previous patch is not needed.
>>
>> How does the consumer (the camera sensor) retrieve the GPIO though ? The
>> _DSM is in the PMIC device object, while the real consumer is the camera
>> sensor.
> 
> 1. A GPIO proxy
> 2. A custom GPIO lookup tables
> 3. An fwnode passing to the sensor (via swnodes graph)
> 
> First may issue deferred probe, while second needs some ordering tricks I guess.
> Third one should also provide an ACPI GPIO mapping table or so to make the
> consumer rely on names rather than custom numbers.
> 
> Perhaps someone may propose other solutions.

Hi Andy

Sorry; some more clarification here if you have time please:

1. Do you mean here, register a new gpio_chip providing GPIOs to the
sensors, and just have the .set() callback for that function set the
corresponding line against the INT3472 device?
2. I thought custom GPIO lookup tables was what I was doing, are you
referring to something else?
3. I guess you mean something like of_find_gpio() and acpi_find_gpio()
here? As far as I can see there isn't currently a swnodes
equivalent...we could just pass it via reference of course but it would
mean the sensor drivers would all need to account for that.

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-12-13 22:48         ` Daniel Scally
@ 2020-12-14 15:33           ` Andy Shevchenko
  0 siblings, 0 replies; 144+ messages in thread
From: Andy Shevchenko @ 2020-12-14 15:33 UTC (permalink / raw)
  To: Daniel Scally
  Cc: Laurent Pinchart, linux-kernel, linux-acpi, linux-gpio,
	linux-i2c, linux-media, devel, rjw, lenb, gregkh,
	mika.westerberg, linus.walleij, bgolaszewski, wsa, yong.zhi,
	sakari.ailus, bingbu.cao, tian.shu.qiu, mchehab, robert.moore,
	erik.kaneda, pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On Sun, Dec 13, 2020 at 10:48:39PM +0000, Daniel Scally wrote:
> On 01/12/2020 18:49, Andy Shevchenko wrote:
> >>>> +	table_entry = (struct gpiod_lookup)GPIO_LOOKUP_IDX(acpi_dev_name(adev),
> >>>> +							   ares->data.gpio.pin_table[0],
> >>>> +							   func, 0, GPIO_ACTIVE_HIGH);
> >>>
> >>> You won't need this if you have regular INT3472 platform driver.
> >>> Simple call there _DSM to map resources to the type and use devm_gpiod_get on
> >>> consumer behalf. Thus, previous patch is not needed.
> >>
> >> How does the consumer (the camera sensor) retrieve the GPIO though ? The
> >> _DSM is in the PMIC device object, while the real consumer is the camera
> >> sensor.
> > 
> > 1. A GPIO proxy
> > 2. A custom GPIO lookup tables
> > 3. An fwnode passing to the sensor (via swnodes graph)
> > 
> > First may issue deferred probe, while second needs some ordering tricks I guess.
> > Third one should also provide an ACPI GPIO mapping table or so to make the
> > consumer rely on names rather than custom numbers.
> > 
> > Perhaps someone may propose other solutions.
> 
> Hi Andy
> 
> Sorry; some more clarification here if you have time please:

No problem, thanks for discussing this.

> 1. Do you mean here, register a new gpio_chip providing GPIOs to the
> sensors, and just have the .set() callback for that function set the
> corresponding line against the INT3472 device?

Yes. On one hand it should be a consumer (*gpiod_get*() family of APIs),
on the other it should be provider of known (artificial) GPIO chip.

> 2. I thought custom GPIO lookup tables was what I was doing, are you
> referring to something else?

I think so, i.e. nothing else from high point of view.

> 3. I guess you mean something like of_find_gpio() and acpi_find_gpio()
> here? As far as I can see there isn't currently a swnodes
> equivalent...we could just pass it via reference of course but it would
> mean the sensor drivers would all need to account for that.

Theoretically we may provide GPIOs as swnodes. In that case the consumer will
get them as usual But I think it may be too complicated / over engineered.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-11-30 20:35   ` Sakari Ailus
  2020-12-01  8:13     ` Dan Scally
  2020-12-01 15:06     ` Andy Shevchenko
@ 2020-12-15 10:28     ` Daniel Scally
  2020-12-15 10:32       ` Daniel Scally
  2020-12-15 22:02       ` Sakari Ailus
  2 siblings, 2 replies; 144+ messages in thread
From: Daniel Scally @ 2020-12-15 10:28 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Morning Sakari

On 30/11/2020 20:35, Sakari Ailus wrote:
>> +/*
>> + * Extend this array with ACPI Hardware ID's of devices known to be working.
>> + * Do not add a HID for a sensor that is not actually supported.
>> + */
>> +static const char * const cio2_supported_devices[] = {
>> +	"INT33BE",
>> +	"OVTI2680",
> 
> I guess we don't have the known-good frequencies for the CSI-2 bus in
> firmware?
> 
> One option would be to put there what the drivers currently use. This
> assumes the support for these devices is, well, somewhat opportunistic but
> I guess there's no way around that right now at least.
> 
> As the systems are laptops, they're likely somewhat less prone to EMI
> issues to begin with than mobile phones anyway.

Just looking at this; we're currently using this with the ov2680 driver
that's in mainline currently (with very minor tweaks) plus a
hacked-into-roughly-working version of the atomisp-ov5693 driver (ACPI
ID INT33BE = ov5693 physical device). Neither of those drivers lists any
link frequencies, nor provides a link frequency control for v4l2 to work
with.

On the other hand, the ov5648 [1] and ov8865 [2] drivers which Paul has
submitted recently, which we also want to be able to support, _do_
include that. I can register the frequencies Paul's defined there as a
link-frequencies property but this gives rise to two questions:


1. Is this _mandatory_? Do I need to be finding the link-frequencies for
the OV2680 and OV5693 drivers too? Or can I skip that property where the
driver doesn't handle it anyway. Seems to be working fine without
controlling it in driver.
2. Can I trust all the values in the drivers to be available on each
platform? For example for the ov5648 Paul lists these as available:

 938static const s64 ov5648_link_freq_menu[] = {


 939        210000000,


 940        168000000,


 941};

But can I safely register a link-frequencies property for both of those
and trust that that'll work on all IPU3 platforms with an ov5648 in them?

Thanks
Dan

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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-12-15 10:28     ` Daniel Scally
@ 2020-12-15 10:32       ` Daniel Scally
  2020-12-15 22:02       ` Sakari Ailus
  1 sibling, 0 replies; 144+ messages in thread
From: Daniel Scally @ 2020-12-15 10:32 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, andriy.shevchenko,
	linus.walleij, bgolaszewski, wsa, yong.zhi, sakari.ailus,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

On 15/12/2020 10:28, Daniel Scally wrote:
> Morning Sakari
>
> On 30/11/2020 20:35, Sakari Ailus wrote:
>>> +/*
>>> + * Extend this array with ACPI Hardware ID's of devices known to be working.
>>> + * Do not add a HID for a sensor that is not actually supported.
>>> + */
>>> +static const char * const cio2_supported_devices[] = {
>>> +	"INT33BE",
>>> +	"OVTI2680",
>> I guess we don't have the known-good frequencies for the CSI-2 bus in
>> firmware?
>>
>> One option would be to put there what the drivers currently use. This
>> assumes the support for these devices is, well, somewhat opportunistic but
>> I guess there's no way around that right now at least.
>>
>> As the systems are laptops, they're likely somewhat less prone to EMI
>> issues to begin with than mobile phones anyway.
> Just looking at this; we're currently using this with the ov2680 driver
> that's in mainline currently (with very minor tweaks) plus a
> hacked-into-roughly-working version of the atomisp-ov5693 driver (ACPI
> ID INT33BE = ov5693 physical device). Neither of those drivers lists any
> link frequencies, nor provides a link frequency control for v4l2 to work
> with.
>
> On the other hand, the ov5648 [1] and ov8865 [2] drivers which Paul has
> submitted recently


Forgot to actually link these:


[1]
https://lore.kernel.org/linux-media/20201211154027.153535-1-paul.kocialkowski@bootlin.com/T/#m5eb18611b7df1538ed4924422583b62cc61dbfae

[2]
https://lore.kernel.org/linux-media/20201211154428.153762-1-paul.kocialkowski@bootlin.com/T/#m6d4fd5e590b1c4583d4a74f5ae938ea011408640


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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-12-15 10:28     ` Daniel Scally
  2020-12-15 10:32       ` Daniel Scally
@ 2020-12-15 22:02       ` Sakari Ailus
  2020-12-17 14:17         ` Daniel Scally
  1 sibling, 1 reply; 144+ messages in thread
From: Sakari Ailus @ 2020-12-15 22:02 UTC (permalink / raw)
  To: Daniel Scally
  Cc: Sakari Ailus, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	andriy.shevchenko, linus.walleij, bgolaszewski, wsa, yong.zhi,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Daniel,

On Tue, Dec 15, 2020 at 10:28:59AM +0000, Daniel Scally wrote:
> Morning Sakari
> 
> On 30/11/2020 20:35, Sakari Ailus wrote:
> >> +/*
> >> + * Extend this array with ACPI Hardware ID's of devices known to be working.
> >> + * Do not add a HID for a sensor that is not actually supported.
> >> + */
> >> +static const char * const cio2_supported_devices[] = {
> >> +	"INT33BE",
> >> +	"OVTI2680",
> > 
> > I guess we don't have the known-good frequencies for the CSI-2 bus in
> > firmware?
> > 
> > One option would be to put there what the drivers currently use. This
> > assumes the support for these devices is, well, somewhat opportunistic but
> > I guess there's no way around that right now at least.
> > 
> > As the systems are laptops, they're likely somewhat less prone to EMI
> > issues to begin with than mobile phones anyway.
> 
> Just looking at this; we're currently using this with the ov2680 driver
> that's in mainline currently (with very minor tweaks) plus a
> hacked-into-roughly-working version of the atomisp-ov5693 driver (ACPI
> ID INT33BE = ov5693 physical device). Neither of those drivers lists any
> link frequencies, nor provides a link frequency control for v4l2 to work
> with.
> 
> On the other hand, the ov5648 [1] and ov8865 [2] drivers which Paul has
> submitted recently, which we also want to be able to support, _do_
> include that. I can register the frequencies Paul's defined there as a
> link-frequencies property but this gives rise to two questions:
> 
> 
> 1. Is this _mandatory_? Do I need to be finding the link-frequencies for
> the OV2680 and OV5693 drivers too? Or can I skip that property where the
> driver doesn't handle it anyway. Seems to be working fine without
> controlling it in driver.

Receiver drivers generally need the information to program the receiver
timing. It may work for you without using the correct frequency, but the
risk of failure on another unit increases.

> 2. Can I trust all the values in the drivers to be available on each
> platform? For example for the ov5648 Paul lists these as available:
> 
>  938static const s64 ov5648_link_freq_menu[] = {
> 
> 
>  939        210000000,
> 
> 
>  940        168000000,
> 
> 
>  941};
> 
> But can I safely register a link-frequencies property for both of those
> and trust that that'll work on all IPU3 platforms with an ov5648 in them?

Ideally we'd know which frequency Windows uses, and use the same.

Using another frequency may have adverse effects elsewhere in the system.
AFAIU mostly this concerns radios of all sorts.

Now that this is in the kernel in any case, it can be fixed later on so I'm
not too worried about it. Having still a comment there that the
configuration is opportunistic would be nice.

-- 
Kind regards,

Kind regards,

Sakari Ailus

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

* Re: [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows
  2020-12-15 22:02       ` Sakari Ailus
@ 2020-12-17 14:17         ` Daniel Scally
  0 siblings, 0 replies; 144+ messages in thread
From: Daniel Scally @ 2020-12-17 14:17 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: Sakari Ailus, linux-kernel, linux-acpi, linux-gpio, linux-i2c,
	linux-media, devel, rjw, lenb, gregkh, mika.westerberg,
	andriy.shevchenko, linus.walleij, bgolaszewski, wsa, yong.zhi,
	bingbu.cao, tian.shu.qiu, mchehab, robert.moore, erik.kaneda,
	pmladek, rostedt, sergey.senozhatsky, linux,
	kieran.bingham+renesas, jacopo+renesas, laurent.pinchart+renesas,
	jorhand, kitakar, heikki.krogerus

Hi Sakari - sorry for delayed reply. I didn't get this email actually,
just spotted it on the newsgroup by chance.

On 15/12/2020 22:02, Sakari Ailus wrote:
> Hi Daniel,
> 
> On Tue, Dec 15, 2020 at 10:28:59AM +0000, Daniel Scally wrote:
>> Morning Sakari
>>
>> On 30/11/2020 20:35, Sakari Ailus wrote:
>>>> +/*
>>>> + * Extend this array with ACPI Hardware ID's of devices known to be working.
>>>> + * Do not add a HID for a sensor that is not actually supported.
>>>> + */
>>>> +static const char * const cio2_supported_devices[] = {
>>>> +	"INT33BE",
>>>> +	"OVTI2680",
>>>
>>> I guess we don't have the known-good frequencies for the CSI-2 bus in
>>> firmware?
>>>
>>> One option would be to put there what the drivers currently use. This
>>> assumes the support for these devices is, well, somewhat opportunistic but
>>> I guess there's no way around that right now at least.
>>>
>>> As the systems are laptops, they're likely somewhat less prone to EMI
>>> issues to begin with than mobile phones anyway.
>>
>> Just looking at this; we're currently using this with the ov2680 driver
>> that's in mainline currently (with very minor tweaks) plus a
>> hacked-into-roughly-working version of the atomisp-ov5693 driver (ACPI
>> ID INT33BE = ov5693 physical device). Neither of those drivers lists any
>> link frequencies, nor provides a link frequency control for v4l2 to work
>> with.
>>
>> On the other hand, the ov5648 [1] and ov8865 [2] drivers which Paul has
>> submitted recently, which we also want to be able to support, _do_
>> include that. I can register the frequencies Paul's defined there as a
>> link-frequencies property but this gives rise to two questions:
>>
>>
>> 1. Is this _mandatory_? Do I need to be finding the link-frequencies for
>> the OV2680 and OV5693 drivers too? Or can I skip that property where the
>> driver doesn't handle it anyway. Seems to be working fine without
>> controlling it in driver.
> 
> Receiver drivers generally need the information to program the receiver
> timing. It may work for you without using the correct frequency, but the
> risk of failure on another unit increases.

Hmm, ok. I'll see if I can find the correct values then to add to the
existing drivers.

>> 2. Can I trust all the values in the drivers to be available on each
>> platform? For example for the ov5648 Paul lists these as available:
>>
>>  938static const s64 ov5648_link_freq_menu[] = {
>>
>>
>>  939        210000000,
>>
>>
>>  940        168000000,
>>
>>
>>  941};
>>
>> But can I safely register a link-frequencies property for both of those
>> and trust that that'll work on all IPU3 platforms with an ov5648 in them?
> 
> Ideally we'd know which frequency Windows uses, and use the same.
> 
> Using another frequency may have adverse effects elsewhere in the system.
> AFAIU mostly this concerns radios of all sorts.
> 
> Now that this is in the kernel in any case, it can be fixed later on so I'm
> not too worried about it. Having still a comment there that the
> configuration is opportunistic would be nice.
> 

Understood - I'll add in the ability to add the link-frequencies plus a
comment explaining.

Thanks
Dan


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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2020-11-30 20:07   ` Andy Shevchenko
  2020-11-30 23:32     ` Laurent Pinchart
  2020-12-01  8:30     ` Dan Scally
@ 2021-01-07 23:55     ` Daniel Scally
  2021-01-08 12:17       ` Andy Shevchenko
  2 siblings, 1 reply; 144+ messages in thread
From: Daniel Scally @ 2021-01-07 23:55 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-kernel, linux-acpi, linux-gpio, linux-i2c, linux-media,
	devel, rjw, lenb, gregkh, mika.westerberg, linus.walleij,
	bgolaszewski, wsa, yong.zhi, sakari.ailus, bingbu.cao,
	tian.shu.qiu, mchehab, robert.moore, erik.kaneda, pmladek,
	rostedt, sergey.senozhatsky, linux, kieran.bingham+renesas,
	jacopo+renesas, laurent.pinchart+renesas, jorhand, kitakar,
	heikki.krogerus, Laurent Pinchart

Hi Andy, all

On 30/11/2020 20:07, Andy Shevchenko wrote:
> On Mon, Nov 30, 2020 at 01:31:29PM +0000, Daniel Scally wrote:
>> On platforms where ACPI is designed for use with Windows, resources
>> that are intended to be consumed by sensor devices are sometimes in
>> the _CRS of a dummy INT3472 device upon which the sensor depends. This
>> driver binds to the dummy acpi device (which does not represent a
> acpi device -> acpi_device
>
>> physical PMIC) and maps them into GPIO lines and regulators for use by
>> the sensor device instead.
> ...
>
>> This patch contains the bits of this process that we're least sure about.
>> The sensors in scope for this work are called out as dependent (in their
>> DSDT entry's _DEP) on a device with _HID INT3472. These come in at least
>> 2 kinds; those with an I2cSerialBusV2 entry (which we presume therefore
>> are legitimate tps68470 PMICs that need handling by those drivers - work
>> on that in the future). And those without an I2C device. For those without
>> an I2C device they instead have an array of GPIO pins defined in _CRS. So
>> for example, my Lenovo Miix 510's OVTI2680 sensor is dependent on one of
>> the _latter_ kind of INT3472 devices, with this _CRS:
>>
>> Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
>> {
>>     Name (SBUF, ResourceTemplate ()
>>     {
>>         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
>> 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
>> 	    0x00, ResourceConsumer, ,
>>             )
>>             {   // Pin list
>>                 0x0079
>>             }
>>         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
>> 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
>> 	    0x00, ResourceConsumer, ,
>>             )
>>             {   // Pin list
>>                 0x007A
>>             }
>>         GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
>> 	    IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
>> 	    0x00, ResourceConsumer, ,
>>             )
>>             {   // Pin list
>>                 0x008F
>>             }
>>     })
>>     Return (SBUF) /* \_SB_.PCI0.PMI1._CRS.SBUF */
>> }
>>
>> and the same device has a _DSM Method, which returns 32-bit ints where
>> the second lowest byte we noticed to match the pin numbers of the GPIO
>> lines:
>>
>> Method (_DSM, 4, NotSerialized)  // _DSM: Device-Specific Method
>> {
>>     If ((Arg0 == ToUUID ("79234640-9e10-4fea-a5c1-b5aa8b19756f")))
>>     {
>>         If ((Arg2 == One))
>>         {
>>             Return (0x03)
>>         }
>>
>>         If ((Arg2 == 0x02))
>>         {
>>             Return (0x01007900)
>>         }
>>
>>         If ((Arg2 == 0x03))
>>         {
>>             Return (0x01007A0C)
>>         }
>>
>>         If ((Arg2 == 0x04))
>>         {
>>             Return (0x01008F01)
>>         }
>>     }
>>
>>     Return (Zero)
>> }
>>
>> We know that at least some of those pins have to be toggled active for the
>> sensor devices to be available in i2c, so the conclusion we came to was
>> that those GPIO entries assigned to the INT3472 device actually represent
>> GPIOs and regulators to be consumed by the sensors themselves. Tsuchiya
>> noticed that the lowest byte in the return values of the _DSM method
>> seemed to represent the type or function of the GPIO line, and we
>> confirmed that by testing on each surface device that GPIO lines where the
>> low byte in the _DSM entry for that pin was 0x0d controlled the privacy
>> LED of the cameras.
>>
>> We're guessing as to the exact meaning of the function byte, but I
>> conclude they're something like this:
>>
>> 0x00 - probably a reset GPIO
>> 0x01 - regulator for the sensor
>> 0x0c - regulator for the sensor
>> 0x0b - regulator again, but for a VCM or EEPROM
>> 0x0d - privacy led (only one we're totally confident of since we can see
>>        it happen!)
> It's solely Windows driver design...
> Luckily I found some information and can clarify above table:
>
> 0x00 Reset
> 0x01 Power down
> 0x0b Power enable
> 0x0c Clock enable
> 0x0d LED (active high)
>
> The above text perhaps should go somewhere under Documentation.

Coming back to this; there's a bit of an anomaly with the 0x01 Power
Down pin for at least one platform.  As listed above, the OV2680 on one
of my platforms has 3 GPIOs defined, and the table above gives them as
type Reset, Power down and Clock enable. I'd assumed from this table
that "power down" meant a powerdown GPIO (I.E. the one usually called
PWDNB in Omnivision datasheets and "powerdown" in drivers), but the
datasheet for the OV2680 doesn't list a separate reset and powerdown
pin, but rather a single pin that performs both functions.


Am I wrong to treat that as something that ought to be mapped as a
powerdown GPIO to the sensors? Or do you know of any other way to
reconcile that discrepancy?


Failing that; the only way I can think to handle this is to register
proxy GPIO pins assigned to the sensors as you suggested previously, and
have them toggle the GPIO's assigned to the INT3472 based on platform
specific mapping data (I.E. we register a pin called "reset", which on
most platforms just toggles the 0x00 pin, but on this specific platform
would drive both 0x00 and 0x01 together. We're already heading that way
for the regulator consumer supplies so it's sort of nothing new, but I'd
still rather not if it can be avoided.


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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2021-01-07 23:55     ` Daniel Scally
@ 2021-01-08 12:17       ` Andy Shevchenko
  2021-01-08 23:24         ` Daniel Scally
  2021-01-09  0:18         ` Laurent Pinchart
  0 siblings, 2 replies; 144+ messages in thread
From: Andy Shevchenko @ 2021-01-08 12:17 UTC (permalink / raw)
  To: Daniel Scally
  Cc: Andy Shevchenko, Linux Kernel Mailing List,
	ACPI Devel Maling List, open list:GPIO SUBSYSTEM, linux-i2c,
	Linux Media Mailing List, devel, Rafael J. Wysocki, Len Brown,
	Greg Kroah-Hartman, Mika Westerberg, Linus Walleij,
	Bartosz Golaszewski, Wolfram Sang, Yong Zhi, Sakari Ailus,
	Bingbu Cao, Tian Shu Qiu, Mauro Carvalho Chehab, Robert Moore,
	Erik Kaneda, Petr Mladek, Steven Rostedt, Sergey Senozhatsky,
	Rasmus Villemoes, kieran.bingham+renesas, Jacopo Mondi,
	Laurent Pinchart, Jordan Hand, Tsuchiya Yuto, Krogerus, Heikki,
	Laurent Pinchart

On Fri, Jan 8, 2021 at 1:56 AM Daniel Scally <djrscally@gmail.com> wrote:
> On 30/11/2020 20:07, Andy Shevchenko wrote:
> > On Mon, Nov 30, 2020 at 01:31:29PM +0000, Daniel Scally wrote:

...

> > It's solely Windows driver design...
> > Luckily I found some information and can clarify above table:
> >
> > 0x00 Reset
> > 0x01 Power down
> > 0x0b Power enable
> > 0x0c Clock enable
> > 0x0d LED (active high)
> >
> > The above text perhaps should go somewhere under Documentation.
>
> Coming back to this; there's a bit of an anomaly with the 0x01 Power
> Down pin for at least one platform.  As listed above, the OV2680 on one
> of my platforms has 3 GPIOs defined, and the table above gives them as
> type Reset, Power down and Clock enable. I'd assumed from this table
> that "power down" meant a powerdown GPIO (I.E. the one usually called
> PWDNB in Omnivision datasheets and "powerdown" in drivers), but the
> datasheet for the OV2680 doesn't list a separate reset and powerdown
> pin, but rather a single pin that performs both functions.

All of them are GPIOs, the question here is how they are actually
connected on PCB level and I have no answer to that. You have to find
schematics somewhere.

> Am I wrong to treat that as something that ought to be mapped as a
> powerdown GPIO to the sensors? Or do you know of any other way to
> reconcile that discrepancy?

The GPIOs can go directly to the sensors or be a control pin for
separate discrete power gates.
So, we can do one of the following:
 a) present PD GPIO as fixed regulator;
 b) present PD & Reset GPIOs as regulator;
 c) provide them as is to the sensor and sensor driver must do what it
considers right.

Since we don't have schematics (yet?) and we have plenty of variations
of sensors, I would go to c) and update the driver of the affected
sensor as needed. Because even if you have separate discrete PD for
one sensor on one platform there is no guarantee that it will be the
same on another. Providing a "virtual" PD in a sensor that doesn't
support it is the best choice I think. Let's hear what Sakari and
other experienced camera sensor developers say.

My vision is purely based on electrical engineering background,
experience with existing (not exactly camera) sensor drivers and
generic cases.

> Failing that; the only way I can think to handle this is to register
> proxy GPIO pins assigned to the sensors as you suggested previously, and
> have them toggle the GPIO's assigned to the INT3472 based on platform
> specific mapping data (I.E. we register a pin called "reset", which on
> most platforms just toggles the 0x00 pin, but on this specific platform
> would drive both 0x00 and 0x01 together. We're already heading that way
> for the regulator consumer supplies so it's sort of nothing new, but I'd
> still rather not if it can be avoided.


-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2021-01-08 12:17       ` Andy Shevchenko
@ 2021-01-08 23:24         ` Daniel Scally
       [not found]           ` <CAHp75Vcy878xKUUUDH5ory9uS-Vhhx_W1PZc=S6hsSLYJ0i60w@mail.gmail.com>
  2021-01-09  0:18         ` Laurent Pinchart
  1 sibling, 1 reply; 144+ messages in thread
From: Daniel Scally @ 2021-01-08 23:24 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Andy Shevchenko, Linux Kernel Mailing List,
	ACPI Devel Maling List, open list:GPIO SUBSYSTEM, linux-i2c,
	Linux Media Mailing List, devel, Rafael J. Wysocki, Len Brown,
	Greg Kroah-Hartman, Mika Westerberg, Linus Walleij,
	Bartosz Golaszewski, Wolfram Sang, Yong Zhi, Sakari Ailus,
	Bingbu Cao, Tian Shu Qiu, Mauro Carvalho Chehab, Robert Moore,
	Erik Kaneda, Petr Mladek, Steven Rostedt, Sergey Senozhatsky,
	Rasmus Villemoes, kieran.bingham+renesas, Jacopo Mondi,
	Laurent Pinchart, Jordan Hand, Tsuchiya Yuto, Krogerus, Heikki,
	Laurent Pinchart

Hi Andy

On 08/01/2021 12:17, Andy Shevchenko wrote:
> On Fri, Jan 8, 2021 at 1:56 AM Daniel Scally <djrscally@gmail.com> wrote:
>> On 30/11/2020 20:07, Andy Shevchenko wrote:
>>> On Mon, Nov 30, 2020 at 01:31:29PM +0000, Daniel Scally wrote:
> ...
>
>>> It's solely Windows driver design...
>>> Luckily I found some information and can clarify above table:
>>>
>>> 0x00 Reset
>>> 0x01 Power down
>>> 0x0b Power enable
>>> 0x0c Clock enable
>>> 0x0d LED (active high)
>>>
>>> The above text perhaps should go somewhere under Documentation.
>> Coming back to this; there's a bit of an anomaly with the 0x01 Power
>> Down pin for at least one platform.  As listed above, the OV2680 on one
>> of my platforms has 3 GPIOs defined, and the table above gives them as
>> type Reset, Power down and Clock enable. I'd assumed from this table
>> that "power down" meant a powerdown GPIO (I.E. the one usually called
>> PWDNB in Omnivision datasheets and "powerdown" in drivers), but the
>> datasheet for the OV2680 doesn't list a separate reset and powerdown
>> pin, but rather a single pin that performs both functions.
> All of them are GPIOs, the question here is how they are actually
> connected on PCB level and I have no answer to that. You have to find
> schematics somewhere.

Yeah; I've been trying to get those but so far, no dice.

>
>> Am I wrong to treat that as something that ought to be mapped as a
>> powerdown GPIO to the sensors? Or do you know of any other way to
>> reconcile that discrepancy?
> The GPIOs can go directly to the sensors or be a control pin for
> separate discrete power gates.
> So, we can do one of the following:
>  a) present PD GPIO as fixed regulator;
>  b) present PD & Reset GPIOs as regulator;
>  c) provide them as is to the sensor and sensor driver must do what it
> considers right.
>
> Since we don't have schematics (yet?) and we have plenty of variations
> of sensors, I would go to c) and update the driver of the affected
> sensor as needed. Because even if you have separate discrete PD for
> one sensor on one platform there is no guarantee that it will be the
> same on another. Providing a "virtual" PD in a sensor that doesn't
> support it is the best choice I think. Let's hear what Sakari and
> other experienced camera sensor developers say.
>
> My vision is purely based on electrical engineering background,
> experience with existing (not exactly camera) sensor drivers and
> generic cases.

Alright; thanks. I'm happy with C being the answer, so unless someone
thinks differently I'll work on that basis.

>> Failing that; the only way I can think to handle this is to register
>> proxy GPIO pins assigned to the sensors as you suggested previously, and
>> have them toggle the GPIO's assigned to the INT3472 based on platform
>> specific mapping data (I.E. we register a pin called "reset", which on
>> most platforms just toggles the 0x00 pin, but on this specific platform
>> would drive both 0x00 and 0x01 together. We're already heading that way
>> for the regulator consumer supplies so it's sort of nothing new, but I'd
>> still rather not if it can be avoided.
>

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2021-01-08 12:17       ` Andy Shevchenko
  2021-01-08 23:24         ` Daniel Scally
@ 2021-01-09  0:18         ` Laurent Pinchart
  2021-01-09  0:39           ` Daniel Scally
  1 sibling, 1 reply; 144+ messages in thread
From: Laurent Pinchart @ 2021-01-09  0:18 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Daniel Scally, Andy Shevchenko, Linux Kernel Mailing List,
	ACPI Devel Maling List, open list:GPIO SUBSYSTEM, linux-i2c,
	Linux Media Mailing List, devel, Rafael J. Wysocki, Len Brown,
	Greg Kroah-Hartman, Mika Westerberg, Linus Walleij,
	Bartosz Golaszewski, Wolfram Sang, Yong Zhi, Sakari Ailus,
	Bingbu Cao, Tian Shu Qiu, Mauro Carvalho Chehab, Robert Moore,
	Erik Kaneda, Petr Mladek, Steven Rostedt, Sergey Senozhatsky,
	Rasmus Villemoes, kieran.bingham+renesas, Jacopo Mondi,
	Laurent Pinchart, Jordan Hand, Tsuchiya Yuto, Krogerus, Heikki

H Andy and Daniel,

On Fri, Jan 08, 2021 at 02:17:49PM +0200, Andy Shevchenko wrote:
> On Fri, Jan 8, 2021 at 1:56 AM Daniel Scally wrote:
> > On 30/11/2020 20:07, Andy Shevchenko wrote:
> > > On Mon, Nov 30, 2020 at 01:31:29PM +0000, Daniel Scally wrote:
> 
> ...
> 
> > > It's solely Windows driver design...
> > > Luckily I found some information and can clarify above table:
> > >
> > > 0x00 Reset
> > > 0x01 Power down
> > > 0x0b Power enable
> > > 0x0c Clock enable
> > > 0x0d LED (active high)
> > >
> > > The above text perhaps should go somewhere under Documentation.
> >
> > Coming back to this; there's a bit of an anomaly with the 0x01 Power
> > Down pin for at least one platform.  As listed above, the OV2680 on one
> > of my platforms has 3 GPIOs defined, and the table above gives them as
> > type Reset, Power down and Clock enable. I'd assumed from this table
> > that "power down" meant a powerdown GPIO (I.E. the one usually called
> > PWDNB in Omnivision datasheets and "powerdown" in drivers), but the
> > datasheet for the OV2680 doesn't list a separate reset and powerdown
> > pin, but rather a single pin that performs both functions.

First question, do we have a confirmation that the OV2680 sensor on that
platform requires GPIO 0x01 to be toggled to work properly ? I'd like to
rule out the option of the GPIO being simply not connected (that would
be best for us, although my experience so far with this terrible ACPI
design doesn't of course give me much hope).

Where did you find the OV2680 datasheet by the way, can you share a link
to a leaked version ?

> All of them are GPIOs, the question here is how they are actually
> connected on PCB level and I have no answer to that. You have to find
> schematics somewhere.
> 
> > Am I wrong to treat that as something that ought to be mapped as a
> > powerdown GPIO to the sensors? Or do you know of any other way to
> > reconcile that discrepancy?
> 
> The GPIOs can go directly to the sensors or be a control pin for
> separate discrete power gates.

GPIO functions 0x00 and 0x01 are meant to control sensor signals, while
GPIO function 0x0b is meant to control a power gate. Of course board
designers may have thought clever to use function 0x01 to control a
second power gate, this can't be ruled out without the schematics (or
reverse engineering of the hardware).

> So, we can do one of the following:
>  a) present PD GPIO as fixed regulator;
>  b) present PD & Reset GPIOs as regulator;
>  c) provide them as is to the sensor and sensor driver must do what it
> considers right.
> 
> Since we don't have schematics (yet?) and we have plenty of variations
> of sensors, I would go to c) and update the driver of the affected
> sensor as needed. Because even if you have separate discrete PD for
> one sensor on one platform there is no guarantee that it will be the
> same on another. Providing a "virtual" PD in a sensor that doesn't
> support it is the best choice I think. Let's hear what Sakari and
> other experienced camera sensor developers say.
> 
> My vision is purely based on electrical engineering background,
> experience with existing (not exactly camera) sensor drivers and
> generic cases.

If the OV2680 has indeed no power down pin, that won't work. Adding
support for a non-existent powerdown pin to the corresponding driver
won't be accepted. Workarounds and hacks to support IPU3-based devices
need to be kept out of camera sensor drivers.

If we need to map GPIO function 0x01 to a sensor GPIO on some platform,
and to a regulator on other platforms, then we will need per-platform
data in the INT3472 driver. For this particular platform, the reset
(0x00) GPIO should be passed to the sensor, and the powerdown (0x01)
GPIO should control a regulator (again assuming that our assumption that
the GPIO is wired to a power gate is correct).

> > Failing that; the only way I can think to handle this is to register
> > proxy GPIO pins assigned to the sensors as you suggested previously, and
> > have them toggle the GPIO's assigned to the INT3472 based on platform
> > specific mapping data (I.E. we register a pin called "reset", which on
> > most platforms just toggles the 0x00 pin, but on this specific platform
> > would drive both 0x00 and 0x01 together. We're already heading that way
> > for the regulator consumer supplies so it's sort of nothing new, but I'd
> > still rather not if it can be avoided.

-- 
Regards,

Laurent Pinchart

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
  2021-01-09  0:18         ` Laurent Pinchart
@ 2021-01-09  0:39           ` Daniel Scally
  0 siblings, 0 replies; 144+ messages in thread
From: Daniel Scally @ 2021-01-09  0:39 UTC (permalink / raw)
  To: Laurent Pinchart, Andy Shevchenko
  Cc: Andy Shevchenko, Linux Kernel Mailing List,
	ACPI Devel Maling List, open list:GPIO SUBSYSTEM, linux-i2c,
	Linux Media Mailing List, devel, Rafael J. Wysocki, Len Brown,
	Greg Kroah-Hartman, Mika Westerberg, Linus Walleij,
	Bartosz Golaszewski, Wolfram Sang, Yong Zhi, Sakari Ailus,
	Bingbu Cao, Tian Shu Qiu, Mauro Carvalho Chehab, Robert Moore,
	Erik Kaneda, Petr Mladek, Steven Rostedt, Sergey Senozhatsky,
	Rasmus Villemoes, kieran.bingham+renesas, Jacopo Mondi,
	Laurent Pinchart, Jordan Hand, Tsuchiya Yuto, Krogerus, Heikki

Hi Laurent

On 09/01/2021 00:18, Laurent Pinchart wrote:
> H Andy and Daniel,
>
> On Fri, Jan 08, 2021 at 02:17:49PM +0200, Andy Shevchenko wrote:
>> On Fri, Jan 8, 2021 at 1:56 AM Daniel Scally wrote:
>>> On 30/11/2020 20:07, Andy Shevchenko wrote:
>>>> On Mon, Nov 30, 2020 at 01:31:29PM +0000, Daniel Scally wrote:
>> ...
>>
>>>> It's solely Windows driver design...
>>>> Luckily I found some information and can clarify above table:
>>>>
>>>> 0x00 Reset
>>>> 0x01 Power down
>>>> 0x0b Power enable
>>>> 0x0c Clock enable
>>>> 0x0d LED (active high)
>>>>
>>>> The above text perhaps should go somewhere under Documentation.
>>> Coming back to this; there's a bit of an anomaly with the 0x01 Power
>>> Down pin for at least one platform.  As listed above, the OV2680 on one
>>> of my platforms has 3 GPIOs defined, and the table above gives them as
>>> type Reset, Power down and Clock enable. I'd assumed from this table
>>> that "power down" meant a powerdown GPIO (I.E. the one usually called
>>> PWDNB in Omnivision datasheets and "powerdown" in drivers), but the
>>> datasheet for the OV2680 doesn't list a separate reset and powerdown
>>> pin, but rather a single pin that performs both functions.
> First question, do we have a confirmation that the OV2680 sensor on that
> platform requires GPIO 0x01 to be toggled to work properly ?

Yes; without that toggled not even the i2c interface is available.

> I'd like to
> rule out the option of the GPIO being simply not connected (that would
> be best for us, although my experience so far with this terrible ACPI
> design doesn't of course give me much hope).
Sorry to dash what little hope was left.
> Where did you find the OV2680 datasheet by the way, can you share a link
> to a leaked version ?
Sure. I left the PC already, but I'll do that tomorrow.
>> All of them are GPIOs, the question here is how they are actually
>> connected on PCB level and I have no answer to that. You have to find
>> schematics somewhere.
>>
>>> Am I wrong to treat that as something that ought to be mapped as a
>>> powerdown GPIO to the sensors? Or do you know of any other way to
>>> reconcile that discrepancy?
>> The GPIOs can go directly to the sensors or be a control pin for
>> separate discrete power gates.
> GPIO functions 0x00 and 0x01 are meant to control sensor signals, while
> GPIO function 0x0b is meant to control a power gate. Of course board
> designers may have thought clever to use function 0x01 to control a
> second power gate, this can't be ruled out without the schematics (or
> reverse engineering of the hardware).
>
>> So, we can do one of the following:
>>  a) present PD GPIO as fixed regulator;
>>  b) present PD & Reset GPIOs as regulator;
>>  c) provide them as is to the sensor and sensor driver must do what it
>> considers right.
>>
>> Since we don't have schematics (yet?) and we have plenty of variations
>> of sensors, I would go to c) and update the driver of the affected
>> sensor as needed. Because even if you have separate discrete PD for
>> one sensor on one platform there is no guarantee that it will be the
>> same on another. Providing a "virtual" PD in a sensor that doesn't
>> support it is the best choice I think. Let's hear what Sakari and
>> other experienced camera sensor developers say.
>>
>> My vision is purely based on electrical engineering background,
>> experience with existing (not exactly camera) sensor drivers and
>> generic cases.
> If the OV2680 has indeed no power down pin, that won't work. Adding
> support for a non-existent powerdown pin to the corresponding driver
> won't be accepted. Workarounds and hacks to support IPU3-based devices
> need to be kept out of camera sensor drivers.
>
> If we need to map GPIO function 0x01 to a sensor GPIO on some platform,
> and to a regulator on other platforms, then we will need per-platform
> data in the INT3472 driver. For this particular platform, the reset
> (0x00) GPIO should be passed to the sensor, and the powerdown (0x01)
> GPIO should control a regulator (again assuming that our assumption that
> the GPIO is wired to a power gate is correct).
Let me think of a neat way to do this then.
>
>>> Failing that; the only way I can think to handle this is to register
>>> proxy GPIO pins assigned to the sensors as you suggested previously, and
>>> have them toggle the GPIO's assigned to the INT3472 based on platform
>>> specific mapping data (I.E. we register a pin called "reset", which on
>>> most platforms just toggles the 0x00 pin, but on this specific platform
>>> would drive both 0x00 and 0x01 together. We're already heading that way
>>> for the regulator consumer supplies so it's sort of nothing new, but I'd
>>> still rather not if it can be avoided.

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

* Re: [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device
       [not found]           ` <CAHp75Vcy878xKUUUDH5ory9uS-Vhhx_W1PZc=S6hsSLYJ0i60w@mail.gmail.com>
@ 2021-01-09  9:58             ` Daniel Scally
  0 siblings, 0 replies; 144+ messages in thread
From: Daniel Scally @ 2021-01-09  9:58 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Andy Shevchenko, Linux Kernel Mailing List,
	ACPI Devel Maling List, open list:GPIO SUBSYSTEM, linux-i2c,
	Linux Media Mailing List, devel, Rafael J. Wysocki, Len Brown,
	Greg Kroah-Hartman, Mika Westerberg, Linus Walleij,
	Bartosz Golaszewski, Wolfram Sang, Yong Zhi, Sakari Ailus,
	Bingbu Cao, Tian Shu Qiu, Mauro Carvalho Chehab, Robert Moore,
	Erik Kaneda, Petr Mladek, Steven Rostedt, Sergey Senozhatsky,
	Rasmus Villemoes, kieran.bingham+renesas, Jacopo Mondi,
	Laurent Pinchart, Jordan Hand, Tsuchiya Yuto, Krogerus, Heikki,
	Laurent Pinchart


On 09/01/2021 09:17, Andy Shevchenko wrote:
> On Saturday, January 9, 2021, Daniel Scally <djrscally@gmail.com> wrote:
>
>> Hi Andy
>>
>> On 08/01/2021 12:17, Andy Shevchenko wrote:
>>> On Fri, Jan 8, 2021 at 1:56 AM Daniel Scally <djrscally@gmail.com>
>> wrote:
>>>> On 30/11/2020 20:07, Andy Shevchenko wrote:
>>>>> On Mon, Nov 30, 2020 at 01:31:29PM +0000, Daniel Scally wrote:
>>> ...
>>>
>>>>> It's solely Windows driver design...
>>>>> Luckily I found some information and can clarify above table:
>>>>>
>>>>> 0x00 Reset
>>>>> 0x01 Power down
>>>>> 0x0b Power enable
>>>>> 0x0c Clock enable
>>>>> 0x0d LED (active high)
>>>>>
>>>>> The above text perhaps should go somewhere under Documentation.
>>>> Coming back to this; there's a bit of an anomaly with the 0x01 Power
>>>> Down pin for at least one platform.  As listed above, the OV2680 on one
>>>> of my platforms has 3 GPIOs defined, and the table above gives them as
>>>> type Reset, Power down and Clock enable. I'd assumed from this table
>>>> that "power down" meant a powerdown GPIO (I.E. the one usually called
>>>> PWDNB in Omnivision datasheets and "powerdown" in drivers), but the
>>>> datasheet for the OV2680 doesn't list a separate reset and powerdown
>>>> pin, but rather a single pin that performs both functions.
>>> All of them are GPIOs, the question here is how they are actually
>>> connected on PCB level and I have no answer to that. You have to find
>>> schematics somewhere.
>> Yeah; I've been trying to get those but so far, no dice.
>>
>>
> Can you share the exact name / model of the hardware in question here? I
> would try to search for the schematics.
Lenovo Miix 510-12ISK 80U1 - I also tried asking Lenovo for them but
that didn't really go anywhere; but of course I'm just contacting their
usual support line and explaining what I'm after, so I didn't really
expect it to.
>
>
>>>> Am I wrong to treat that as something that ought to be mapped as a
>>>> powerdown GPIO to the sensors? Or do you know of any other way to
>>>> reconcile that discrepancy?
>>> The GPIOs can go directly to the sensors or be a control pin for
>>> separate discrete power gates.
>>> So, we can do one of the following:
>>>  a) present PD GPIO as fixed regulator;
>>>  b) present PD & Reset GPIOs as regulator;
>>>  c) provide them as is to the sensor and sensor driver must do what it
>>> considers right.
>>>
>>> Since we don't have schematics (yet?) and we have plenty of variations
>>> of sensors, I would go to c) and update the driver of the affected
>>> sensor as needed. Because even if you have separate discrete PD for
>>> one sensor on one platform there is no guarantee that it will be the
>>> same on another. Providing a "virtual" PD in a sensor that doesn't
>>> support it is the best choice I think. Let's hear what Sakari and
>>> other experienced camera sensor developers say.
>>>
>>> My vision is purely based on electrical engineering background,
>>> experience with existing (not exactly camera) sensor drivers and
>>> generic cases.
>> Alright; thanks. I'm happy with C being the answer, so unless someone
>> thinks differently I'll work on that basis.
>>
>>
> Laurent answered that it is not the best choice from camera sensor driver
> perspective.
Yep, seen - no problem. I will look at doing it via the method he suggests.

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

end of thread, other threads:[~2021-01-09  9:59 UTC | newest]

Thread overview: 144+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-30 13:31 [PATCH 00/18] Add functionality to ipu3-cio2 driver allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
2020-11-30 13:31 ` [PATCH 01/18] property: Return true in fwnode_device_is_available for node types that do not implement this operation Daniel Scally
2020-11-30 16:05   ` Laurent Pinchart
2020-11-30 17:21   ` Andy Shevchenko
2020-12-01  3:12   ` Bingbu Cao
2020-12-01  8:46     ` Dan Scally
2020-11-30 13:31 ` [PATCH 02/18] property: Add support for calling fwnode_graph_get_endpoint_by_id() for fwnode->secondary Daniel Scally
2020-11-30 16:08   ` Laurent Pinchart
2020-11-30 17:29   ` Andy Shevchenko
2020-11-30 17:28     ` Laurent Pinchart
2020-11-30 17:53       ` Andy Shevchenko
2020-11-30 18:41         ` Laurent Pinchart
2020-11-30 19:21           ` Andy Shevchenko
2020-12-02 10:13     ` Dan Scally
2020-11-30 13:31 ` [PATCH 03/18] software_node: Fix failure to put() and get() references to children in software_node_get_next_child() Daniel Scally
2020-11-30 16:10   ` Laurent Pinchart
2020-11-30 17:30   ` Andy Shevchenko
2020-11-30 13:31 ` [PATCH 04/18] software_node: Enforce parent before child ordering of nodes array for software_node_register_nodes() Daniel Scally
2020-11-30 16:11   ` Laurent Pinchart
2020-11-30 16:12     ` Laurent Pinchart
2020-11-30 23:10       ` Dan Scally
2020-11-30 17:35   ` Andy Shevchenko
2020-11-30 17:37     ` Andy Shevchenko
2020-11-30 13:31 ` [PATCH 05/18] software_node: Alter software_node_unregister_nodes() to unregister the array in reverse order Daniel Scally
2020-11-30 16:14   ` Laurent Pinchart
2020-11-30 17:45   ` Andy Shevchenko
2020-12-01 23:36     ` Dan Scally
2020-11-30 13:31 ` [PATCH 06/18] software_node: amend software_node_unregister_node_group() to perform unregistration of array in reverse order to be consistent with software_node_unregister_nodes() Daniel Scally
2020-11-30 16:17   ` Laurent Pinchart
2020-11-30 17:47     ` Andy Shevchenko
2020-12-02 10:04       ` Dan Scally
2020-11-30 17:19   ` kernel test robot
2020-12-01 18:18   ` Dan Carpenter
2020-11-30 13:31 ` [PATCH 07/18] software_node: Add support for fwnode_graph*() family of functions Daniel Scally
2020-11-30 16:25   ` Laurent Pinchart
2020-11-30 23:34     ` Dan Scally
2020-11-30 13:31 ` [PATCH 08/18] lib/test_printf.c: Use helper function to unwind array of software_nodes Daniel Scally
2020-11-30 15:54   ` Sergey Senozhatsky
2020-11-30 16:26   ` Laurent Pinchart
2020-11-30 13:31 ` [PATCH 09/18] ipu3-cio2: Add T: entry to MAINTAINERS Daniel Scally
2020-11-30 13:31 ` [PATCH 10/18] ipu3-cio2: Rename ipu3-cio2.c to allow module to be built from multiple source files retaining ipu3-cio2 name Daniel Scally
2020-12-01  6:56   ` Bingbu Cao
2020-12-01  7:07     ` Bingbu Cao
2020-11-30 13:31 ` [PATCH 11/18] media: v4l2-core: v4l2-async: Check possible match in match_fwnode based on sd->fwnode->secondary Daniel Scally
2020-11-30 16:27   ` Laurent Pinchart
2020-11-30 17:55   ` Andy Shevchenko
2020-11-30 13:31 ` [PATCH 12/18] acpi: Add acpi_dev_get_next_match_dev() and macro to iterate through acpi_devices matching a given _HID Daniel Scally
2020-11-30 17:58   ` Andy Shevchenko
2020-11-30 13:31 ` [PATCH 13/18] ipu3-cio2: Add functionality allowing software_node connections to sensors on platforms designed for Windows Daniel Scally
2020-11-30 16:45   ` kernel test robot
2020-11-30 17:09   ` Laurent Pinchart
2020-11-30 18:14     ` Andy Shevchenko
2020-12-01 22:08     ` Dan Scally
2020-12-01 22:11       ` Dan Scally
2020-12-01 22:30       ` Laurent Pinchart
2020-12-01 23:15         ` Dan Scally
2020-12-02 10:38         ` Sakari Ailus
2020-12-02 10:53           ` Dan Scally
2020-12-02 12:02             ` Andy Shevchenko
2020-12-02 22:44               ` Dan Scally
2020-12-02 12:01           ` Andy Shevchenko
2020-11-30 20:27   ` kernel test robot
2020-11-30 20:35   ` Sakari Ailus
2020-12-01  8:13     ` Dan Scally
2020-12-01 15:06     ` Andy Shevchenko
2020-12-15 10:28     ` Daniel Scally
2020-12-15 10:32       ` Daniel Scally
2020-12-15 22:02       ` Sakari Ailus
2020-12-17 14:17         ` Daniel Scally
2020-11-30 13:31 ` [PATCH 14/18] acpi: utils: Add function to fetch dependent acpi_devices Daniel Scally
2020-11-30 18:23   ` Andy Shevchenko
2020-11-30 18:40     ` Laurent Pinchart
2020-11-30 23:54     ` Dan Scally
2020-12-01 15:10       ` Andy Shevchenko
2020-12-01 15:23         ` Dan Scally
2020-11-30 13:31 ` [PATCH 15/18] i2c: i2c-core-acpi: Add i2c_acpi_dev_name() Daniel Scally
2020-11-30 17:11   ` Laurent Pinchart
2020-12-02 22:44     ` Dan Scally
2020-11-30 13:31 ` [PATCH 16/18] i2c: i2c-core-base: Use the new i2c_acpi_dev_name() in i2c_set_dev_name() Daniel Scally
2020-11-30 17:12   ` Laurent Pinchart
2020-11-30 19:18     ` Andy Shevchenko
2020-12-02  9:35       ` Andy Shevchenko
2020-12-02  9:49         ` Dan Scally
2020-12-01 23:50     ` Dan Scally
2020-11-30 13:31 ` [PATCH 17/18] gpio: gpiolib-acpi: Export acpi_get_gpiod() Daniel Scally
2020-11-30 17:02   ` kernel test robot
2020-11-30 18:04   ` kernel test robot
2020-11-30 19:20   ` Andy Shevchenko
2020-11-30 13:31 ` [PATCH 18/18] ipu3: Add driver for dummy INT3472 ACPI device Daniel Scally
2020-11-30 16:17   ` Jean-Michel Hautbois
2020-11-30 23:20     ` Dan Scally
2020-12-01 18:31       ` Andy Shevchenko
2020-12-01 18:36         ` Laurent Pinchart
2020-12-01 18:51           ` Andy Shevchenko
2020-11-30 16:29   ` Kieran Bingham
2020-11-30 17:21     ` Laurent Pinchart
2020-11-30 20:07   ` Andy Shevchenko
2020-11-30 23:32     ` Laurent Pinchart
2020-12-01 15:55       ` Sakari Ailus
2020-12-01 18:37         ` Laurent Pinchart
2020-12-02 11:09           ` Sakari Ailus
2020-12-02 12:42             ` Laurent Pinchart
2020-12-02 15:08               ` Andy Shevchenko
2020-12-03 12:37                 ` Dan Scally
2020-12-03 12:57                   ` Andy Shevchenko
2020-12-01 18:49       ` Andy Shevchenko
2020-12-01 20:59         ` Dan Scally
2020-12-02  9:39           ` Andy Shevchenko
2020-12-02 12:35             ` Laurent Pinchart
2020-12-02 15:11               ` Andy Shevchenko
2020-12-03 12:25             ` Dan Scally
2020-12-13 22:48         ` Daniel Scally
2020-12-14 15:33           ` Andy Shevchenko
2020-12-01  8:30     ` Dan Scally
2020-12-01 18:54       ` Andy Shevchenko
2020-12-01 18:55         ` Laurent Pinchart
2020-12-01 19:05           ` Andy Shevchenko
2020-12-01 19:06             ` Laurent Pinchart
2020-12-01 19:21               ` Andy Shevchenko
2020-12-01 20:34                 ` Hans de Goede
2020-12-01 20:46                   ` Andy Shevchenko
2020-12-02 12:48                   ` Laurent Pinchart
2020-12-02 15:15                     ` Andy Shevchenko
2020-12-01 21:05                 ` Dan Scally
2020-12-02  9:42                   ` Andy Shevchenko
2021-01-07 23:55     ` Daniel Scally
2021-01-08 12:17       ` Andy Shevchenko
2021-01-08 23:24         ` Daniel Scally
     [not found]           ` <CAHp75Vcy878xKUUUDH5ory9uS-Vhhx_W1PZc=S6hsSLYJ0i60w@mail.gmail.com>
2021-01-09  9:58             ` Daniel Scally
2021-01-09  0:18         ` Laurent Pinchart
2021-01-09  0:39           ` Daniel Scally
2020-11-30 20:52   ` Sakari Ailus
2020-11-30 23:06     ` Dan Scally
2020-11-30 23:21       ` Laurent Pinchart
2020-12-01  0:05         ` Dan Scally
2020-12-01  6:44       ` Sakari Ailus
2020-12-01  8:08         ` Dan Scally
2020-12-01  8:09           ` Dan Scally
2020-12-01 12:32           ` Sakari Ailus
2020-12-01 12:40             ` Laurent Pinchart
2020-12-01 12:44               ` Sakari Ailus
2020-12-01 12:48             ` Dan Scally
2020-12-01 19:01               ` Andy Shevchenko
2020-12-01 18:55       ` Andy Shevchenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).