Browse Source

Update v5.17 patches

Changes:
- Add auto-focus support for world-facing camera (@djrscally)
  - PR: https://github.com/linux-surface/kernel/pull/123
- Refactor Surface Aggregator subsystem device hubs

Links:
- kernel: https://github.com/linux-surface/kernel/commit/6ea3d62a89031365d8de81d21e20e50055192ac5
Maximilian Luz 3 năm trước cách đây
mục cha
commit
d04a703366

+ 382 - 173
patches/5.17/0005-surface-sam.patch

@@ -1,4 +1,4 @@
-From bf1eb62319be3db94fbf1551573c77528c246bff Mon Sep 17 00:00:00 2001
+From 00d3f4cffd80269b24fa25939d8bbac2e0536524 Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Tue, 8 Jun 2021 00:24:47 +0200
 Subject: [PATCH] platform/surface: aggregator: Allow devices to be marked as
@@ -119,7 +119,7 @@ index cc257097eb05..491aa7e9f4bc 100644
 -- 
 2.36.0
 
-From 199fd2d3b2df873f050b823804808003de75d930 Mon Sep 17 00:00:00 2001
+From 495bbba942257acc0892bb6c4ce5d09aa086c314 Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Tue, 8 Jun 2021 00:48:22 +0200
 Subject: [PATCH] platform/surface: aggregator: Allow notifiers to avoid
@@ -406,7 +406,7 @@ index 491aa7e9f4bc..16816c34da3e 100644
 -- 
 2.36.0
 
-From 09733bcaf64f287574617a7fd785555490fc069c Mon Sep 17 00:00:00 2001
+From e1d5f7e9cbc68f580ca6ecdbabd08ba930811cee Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Tue, 8 Jun 2021 01:20:49 +0200
 Subject: [PATCH] platform/surface: aggregator_registry: Use client device
@@ -455,7 +455,7 @@ index ce2bd88feeaa..9f630e890ff7 100644
 -- 
 2.36.0
 
-From 7e093dcab6d846b0dd8bde20ac3cbbf33464385b Mon Sep 17 00:00:00 2001
+From 74eb9b767fd8be1ef6982918137e5d89b28eb61f Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Thu, 28 Oct 2021 03:37:06 +0200
 Subject: [PATCH] power/supply: surface_charger: Use client device wrappers for
@@ -495,7 +495,7 @@ index a060c36c7766..59182d55742d 100644
 -- 
 2.36.0
 
-From 0596f79e4fc188631bdddb9d2e7b91c1203187e2 Mon Sep 17 00:00:00 2001
+From f01bfa451a11c294f1ceb55e99556d528a3e1b93 Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Thu, 28 Oct 2021 03:38:09 +0200
 Subject: [PATCH] power/supply: surface_battery: Use client device wrappers for
@@ -535,7 +535,7 @@ index 5ec2e6bb2465..540707882bb0 100644
 -- 
 2.36.0
 
-From 7ac8a5db2df06cfdc4af31266c7f57c0972eb096 Mon Sep 17 00:00:00 2001
+From 14f1357286128b7e6be3d8405e6ffee9ab5a8d64 Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Tue, 8 Jun 2021 01:33:02 +0200
 Subject: [PATCH] HID: surface-hid: Add support for hot-removal
@@ -646,7 +646,7 @@ index e46330b2e561..87637f813de2 100644
 -- 
 2.36.0
 
-From fe21a8dfcc86dbfe0f5fc9bdf0fa7dee09d45862 Mon Sep 17 00:00:00 2001
+From 995ea86ebc23247bb4c70744add70654b1db7832 Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Sun, 31 Oct 2021 12:34:08 +0100
 Subject: [PATCH] platform/surface: aggregator: Add comment for KIP subsystem
@@ -684,9 +684,362 @@ index c3de43edcffa..d1efac85caf1 100644
 -- 
 2.36.0
 
-From 489d63cb6d02eecc0a986dac9f056fb488318dfa Mon Sep 17 00:00:00 2001
+From 37fe46bc50ae8bc110375ae3e70111b0975780e5 Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
-Date: Sun, 10 Oct 2021 23:56:23 +0200
+Date: Fri, 29 Apr 2022 22:42:32 +0200
+Subject: [PATCH] platform/surface: aggregator_registry: Generify subsystem hub
+ functionality
+
+The Surface System Aggregator Module (SSAM) has multiple subsystems that
+can manage detachable devices. At the moment, we only support the "base"
+(BAS/0x11) subsystem, which is used on the Surface Book 3 to manage
+devices (including keyboard, touchpad, and secondary battery) connected
+to the base of the device.
+
+The Surface Pro 8 has a new type-cover with keyboard and touchpad, which
+is managed via the KIP/0x0e subsystem. The general procedure is the
+same, but with slightly different events and setup. To make
+implementation of the KIP hub easier and prevent duplication, generify
+the parts of the base hub that we can use for the KIP hub (or any
+potential future subsystem hubs).
+
+This also switches over to use the newly introduced "hot-remove"
+functionality, which should prevent communication issues when devices
+have been detached.
+
+Lastly, also drop the undocumented and unused sysfs "state" attribute of
+the base hub. It's at best useful for debugging.
+
+Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
+Patchset: surface-sam
+---
+ .../surface/surface_aggregator_registry.c     | 236 +++++++++---------
+ 1 file changed, 119 insertions(+), 117 deletions(-)
+
+diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
+index 9f630e890ff7..fadfaf4eb6e9 100644
+--- a/drivers/platform/surface/surface_aggregator_registry.c
++++ b/drivers/platform/surface/surface_aggregator_registry.c
+@@ -308,30 +308,124 @@ static int ssam_hub_register_clients(struct device *parent, struct ssam_controll
+ }
+ 
+ 
+-/* -- SSAM base-hub driver. ------------------------------------------------- */
+-
+-/*
+- * Some devices (especially battery) may need a bit of time to be fully usable
+- * after being (re-)connected. This delay has been determined via
+- * experimentation.
+- */
+-#define SSAM_BASE_UPDATE_CONNECT_DELAY		msecs_to_jiffies(2500)
++/* -- SSAM generic subsystem hub driver framework. -------------------------- */
+ 
+-enum ssam_base_hub_state {
+-	SSAM_BASE_HUB_UNINITIALIZED,
+-	SSAM_BASE_HUB_CONNECTED,
+-	SSAM_BASE_HUB_DISCONNECTED,
++enum ssam_hub_state {
++	SSAM_HUB_UNINITIALIZED,
++	SSAM_HUB_CONNECTED,
++	SSAM_HUB_DISCONNECTED,
+ };
+ 
+-struct ssam_base_hub {
++struct ssam_hub {
+ 	struct ssam_device *sdev;
+ 
+-	enum ssam_base_hub_state state;
++	enum ssam_hub_state state;
+ 	struct delayed_work update_work;
++	unsigned long connect_delay;
+ 
+ 	struct ssam_event_notifier notif;
++
++	int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
+ };
+ 
++static void ssam_hub_update_workfn(struct work_struct *work)
++{
++	struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
++	struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
++	enum ssam_hub_state state;
++	int status = 0;
++
++	status = hub->get_state(hub, &state);
++	if (status)
++		return;
++
++	if (hub->state == state)
++		return;
++	hub->state = state;
++
++	if (hub->state == SSAM_HUB_CONNECTED)
++		status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
++	else
++		ssam_remove_clients(&hub->sdev->dev);
++
++	if (status)
++		dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status);
++}
++
++static int ssam_hub_mark_hot_removed(struct device *dev, void *_data)
++{
++	struct ssam_device *sdev = to_ssam_device(dev);
++
++	if (is_ssam_device(dev))
++		ssam_device_mark_hot_removed(sdev);
++
++	return 0;
++}
++
++static void ssam_hub_update(struct ssam_hub *hub, bool connected)
++{
++	unsigned long delay;
++
++	/* Mark devices as hot-removed before we remove any */
++	if (!connected)
++		device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed);
++
++	/*
++	 * Delay update when the base/keyboard cover is being connected to give
++	 * devices/EC some time to set up.
++	 */
++	delay = connected ? hub->connect_delay : 0;
++
++	schedule_delayed_work(&hub->update_work, delay);
++}
++
++static int __maybe_unused ssam_hub_resume(struct device *dev)
++{
++	struct ssam_hub *hub = dev_get_drvdata(dev);
++
++	schedule_delayed_work(&hub->update_work, 0);
++	return 0;
++}
++static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume);
++
++static int ssam_hub_setup(struct ssam_device *sdev, struct ssam_hub *hub)
++{
++	int status;
++
++	hub->sdev = sdev;
++	hub->state = SSAM_HUB_UNINITIALIZED;
++
++	INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn);
++
++	ssam_device_set_drvdata(sdev, hub);
++
++	status = ssam_device_notifier_register(sdev, &hub->notif);
++	if (status)
++		return status;
++
++	schedule_delayed_work(&hub->update_work, 0);
++	return 0;
++}
++
++static void ssam_hub_remove(struct ssam_device *sdev)
++{
++	struct ssam_hub *hub = ssam_device_get_drvdata(sdev);
++
++	ssam_device_notifier_unregister(sdev, &hub->notif);
++	cancel_delayed_work_sync(&hub->update_work);
++	ssam_remove_clients(&sdev->dev);
++}
++
++
++/* -- SSAM base-hub driver. ------------------------------------------------- */
++
++/*
++ * Some devices (especially battery) may need a bit of time to be fully usable
++ * after being (re-)connected. This delay has been determined via
++ * experimentation.
++ */
++#define SSAM_BASE_UPDATE_CONNECT_DELAY		msecs_to_jiffies(2500)
++
+ SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
+ 	.target_category = SSAM_SSH_TC_BAS,
+ 	.target_id       = 0x01,
+@@ -342,7 +436,7 @@ SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
+ #define SSAM_BAS_OPMODE_TABLET		0x00
+ #define SSAM_EVENT_BAS_CID_CONNECTION	0x0c
+ 
+-static int ssam_base_hub_query_state(struct ssam_base_hub *hub, enum ssam_base_hub_state *state)
++static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
+ {
+ 	u8 opmode;
+ 	int status;
+@@ -354,62 +448,16 @@ static int ssam_base_hub_query_state(struct ssam_base_hub *hub, enum ssam_base_h
+ 	}
+ 
+ 	if (opmode != SSAM_BAS_OPMODE_TABLET)
+-		*state = SSAM_BASE_HUB_CONNECTED;
++		*state = SSAM_HUB_CONNECTED;
+ 	else
+-		*state = SSAM_BASE_HUB_DISCONNECTED;
++		*state = SSAM_HUB_DISCONNECTED;
+ 
+ 	return 0;
+ }
+ 
+-static ssize_t ssam_base_hub_state_show(struct device *dev, struct device_attribute *attr,
+-					char *buf)
+-{
+-	struct ssam_base_hub *hub = dev_get_drvdata(dev);
+-	bool connected = hub->state == SSAM_BASE_HUB_CONNECTED;
+-
+-	return sysfs_emit(buf, "%d\n", connected);
+-}
+-
+-static struct device_attribute ssam_base_hub_attr_state =
+-	__ATTR(state, 0444, ssam_base_hub_state_show, NULL);
+-
+-static struct attribute *ssam_base_hub_attrs[] = {
+-	&ssam_base_hub_attr_state.attr,
+-	NULL,
+-};
+-
+-static const struct attribute_group ssam_base_hub_group = {
+-	.attrs = ssam_base_hub_attrs,
+-};
+-
+-static void ssam_base_hub_update_workfn(struct work_struct *work)
+-{
+-	struct ssam_base_hub *hub = container_of(work, struct ssam_base_hub, update_work.work);
+-	struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
+-	enum ssam_base_hub_state state;
+-	int status = 0;
+-
+-	status = ssam_base_hub_query_state(hub, &state);
+-	if (status)
+-		return;
+-
+-	if (hub->state == state)
+-		return;
+-	hub->state = state;
+-
+-	if (hub->state == SSAM_BASE_HUB_CONNECTED)
+-		status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
+-	else
+-		ssam_remove_clients(&hub->sdev->dev);
+-
+-	if (status)
+-		dev_err(&hub->sdev->dev, "failed to update base-hub devices: %d\n", status);
+-}
+-
+ static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
+ {
+-	struct ssam_base_hub *hub = container_of(nf, struct ssam_base_hub, notif);
+-	unsigned long delay;
++	struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
+ 
+ 	if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION)
+ 		return 0;
+@@ -419,13 +467,7 @@ static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam
+ 		return 0;
+ 	}
+ 
+-	/*
+-	 * Delay update when the base is being connected to give devices/EC
+-	 * some time to set up.
+-	 */
+-	delay = event->data[0] ? SSAM_BASE_UPDATE_CONNECT_DELAY : 0;
+-
+-	schedule_delayed_work(&hub->update_work, delay);
++	ssam_hub_update(hub, event->data[0]);
+ 
+ 	/*
+ 	 * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and
+@@ -435,27 +477,14 @@ static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam
+ 	return 0;
+ }
+ 
+-static int __maybe_unused ssam_base_hub_resume(struct device *dev)
+-{
+-	struct ssam_base_hub *hub = dev_get_drvdata(dev);
+-
+-	schedule_delayed_work(&hub->update_work, 0);
+-	return 0;
+-}
+-static SIMPLE_DEV_PM_OPS(ssam_base_hub_pm_ops, NULL, ssam_base_hub_resume);
+-
+ static int ssam_base_hub_probe(struct ssam_device *sdev)
+ {
+-	struct ssam_base_hub *hub;
+-	int status;
++	struct ssam_hub *hub;
+ 
+ 	hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
+ 	if (!hub)
+ 		return -ENOMEM;
+ 
+-	hub->sdev = sdev;
+-	hub->state = SSAM_BASE_HUB_UNINITIALIZED;
+-
+ 	hub->notif.base.priority = INT_MAX;  /* This notifier should run first. */
+ 	hub->notif.base.fn = ssam_base_hub_notif;
+ 	hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
+@@ -464,37 +493,10 @@ static int ssam_base_hub_probe(struct ssam_device *sdev)
+ 	hub->notif.event.mask = SSAM_EVENT_MASK_NONE;
+ 	hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
+ 
+-	INIT_DELAYED_WORK(&hub->update_work, ssam_base_hub_update_workfn);
+-
+-	ssam_device_set_drvdata(sdev, hub);
+-
+-	status = ssam_device_notifier_register(sdev, &hub->notif);
+-	if (status)
+-		return status;
++	hub->connect_delay = SSAM_BASE_UPDATE_CONNECT_DELAY;
++	hub->get_state = ssam_base_hub_query_state;
+ 
+-	status = sysfs_create_group(&sdev->dev.kobj, &ssam_base_hub_group);
+-	if (status)
+-		goto err;
+-
+-	schedule_delayed_work(&hub->update_work, 0);
+-	return 0;
+-
+-err:
+-	ssam_device_notifier_unregister(sdev, &hub->notif);
+-	cancel_delayed_work_sync(&hub->update_work);
+-	ssam_remove_clients(&sdev->dev);
+-	return status;
+-}
+-
+-static void ssam_base_hub_remove(struct ssam_device *sdev)
+-{
+-	struct ssam_base_hub *hub = ssam_device_get_drvdata(sdev);
+-
+-	sysfs_remove_group(&sdev->dev.kobj, &ssam_base_hub_group);
+-
+-	ssam_device_notifier_unregister(sdev, &hub->notif);
+-	cancel_delayed_work_sync(&hub->update_work);
+-	ssam_remove_clients(&sdev->dev);
++	return ssam_hub_setup(sdev, hub);
+ }
+ 
+ static const struct ssam_device_id ssam_base_hub_match[] = {
+@@ -504,12 +506,12 @@ static const struct ssam_device_id ssam_base_hub_match[] = {
+ 
+ static struct ssam_device_driver ssam_base_hub_driver = {
+ 	.probe = ssam_base_hub_probe,
+-	.remove = ssam_base_hub_remove,
++	.remove = ssam_hub_remove,
+ 	.match_table = ssam_base_hub_match,
+ 	.driver = {
+ 		.name = "surface_aggregator_base_hub",
+ 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+-		.pm = &ssam_base_hub_pm_ops,
++		.pm = &ssam_hub_pm_ops,
+ 	},
+ };
+ 
+-- 
+2.36.0
+
+From 29878abe6a5fd9abb177ca66d5ba618336f3bd1a Mon Sep 17 00:00:00 2001
+From: Maximilian Luz <luzmaximilian@gmail.com>
+Date: Fri, 29 Apr 2022 23:02:06 +0200
 Subject: [PATCH] platform/surface: aggregator_registry: Add KIP device hub
 
 Add a Surface System Aggregator Module (SSAM) client device hub for
@@ -717,14 +1070,14 @@ been (re-)attached.
 Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
 Patchset: surface-sam
 ---
- .../surface/surface_aggregator_registry.c     | 247 +++++++++++++++++-
- 1 file changed, 245 insertions(+), 2 deletions(-)
+ .../surface/surface_aggregator_registry.c     | 103 +++++++++++++++++-
+ 1 file changed, 101 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
-index 9f630e890ff7..4838ce6519a6 100644
+index fadfaf4eb6e9..eb4b55516d3f 100644
 --- a/drivers/platform/surface/surface_aggregator_registry.c
 +++ b/drivers/platform/surface/surface_aggregator_registry.c
-@@ -514,6 +514,237 @@ static struct ssam_device_driver ssam_base_hub_driver = {
+@@ -516,6 +516,93 @@ static struct ssam_device_driver ssam_base_hub_driver = {
  };
  
  
@@ -738,21 +1091,6 @@ index 9f630e890ff7..4838ce6519a6 100644
 +
 +#define SSAM_EVENT_KIP_CID_CONNECTION		0x2c
 +
-+enum ssam_kip_hub_state {
-+	SSAM_KIP_HUB_UNINITIALIZED,
-+	SSAM_KIP_HUB_CONNECTED,
-+	SSAM_KIP_HUB_DISCONNECTED,
-+};
-+
-+struct ssam_kip_hub {
-+	struct ssam_device *sdev;
-+
-+	enum ssam_kip_hub_state state;
-+	struct delayed_work update_work;
-+
-+	struct ssam_event_notifier notif;
-+};
-+
 +SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_connection_state, u8, {
 +	.target_category = SSAM_SSH_TC_KIP,
 +	.target_id       = 0x01,
@@ -760,7 +1098,7 @@ index 9f630e890ff7..4838ce6519a6 100644
 +	.instance_id     = 0x00,
 +});
 +
-+static int ssam_kip_get_connection_state(struct ssam_kip_hub *hub, enum ssam_kip_hub_state *state)
++static int ssam_kip_get_connection_state(struct ssam_hub *hub, enum ssam_hub_state *state)
 +{
 +	int status;
 +	u8 connected;
@@ -771,92 +1109,13 @@ index 9f630e890ff7..4838ce6519a6 100644
 +		return status;
 +	}
 +
-+	*state = connected ? SSAM_KIP_HUB_CONNECTED : SSAM_KIP_HUB_DISCONNECTED;
++	*state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED;
 +	return 0;
 +}
 +
-+static ssize_t ssam_kip_hub_state_show(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+	struct ssam_kip_hub *hub = dev_get_drvdata(dev);
-+	const char *state;
-+
-+	switch (hub->state) {
-+	case SSAM_KIP_HUB_UNINITIALIZED:
-+		state = "uninitialized";
-+		break;
-+
-+	case SSAM_KIP_HUB_CONNECTED:
-+		state = "connected";
-+		break;
-+
-+	case SSAM_KIP_HUB_DISCONNECTED:
-+		state = "disconnected";
-+		break;
-+
-+	default:
-+		/*
-+		 * Any value not handled in the above cases is invalid and
-+		 * should never have been set. Thus this case should be
-+		 * impossible to reach.
-+		 */
-+		WARN(1, "invalid KIP hub state: %d\n", hub->state);
-+		state = "<invalid>";
-+		break;
-+	}
-+
-+	return sysfs_emit(buf, "%s\n", state);
-+}
-+
-+static struct device_attribute ssam_kip_hub_attr_state =
-+	__ATTR(state, 0444, ssam_kip_hub_state_show, NULL);
-+
-+static struct attribute *ssam_kip_hub_attrs[] = {
-+	&ssam_kip_hub_attr_state.attr,
-+	NULL,
-+};
-+
-+static const struct attribute_group ssam_kip_hub_group = {
-+	.attrs = ssam_kip_hub_attrs,
-+};
-+
-+static int ssam_kip_hub_mark_hot_removed(struct device *dev, void *_data)
-+{
-+	struct ssam_device *sdev = to_ssam_device(dev);
-+
-+	if (is_ssam_device(dev))
-+		ssam_device_mark_hot_removed(sdev);
-+
-+	return 0;
-+}
-+
-+static void ssam_kip_hub_update_workfn(struct work_struct *work)
-+{
-+	struct ssam_kip_hub *hub = container_of(work, struct ssam_kip_hub, update_work.work);
-+	struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
-+	enum ssam_kip_hub_state state;
-+	int status = 0;
-+
-+	status = ssam_kip_get_connection_state(hub, &state);
-+	if (status)
-+		return;
-+
-+	if (hub->state == state)
-+		return;
-+	hub->state = state;
-+
-+	if (hub->state == SSAM_KIP_HUB_CONNECTED)
-+		status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
-+	else
-+		ssam_remove_clients(&hub->sdev->dev);
-+
-+	if (status)
-+		dev_err(&hub->sdev->dev, "failed to update KIP-hub devices: %d\n", status);
-+}
-+
 +static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
 +{
-+	struct ssam_kip_hub *hub = container_of(nf, struct ssam_kip_hub, notif);
-+	unsigned long delay;
++	struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
 +
 +	if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION)
 +		return 0;	/* Return "unhandled". */
@@ -866,41 +1125,18 @@ index 9f630e890ff7..4838ce6519a6 100644
 +		return 0;
 +	}
 +
-+	/* Mark devices as hot-removed before we remove any */
-+	if (!event->data[0])
-+		device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_kip_hub_mark_hot_removed);
-+
-+	/*
-+	 * Delay update when KIP devices are being connected to give devices/EC
-+	 * some time to set up.
-+	 */
-+	delay = event->data[0] ? SSAM_KIP_UPDATE_CONNECT_DELAY : 0;
-+
-+	schedule_delayed_work(&hub->update_work, delay);
++	ssam_hub_update(hub, event->data[0]);
 +	return SSAM_NOTIF_HANDLED;
 +}
 +
-+static int __maybe_unused ssam_kip_hub_resume(struct device *dev)
-+{
-+	struct ssam_kip_hub *hub = dev_get_drvdata(dev);
-+
-+	schedule_delayed_work(&hub->update_work, 0);
-+	return 0;
-+}
-+static SIMPLE_DEV_PM_OPS(ssam_kip_hub_pm_ops, NULL, ssam_kip_hub_resume);
-+
 +static int ssam_kip_hub_probe(struct ssam_device *sdev)
 +{
-+	struct ssam_kip_hub *hub;
-+	int status;
++	struct ssam_hub *hub;
 +
 +	hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
 +	if (!hub)
 +		return -ENOMEM;
 +
-+	hub->sdev = sdev;
-+	hub->state = SSAM_KIP_HUB_UNINITIALIZED;
-+
 +	hub->notif.base.priority = INT_MAX;  /* This notifier should run first. */
 +	hub->notif.base.fn = ssam_kip_hub_notif;
 +	hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
@@ -909,37 +1145,10 @@ index 9f630e890ff7..4838ce6519a6 100644
 +	hub->notif.event.mask = SSAM_EVENT_MASK_TARGET;
 +	hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
 +
-+	INIT_DELAYED_WORK(&hub->update_work, ssam_kip_hub_update_workfn);
-+
-+	ssam_device_set_drvdata(sdev, hub);
-+
-+	status = ssam_device_notifier_register(sdev, &hub->notif);
-+	if (status)
-+		return status;
-+
-+	status = sysfs_create_group(&sdev->dev.kobj, &ssam_kip_hub_group);
-+	if (status)
-+		goto err;
-+
-+	schedule_delayed_work(&hub->update_work, 0);
-+	return 0;
-+
-+err:
-+	ssam_device_notifier_unregister(sdev, &hub->notif);
-+	cancel_delayed_work_sync(&hub->update_work);
-+	ssam_remove_clients(&sdev->dev);
-+	return status;
-+}
-+
-+static void ssam_kip_hub_remove(struct ssam_device *sdev)
-+{
-+	struct ssam_kip_hub *hub = ssam_device_get_drvdata(sdev);
-+
-+	sysfs_remove_group(&sdev->dev.kobj, &ssam_kip_hub_group);
++	hub->connect_delay = SSAM_KIP_UPDATE_CONNECT_DELAY;
++	hub->get_state = ssam_kip_get_connection_state;
 +
-+	ssam_device_notifier_unregister(sdev, &hub->notif);
-+	cancel_delayed_work_sync(&hub->update_work);
-+	ssam_remove_clients(&sdev->dev);
++	return ssam_hub_setup(sdev, hub);
 +}
 +
 +static const struct ssam_device_id ssam_kip_hub_match[] = {
@@ -949,12 +1158,12 @@ index 9f630e890ff7..4838ce6519a6 100644
 +
 +static struct ssam_device_driver ssam_kip_hub_driver = {
 +	.probe = ssam_kip_hub_probe,
-+	.remove = ssam_kip_hub_remove,
++	.remove = ssam_hub_remove,
 +	.match_table = ssam_kip_hub_match,
 +	.driver = {
 +		.name = "surface_kip_hub",
 +		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
-+		.pm = &ssam_kip_hub_pm_ops,
++		.pm = &ssam_hub_pm_ops,
 +	},
 +};
 +
@@ -962,7 +1171,7 @@ index 9f630e890ff7..4838ce6519a6 100644
  /* -- SSAM platform/meta-hub driver. ---------------------------------------- */
  
  static const struct acpi_device_id ssam_platform_hub_match[] = {
-@@ -636,18 +867,30 @@ static int __init ssam_device_hub_init(void)
+@@ -638,18 +725,30 @@ static int __init ssam_device_hub_init(void)
  
  	status = platform_driver_register(&ssam_platform_hub_driver);
  	if (status)
@@ -998,7 +1207,7 @@ index 9f630e890ff7..4838ce6519a6 100644
 -- 
 2.36.0
 
-From 72361a719765b4c3e644f5c1a78560856698b9d9 Mon Sep 17 00:00:00 2001
+From 0187e4c74438246925c820e32486fcac043d1bb7 Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Wed, 27 Oct 2021 22:33:03 +0200
 Subject: [PATCH] platform/surface: aggregator_registry: Add support for
@@ -1029,7 +1238,7 @@ Patchset: surface-sam
  1 file changed, 36 insertions(+), 1 deletion(-)
 
 diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
-index 4838ce6519a6..c0e29c0514df 100644
+index eb4b55516d3f..ebe8e78cdfef 100644
 --- a/drivers/platform/surface/surface_aggregator_registry.c
 +++ b/drivers/platform/surface/surface_aggregator_registry.c
 @@ -47,6 +47,12 @@ static const struct software_node ssam_node_hub_base = {
@@ -1096,7 +1305,7 @@ index 4838ce6519a6..c0e29c0514df 100644
 -- 
 2.36.0
 
-From 50deaaa19434c8871712984d4bc2cc348e33c082 Mon Sep 17 00:00:00 2001
+From 820556ab9ff756017b68df7a28c685b869f0b36e Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Tue, 8 Jun 2021 03:19:20 +0200
 Subject: [PATCH] platform/surface: Add KIP tablet-mode switch
@@ -1440,7 +1649,7 @@ index 000000000000..458470067579
 -- 
 2.36.0
 
-From 6d860892e44db08cec0f0e666582447daf17d488 Mon Sep 17 00:00:00 2001
+From 739e009ec2dcb4bf68f533a2a4b6343b2b02f4ac Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Wed, 27 Oct 2021 22:33:03 +0200
 Subject: [PATCH] platform/surface: aggregator_registry: Add support for tablet
@@ -1458,7 +1667,7 @@ Patchset: surface-sam
  1 file changed, 7 insertions(+), 1 deletion(-)
 
 diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
-index c0e29c0514df..eaf0054627a5 100644
+index ebe8e78cdfef..e9df8420b145 100644
 --- a/drivers/platform/surface/surface_aggregator_registry.c
 +++ b/drivers/platform/surface/surface_aggregator_registry.c
 @@ -77,6 +77,12 @@ static const struct software_node ssam_node_tmp_pprof = {

+ 2 - 2
patches/5.17/0006-surface-sam-over-hid.patch

@@ -1,4 +1,4 @@
-From 71fee6b52fd56894123da7ec3c8ca610179fdbb6 Mon Sep 17 00:00:00 2001
+From f7c02d9558fe807a567183979e6b64852ca53602 Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Sat, 25 Jul 2020 17:19:53 +0200
 Subject: [PATCH] i2c: acpi: Implement RawBytes read access
@@ -110,7 +110,7 @@ index 85ed4c1d4924..942c1c9a4ea5 100644
 -- 
 2.36.0
 
-From 1a4621385e771975078d4093210b61cf850bd2c7 Mon Sep 17 00:00:00 2001
+From 265d020bc0b2f5af38735a62ad53b83681659e48 Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Sat, 13 Feb 2021 16:41:18 +0100
 Subject: [PATCH] platform/surface: Add driver for Surface Book 1 dGPU switch

+ 1 - 1
patches/5.17/0007-surface-gpe.patch

@@ -1,4 +1,4 @@
-From 53107852ef35cc5e267e6c6bedcdeabbe2007947 Mon Sep 17 00:00:00 2001
+From 75404c502b1909a3f5776376efcd0821d6781d7c Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Wed, 27 Oct 2021 00:56:11 +0200
 Subject: [PATCH] platform/surface: gpe: Add support for Surface Pro 8

+ 4 - 4
patches/5.17/0008-surface-button.patch

@@ -1,4 +1,4 @@
-From 9df4dc6068e780b80ac4bda9fb5513fe2a2462da Mon Sep 17 00:00:00 2001
+From 6f844d5f788aae1d7ecd8602af78324943f04857 Mon Sep 17 00:00:00 2001
 From: Sachi King <nakato@nakato.io>
 Date: Tue, 5 Oct 2021 00:05:09 +1100
 Subject: [PATCH] Input: soc_button_array - support AMD variant Surface devices
@@ -75,7 +75,7 @@ index cb6ec59a045d..4e8944f59def 100644
 -- 
 2.36.0
 
-From 4f8e65d97078c6cd7eb50fc756afab56926c8e85 Mon Sep 17 00:00:00 2001
+From 4cd6811dd4737e4e76ca5b4b3e27b3989505d367 Mon Sep 17 00:00:00 2001
 From: Sachi King <nakato@nakato.io>
 Date: Tue, 5 Oct 2021 00:22:57 +1100
 Subject: [PATCH] platform/surface: surfacepro3_button: don't load on amd
@@ -147,7 +147,7 @@ index 242fb690dcaf..30eea54dbb47 100644
 -- 
 2.36.0
 
-From d2afad12171aa79978f786b5e98c6e72aa8de491 Mon Sep 17 00:00:00 2001
+From f4d1d7bf3fe1661a5177fc5cf4e32e2d68243ebd Mon Sep 17 00:00:00 2001
 From: Hans de Goede <hdegoede@redhat.com>
 Date: Thu, 24 Feb 2022 12:02:40 +0100
 Subject: [PATCH] Input: soc_button_array - add support for Microsoft Surface 3
@@ -250,7 +250,7 @@ index 4e8944f59def..f044c731c6a9 100644
 -- 
 2.36.0
 
-From f8cfbc4206d440fcb05129893996e0952e825537 Mon Sep 17 00:00:00 2001
+From 5cd2cbb9a26c3658cc81325a1e0778654d04a2f2 Mon Sep 17 00:00:00 2001
 From: Hans de Goede <hdegoede@redhat.com>
 Date: Thu, 24 Feb 2022 12:02:41 +0100
 Subject: [PATCH] platform/surface: Remove Surface 3 Button driver

+ 1 - 1
patches/5.17/0009-surface-typecover.patch

@@ -1,4 +1,4 @@
-From 634bb3362ab1a6b87943d750497e2223fdbeb71b Mon Sep 17 00:00:00 2001
+From 95067cdfc6ec05a73236ffee7c700f3123022457 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
 Date: Thu, 5 Nov 2020 13:09:45 +0100
 Subject: [PATCH] hid/multitouch: Turn off Type Cover keyboard backlight when

+ 1 - 1
patches/5.17/0010-surface-battery.patch

@@ -1,4 +1,4 @@
-From 1da1dd4313e7bf02c629804916e4219e177d4f5c Mon Sep 17 00:00:00 2001
+From a571ac532f5b41c81a7d3e699d22f9964747bd45 Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Tue, 8 Feb 2022 01:29:48 +0100
 Subject: [PATCH] ACPI: battery: Add "Not Charging" quirk for Microsoft Surface

+ 327 - 3
patches/5.17/0011-cameras.patch

@@ -1,4 +1,4 @@
-From 60158c7b6219f00a91187c7203df0fc9aeb6a0df Mon Sep 17 00:00:00 2001
+From 148b4c36347ed6bf38edbc72443f875e3da003c9 Mon Sep 17 00:00:00 2001
 From: Hans de Goede <hdegoede@redhat.com>
 Date: Sun, 10 Oct 2021 20:56:57 +0200
 Subject: [PATCH] ACPI: delay enumeration of devices with a _DEP pointing to an
@@ -74,7 +74,7 @@ index c82b1bfa1c3d..2227625202aa 100644
 -- 
 2.36.0
 
-From 06add1b4d4cfb7e3bbf5a5a7a17040786569694e Mon Sep 17 00:00:00 2001
+From b06b7dc558d5a57efce81df201aa6f24ad7b84d6 Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Sun, 10 Oct 2021 20:57:02 +0200
 Subject: [PATCH] platform/x86: int3472: Enable I2c daisy chain
@@ -111,7 +111,7 @@ index 22f61b47f9e5..e1de1ff40bba 100644
 -- 
 2.36.0
 
-From ad82b50db9f9100119925d54804cf0c393f46013 Mon Sep 17 00:00:00 2001
+From f707270ec875d2a6ce1d2129e9750e246ae0b1c3 Mon Sep 17 00:00:00 2001
 From: Daniel Scally <djrscally@gmail.com>
 Date: Thu, 28 Oct 2021 21:55:16 +0100
 Subject: [PATCH] media: i2c: Add driver for DW9719 VCM
@@ -617,3 +617,327 @@ index 000000000000..8451c75b696b
 -- 
 2.36.0
 
+From c7cf5d45fd1e245f70bfb138e2aeabae993dc984 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 13 Dec 2021 22:38:17 +0000
+Subject: [PATCH] media: entity: Skip non-data links in graph iteration
+
+When iterating over the media graph, don't follow links that are not
+data links.
+
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/mc/mc-entity.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
+index b411f9796191..d0563ee4b28b 100644
+--- a/drivers/media/mc/mc-entity.c
++++ b/drivers/media/mc/mc-entity.c
+@@ -295,6 +295,12 @@ static void media_graph_walk_iter(struct media_graph *graph)
+ 
+ 	link = list_entry(link_top(graph), typeof(*link), list);
+ 
++	/* If the link is not a data link, don't follow it */
++	if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) != MEDIA_LNK_FL_DATA_LINK) {
++		link_top(graph) = link_top(graph)->next;
++		return;
++	}
++
+ 	/* The link is not enabled so we do not follow. */
+ 	if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
+ 		link_top(graph) = link_top(graph)->next;
+-- 
+2.36.0
+
+From f5a8d58e2dd0bd7c229da3edfd984ddee3b7c727 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 13 Dec 2021 22:53:09 +0000
+Subject: [PATCH] media: media.h: Add new media link type
+
+To describe in the kernel the connection between devices and their
+supporting peripherals (for example, a camera sensor and the vcm
+driving the focusing lens for it), add a new type of media link
+to introduce the concept of these ancillary links.
+
+Add some elements to the uAPI documentation to explain the new link
+type, their purpose and some aspects of their current implementation.
+
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ .../media/mediactl/media-controller-model.rst   |  6 ++++++
+ .../media/mediactl/media-types.rst              | 17 ++++++++++++-----
+ include/uapi/linux/media.h                      |  1 +
+ 3 files changed, 19 insertions(+), 5 deletions(-)
+
+diff --git a/Documentation/userspace-api/media/mediactl/media-controller-model.rst b/Documentation/userspace-api/media/mediactl/media-controller-model.rst
+index 222cb99debb5..78bfdfb2a322 100644
+--- a/Documentation/userspace-api/media/mediactl/media-controller-model.rst
++++ b/Documentation/userspace-api/media/mediactl/media-controller-model.rst
+@@ -33,3 +33,9 @@ are:
+ 
+ -  An **interface link** is a point-to-point bidirectional control
+    connection between a Linux Kernel interface and an entity.
++
++- An **ancillary link** is a point-to-point connection denoting that two
++  entities form a single logical unit. For example this could represent the
++  fact that a particular camera sensor and lens controller form a single
++  physical module, meaning this lens controller drives the lens for this
++  camera sensor.
+\ No newline at end of file
+diff --git a/Documentation/userspace-api/media/mediactl/media-types.rst b/Documentation/userspace-api/media/mediactl/media-types.rst
+index 0a26397bd01d..60747251d409 100644
+--- a/Documentation/userspace-api/media/mediactl/media-types.rst
++++ b/Documentation/userspace-api/media/mediactl/media-types.rst
+@@ -412,14 +412,21 @@ must be set for every pad.
+ 	  is set by drivers and is read-only for applications.
+ 
+     *  -  ``MEDIA_LNK_FL_LINK_TYPE``
+-       -  This is a bitmask that defines the type of the link. Currently,
+-	  two types of links are supported:
++       -  This is a bitmask that defines the type of the link. The following
++	  link types are currently supported:
+ 
+ 	  .. _MEDIA-LNK-FL-DATA-LINK:
+ 
+-	  ``MEDIA_LNK_FL_DATA_LINK`` if the link is between two pads
++	  ``MEDIA_LNK_FL_DATA_LINK`` for links that represent a data connection
++     between two pads.
+ 
+ 	  .. _MEDIA-LNK-FL-INTERFACE-LINK:
+ 
+-	  ``MEDIA_LNK_FL_INTERFACE_LINK`` if the link is between an
+-	  interface and an entity
++	  ``MEDIA_LNK_FL_INTERFACE_LINK`` for links that associate an entity to its
++     interface.
++
++	  .. _MEDIA-LNK-FL-ANCILLARY-LINK:
++
++	  ``MEDIA_LNK_FL_ANCILLARY_LINK`` for links that represent a physical
++     relationship between two entities. The link may or may not be ummutable, so
++     applications must not assume either case.
+\ No newline at end of file
+diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
+index 200fa8462b90..afbae7213d35 100644
+--- a/include/uapi/linux/media.h
++++ b/include/uapi/linux/media.h
+@@ -226,6 +226,7 @@ struct media_pad_desc {
+ #define MEDIA_LNK_FL_LINK_TYPE			(0xf << 28)
+ #  define MEDIA_LNK_FL_DATA_LINK		(0 << 28)
+ #  define MEDIA_LNK_FL_INTERFACE_LINK		(1 << 28)
++#  define MEDIA_LNK_FL_ANCILLARY_LINK		(2 << 28)
+ 
+ struct media_link_desc {
+ 	struct media_pad_desc source;
+-- 
+2.36.0
+
+From 1ddba27bb46a846b8a501fb770ee9091e02f274a Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 13 Dec 2021 22:36:31 +0000
+Subject: [PATCH] media: entity: Add link_type_name() helper
+
+Now we have three types of media link, printing the right name during
+debug output is slightly more complicated. Add a helper function to
+make it easier.
+
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/mc/mc-entity.c | 18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
+index d0563ee4b28b..1a7d0a4fb9e8 100644
+--- a/drivers/media/mc/mc-entity.c
++++ b/drivers/media/mc/mc-entity.c
+@@ -44,6 +44,20 @@ static inline const char *intf_type(struct media_interface *intf)
+ 	}
+ };
+ 
++static inline const char *link_type_name(struct media_link *link)
++{
++	switch (link->flags & MEDIA_LNK_FL_LINK_TYPE) {
++	case MEDIA_LNK_FL_DATA_LINK:
++		return "data";
++	case MEDIA_LNK_FL_INTERFACE_LINK:
++		return "interface";
++	case MEDIA_LNK_FL_ANCILLARY_LINK:
++		return "ancillary";
++	default:
++		return "unknown";
++	}
++}
++
+ __must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum,
+ 					  int idx_max)
+ {
+@@ -89,9 +103,7 @@ static void dev_dbg_obj(const char *event_name,  struct media_gobj *gobj)
+ 
+ 		dev_dbg(gobj->mdev->dev,
+ 			"%s id %u: %s link id %u ==> id %u\n",
+-			event_name, media_id(gobj),
+-			media_type(link->gobj0) == MEDIA_GRAPH_PAD ?
+-				"data" : "interface",
++			event_name, media_id(gobj), link_type_name(link),
+ 			media_id(link->gobj0),
+ 			media_id(link->gobj1));
+ 		break;
+-- 
+2.36.0
+
+From ba756c496f09ac556bbcf339c503f91e4376f812 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 13 Dec 2021 22:54:10 +0000
+Subject: [PATCH] media: entity: Add support for ancillary links
+
+Add functions to create ancillary links, so that they don't need to
+be manually created by users.
+
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/mc/mc-entity.c | 22 ++++++++++++++++++++++
+ include/media/media-entity.h | 19 +++++++++++++++++++
+ 2 files changed, 41 insertions(+)
+
+diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
+index 1a7d0a4fb9e8..d7e2f78a83cc 100644
+--- a/drivers/media/mc/mc-entity.c
++++ b/drivers/media/mc/mc-entity.c
+@@ -1032,3 +1032,25 @@ void media_remove_intf_links(struct media_interface *intf)
+ 	mutex_unlock(&mdev->graph_mutex);
+ }
+ EXPORT_SYMBOL_GPL(media_remove_intf_links);
++
++struct media_link *media_create_ancillary_link(struct media_entity *primary,
++					       struct media_entity *ancillary)
++{
++	struct media_link *link;
++
++	link = media_add_link(&primary->links);
++	if (!link)
++		return ERR_PTR(-ENOMEM);
++
++	link->gobj0 = &primary->graph_obj;
++	link->gobj1 = &ancillary->graph_obj;
++	link->flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED |
++		      MEDIA_LNK_FL_ANCILLARY_LINK;
++
++	/* Initialize graph object embedded in the new link */
++	media_gobj_create(primary->graph_obj.mdev, MEDIA_GRAPH_LINK,
++			  &link->graph_obj);
++
++	return link;
++}
++EXPORT_SYMBOL_GPL(media_create_ancillary_link);
+diff --git a/include/media/media-entity.h b/include/media/media-entity.h
+index fea489f03d57..2a58defc4886 100644
+--- a/include/media/media-entity.h
++++ b/include/media/media-entity.h
+@@ -1108,4 +1108,23 @@ void media_remove_intf_links(struct media_interface *intf);
+ 	(((entity)->ops && (entity)->ops->operation) ?			\
+ 	 (entity)->ops->operation((entity) , ##args) : -ENOIOCTLCMD)
+ 
++/**
++ * media_create_ancillary_link() - create an ancillary link between two
++ *				   instances of &media_entity
++ *
++ * @primary:	pointer to the primary &media_entity
++ * @ancillary:	pointer to the ancillary &media_entity
++ *
++ * Create an ancillary link between two entities, indicating that they
++ * represent two connected pieces of hardware that form a single logical unit.
++ * A typical example is a camera lens controller being linked to the sensor that
++ * it is supporting.
++ *
++ * The function sets both MEDIA_LNK_FL_ENABLED and MEDIA_LNK_FL_IMMUTABLE for
++ * the new link.
++ */
++struct media_link *
++media_create_ancillary_link(struct media_entity *primary,
++			    struct media_entity *ancillary);
++
+ #endif
+-- 
+2.36.0
+
+From 214d8e2570a6e1ced400e51de771eb10020b3bbc Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Fri, 26 Nov 2021 22:55:50 +0000
+Subject: [PATCH] media: v4l2-async: Create links during
+ v4l2_async_match_notify()
+
+Upon an async fwnode match, there's some typical behaviour that the
+notifier and matching subdev will want to do. For example, a notifier
+representing a sensor matching to an async subdev representing its
+VCM will want to create an ancillary link to expose that relationship
+to userspace.
+
+To avoid lots of code in individual drivers, try to build these links
+within v4l2 core.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/v4l2-core/v4l2-async.c | 31 ++++++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
+index 0404267f1ae4..436bd6900fd8 100644
+--- a/drivers/media/v4l2-core/v4l2-async.c
++++ b/drivers/media/v4l2-core/v4l2-async.c
+@@ -275,6 +275,24 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
+ static int
+ v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
+ 
++static int v4l2_async_create_ancillary_links(struct v4l2_async_notifier *n,
++					     struct v4l2_subdev *sd)
++{
++	struct media_link *link = NULL;
++
++#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER)
++
++	if (sd->entity.function != MEDIA_ENT_F_LENS &&
++	    sd->entity.function != MEDIA_ENT_F_FLASH)
++		return 0;
++
++	link = media_create_ancillary_link(&n->sd->entity, &sd->entity);
++
++#endif
++
++	return IS_ERR(link) ? PTR_ERR(link) : 0;
++}
++
+ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
+ 				   struct v4l2_device *v4l2_dev,
+ 				   struct v4l2_subdev *sd,
+@@ -293,6 +311,19 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
+ 		return ret;
+ 	}
+ 
++	/*
++	 * Depending of the function of the entities involved, we may want to
++	 * create links between them (for example between a sensor and its lens
++	 * or between a sensor's source pad and the connected device's sink
++	 * pad).
++	 */
++	ret = v4l2_async_create_ancillary_links(notifier, sd);
++	if (ret) {
++		v4l2_async_nf_call_unbind(notifier, sd, asd);
++		v4l2_device_unregister_subdev(sd);
++		return ret;
++	}
++
+ 	/* Remove from the waiting list */
+ 	list_del(&asd->list);
+ 	sd->asd = asd;
+-- 
+2.36.0
+

+ 2 - 2
patches/5.17/0012-amd-gpio.patch

@@ -1,4 +1,4 @@
-From 55d5ac979adfe7c8fdbe95a52f7a723f7891b893 Mon Sep 17 00:00:00 2001
+From a8b0b23bde3246c61ef24add46e922ef1015618a Mon Sep 17 00:00:00 2001
 From: Sachi King <nakato@nakato.io>
 Date: Sat, 29 May 2021 17:47:38 +1000
 Subject: [PATCH] ACPI: Add quirk for Surface Laptop 4 AMD missing irq 7
@@ -65,7 +65,7 @@ index 0d01e7f5078c..2b06cf5f2b1f 100644
 -- 
 2.36.0
 
-From f88b7e0091e3407e14337b25cc6263228ace9a57 Mon Sep 17 00:00:00 2001
+From 6a0f34114c20d3a647029ba142d3dbdf899db0b5 Mon Sep 17 00:00:00 2001
 From: Maximilian Luz <luzmaximilian@gmail.com>
 Date: Thu, 3 Jun 2021 14:04:26 +0200
 Subject: [PATCH] ACPI: Add AMD 13" Surface Laptop 4 model to irq 7 override

+ 8 - 8
pkg/arch/kernel/PKGBUILD

@@ -55,14 +55,14 @@ sha256sums=('SKIP'
             'c7b292284a9c2598b8705485336dc30ba8153dd90e7e72a8dd8da49acee915cd'
             '3ffe1ed2d1d4aa7eb0a1bdd13fadfc162384358c7d0fdaf244c2990b1a2e2948'
             '1a274f7d31b4c6b2c4de8766cd54f7494d365b066b995dddf372e05b250d4879'
-            'fbc3da839722741fc93b7823f435a95abf273b3af921f3611d2242f611d84689'
-            'd7586477ecd3dc198fe25c7f06b2807b13b32f54a3d9a9cbe045436c68a4deed'
-            '53ea30836527b2e6d6a4ef964a644a5c0a6595be4f50772e8be7ff02f29b0f95'
-            'fe3c3419053c74b53a67d052eb4757ad7a5a399856dc1bb61b9038cc434e31f9'
-            'c5d9082aad981f5c1f2a83b9d0b8fa93881d7f4bfe52da4387d5d956167b500e'
-            '198c2eabf1928efd07577530f7d9a5a8c7d5c99706668c0ccf6c3bf4bf7b02fe'
-            'b1921c9daa0402ff3a2a4fae18ea6c8304be79d67aa45da16e4a9e90ae6171d2'
-            'cfca153870c0313a71762e0d9934e51f03af7fa1a81788d95a8d7a4ff54c0e62')
+            'e3b7805dc5be1370518a6a8774898d371595e86d906fa052b5655687b196d683'
+            'e788cb6f0fd0316218843825f11ce0c3dcb1bf852cc7bfe3cc38adac96245c7c'
+            'c6511054e84f0e49a301b8980ab3bec863f6b6b839788c905bc971b2de766e3c'
+            'f44ed8cbef8e36c7e381a7f52e8671caf4e73c33635d26b1ded2a828b4146b57'
+            '56884586d149b5c0e6fc707f7fd6debf662498a5e399d7ad5a2432215135b4e0'
+            '265d0c1d455a14503014c885f69e3bd130af2e1bf5b2a39744146435e4acf122'
+            '5ef05f33379d20d9c5e17f4f1fe1631e64325dd715a85358b730e7e4eaf05e5e'
+            'e670c04cfafcd9287d0c0cdb20265c5e8738d923076a1bbb73a31776efa8bc5b')
 
 
 export KBUILD_BUILD_HOST=archlinux