linux-usb.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend)
@ 2021-08-17 21:51 Hans de Goede
  2021-08-17 21:51 ` [PATCH 1/8] drm/connector: Give connector sysfs devices there own device_type Hans de Goede
                   ` (8 more replies)
  0 siblings, 9 replies; 18+ messages in thread
From: Hans de Goede @ 2021-08-17 21:51 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Jani Nikula,
	Lyude, Joonas Lahtinen, Rodrigo Vivi, Imre Deak,
	Greg Kroah-Hartman, Guenter Roeck, Heikki Krogerus
  Cc: Hans de Goede, Daniel Vetter, David Airlie, intel-gfx, dri-devel,
	linux-usb

Hi all,

Here is a rebased-resend of v4 of my patchset making DP over Type-C work on
devices where the Type-C controller does not drive the HPD pin on the GPU,
but instead we need to forward HPD events from the Type-C controller to
the DRM driver.

Changes in v4 resend:
- Rebase on top of latest drm-tip

Changes in v4:
- Rebase on top of latest drm-tip
- Add forward declaration for struct fwnode_handle to drm_crtc_internal.h
  (fixes warning reported by kernel test robot <lkp@intel.com>)
- Add Heikki's Reviewed-by to patch 7 & 8
- Add Heikki's Tested-by to the series

Changes in v3:
- Base on top of latest drm-tip, which should fix the CI being unable to
  apply (and thus to test) the patches
- Make intel_acpi_assign_connector_fwnodes() take a ref on the fwnode
  it stores in connector->fwnode and have drm_connector_cleanup() put
  this reference
- Drop data argument from drm_connector_oob_hotplug_event()
- Make the Type-C DP altmode code only call drm_connector_oob_hotplug_event()
  when the HPD bit in the status vdo changes
- Drop the platform/x86/intel_cht_int33fe: Correct "displayport" fwnode
  reference patch, this will be merged independently through the pdx86 tree

Changes in v2:
- Replace the bogus "drm/connector: Make the drm_sysfs connector->kdev
  device hold a reference to the connector" patch with:
  "drm/connector: Give connector sysfs devices there own device_type"
  the new patch is a dep for patch 2/9 see the patches

- Stop using a class-dev-iter, instead at a global connector list
  to drm_connector.c and use that to find the connector by the fwnode,
  similar to how we already do this in drm_panel.c and drm_bridge.c

- Make drm_connector_oob_hotplug_event() take a fwnode pointer as
  argument, rather then a drm_connector pointer and let it do the
  lookup itself. This allows making drm_connector_find_by_fwnode() a
  drm-internal function and avoids code outside the drm subsystem
  potentially holding on the a drm_connector reference for a longer
  period.

This series not only touches drm subsys files but it also touches
drivers/usb/typec/altmodes/typec_displayport.c, that file usually
does not see a whole lot of changes. So I believe it would be best
to just merge the entire series through drm-misc, Assuming we can
get an ack from Greg for merging the typec_displayport.c changes
this way.

Regards,

Hans

Hans de Goede (7):
  drm/connector: Give connector sysfs devices there own device_type
  drm/connector: Add a fwnode pointer to drm_connector and register with
    ACPI (v2)
  drm/connector: Add drm_connector_find_by_fwnode() function (v3)
  drm/connector: Add support for out-of-band hotplug notification (v3)
  drm/i915/dp: Add support for out-of-bound hotplug events
  usb: typec: altmodes/displayport: Make dp_altmode_notify() more
    generic
  usb: typec: altmodes/displayport: Notify drm subsys of hotplug events

Heikki Krogerus (1):
  drm/i915: Associate ACPI connector nodes with connector entries (v2)

 drivers/gpu/drm/drm_connector.c              | 79 ++++++++++++++++++
 drivers/gpu/drm/drm_crtc_internal.h          |  2 +
 drivers/gpu/drm/drm_sysfs.c                  | 87 +++++++++++++++++---
 drivers/gpu/drm/i915/display/intel_acpi.c    | 46 +++++++++++
 drivers/gpu/drm/i915/display/intel_acpi.h    |  3 +
 drivers/gpu/drm/i915/display/intel_display.c |  1 +
 drivers/gpu/drm/i915/display/intel_dp.c      | 12 +++
 drivers/usb/typec/altmodes/Kconfig           |  1 +
 drivers/usb/typec/altmodes/displayport.c     | 58 ++++++++-----
 include/drm/drm_connector.h                  | 25 ++++++
 10 files changed, 279 insertions(+), 35 deletions(-)

-- 
2.31.1


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

* [PATCH 1/8] drm/connector: Give connector sysfs devices there own device_type
  2021-08-17 21:51 [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend) Hans de Goede
@ 2021-08-17 21:51 ` Hans de Goede
  2021-08-18 21:35   ` Lyude Paul
  2021-08-17 21:51 ` [PATCH 2/8] drm/connector: Add a fwnode pointer to drm_connector and register with ACPI (v2) Hans de Goede
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Hans de Goede @ 2021-08-17 21:51 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Jani Nikula,
	Lyude, Joonas Lahtinen, Rodrigo Vivi, Imre Deak,
	Greg Kroah-Hartman, Guenter Roeck, Heikki Krogerus
  Cc: Hans de Goede, Daniel Vetter, David Airlie, intel-gfx, dri-devel,
	linux-usb

Give connector sysfs devices there own device_type, this allows us to
check if a device passed to functions dealing with generic devices is
a drm_connector or not.

A check like this is necessary in the drm_connector_acpi_bus_match()
function added in the next patch in this series.

Tested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/gpu/drm/drm_sysfs.c | 50 +++++++++++++++++++++++++++----------
 1 file changed, 37 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 968a9560b4aa..f9d92bbb1f98 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -50,6 +50,10 @@ static struct device_type drm_sysfs_device_minor = {
 	.name = "drm_minor"
 };
 
+static struct device_type drm_sysfs_device_connector = {
+	.name = "drm_connector",
+};
+
 struct class *drm_class;
 
 static char *drm_devnode(struct device *dev, umode_t *mode)
@@ -102,6 +106,11 @@ void drm_sysfs_destroy(void)
 	drm_class = NULL;
 }
 
+static void drm_sysfs_release(struct device *dev)
+{
+	kfree(dev);
+}
+
 /*
  * Connector properties
  */
@@ -273,27 +282,47 @@ static const struct attribute_group *connector_dev_groups[] = {
 int drm_sysfs_connector_add(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
+	struct device *kdev;
+	int r;
 
 	if (connector->kdev)
 		return 0;
 
-	connector->kdev =
-		device_create_with_groups(drm_class, dev->primary->kdev, 0,
-					  connector, connector_dev_groups,
-					  "card%d-%s", dev->primary->index,
-					  connector->name);
+	kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
+	if (!kdev)
+		return -ENOMEM;
+
+	device_initialize(kdev);
+	kdev->class = drm_class;
+	kdev->type = &drm_sysfs_device_connector;
+	kdev->parent = dev->primary->kdev;
+	kdev->groups = connector_dev_groups;
+	kdev->release = drm_sysfs_release;
+	dev_set_drvdata(kdev, connector);
+
+	r = dev_set_name(kdev, "card%d-%s", dev->primary->index, connector->name);
+	if (r)
+		goto err_free;
+
 	DRM_DEBUG("adding \"%s\" to sysfs\n",
 		  connector->name);
 
-	if (IS_ERR(connector->kdev)) {
-		DRM_ERROR("failed to register connector device: %ld\n", PTR_ERR(connector->kdev));
-		return PTR_ERR(connector->kdev);
+	r = device_add(kdev);
+	if (r) {
+		DRM_ERROR("failed to register connector device: %d\n", r);
+		goto err_free;
 	}
 
+	connector->kdev = kdev;
+
 	if (connector->ddc)
 		return sysfs_create_link(&connector->kdev->kobj,
 				 &connector->ddc->dev.kobj, "ddc");
 	return 0;
+
+err_free:
+	put_device(kdev);
+	return r;
 }
 
 void drm_sysfs_connector_remove(struct drm_connector *connector)
@@ -374,11 +403,6 @@ void drm_sysfs_connector_status_event(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_sysfs_connector_status_event);
 
-static void drm_sysfs_release(struct device *dev)
-{
-	kfree(dev);
-}
-
 struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
 {
 	const char *minor_str;
-- 
2.31.1


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

* [PATCH 2/8] drm/connector: Add a fwnode pointer to drm_connector and register with ACPI (v2)
  2021-08-17 21:51 [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend) Hans de Goede
  2021-08-17 21:51 ` [PATCH 1/8] drm/connector: Give connector sysfs devices there own device_type Hans de Goede
@ 2021-08-17 21:51 ` Hans de Goede
  2021-08-17 21:51 ` [PATCH 3/8] drm/connector: Add drm_connector_find_by_fwnode() function (v3) Hans de Goede
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2021-08-17 21:51 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Jani Nikula,
	Lyude, Joonas Lahtinen, Rodrigo Vivi, Imre Deak,
	Greg Kroah-Hartman, Guenter Roeck, Heikki Krogerus
  Cc: Hans de Goede, Daniel Vetter, David Airlie, intel-gfx, dri-devel,
	linux-usb

Add a fwnode pointer to struct drm_connector and register an acpi_bus_type
for the connectors with the ACPI subsystem (when CONFIG_ACPI is enabled).

The adding of the fwnode pointer allows drivers to associate a fwnode
that represents a connector with that connector.

When the new fwnode pointer points to an ACPI-companion, then the new
acpi_bus_type will cause the ACPI subsys to bind the device instantiated
for the connector with the fwnode by calling acpi_bind_one(). This will
result in a firmware_node symlink under /sys/class/card#-<connecter-name>/
which helps to verify that the fwnode-s and connectors are properly
matched.

Changes in v2:
- Make drm_connector_cleanup() call fwnode_handle_put() on
  connector->fwnode and document this

Co-developed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Tested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/gpu/drm/drm_connector.c |  2 ++
 drivers/gpu/drm/drm_sysfs.c     | 37 +++++++++++++++++++++++++++++++++
 include/drm/drm_connector.h     |  8 +++++++
 3 files changed, 47 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 2ba257b1ae20..3ad359a216ff 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -474,6 +474,8 @@ void drm_connector_cleanup(struct drm_connector *connector)
 	drm_mode_object_unregister(dev, &connector->base);
 	kfree(connector->name);
 	connector->name = NULL;
+	fwnode_handle_put(connector->fwnode);
+	connector->fwnode = NULL;
 	spin_lock_irq(&dev->mode_config.connector_list_lock);
 	list_del(&connector->head);
 	dev->mode_config.num_connector--;
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index f9d92bbb1f98..bf9edce8e2d1 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -10,6 +10,7 @@
  * Copyright (c) 2003-2004 IBM Corp.
  */
 
+#include <linux/acpi.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/export.h>
@@ -56,6 +57,39 @@ static struct device_type drm_sysfs_device_connector = {
 
 struct class *drm_class;
 
+#ifdef CONFIG_ACPI
+static bool drm_connector_acpi_bus_match(struct device *dev)
+{
+	return dev->type == &drm_sysfs_device_connector;
+}
+
+static struct acpi_device *drm_connector_acpi_find_companion(struct device *dev)
+{
+	struct drm_connector *connector = to_drm_connector(dev);
+
+	return to_acpi_device_node(connector->fwnode);
+}
+
+static struct acpi_bus_type drm_connector_acpi_bus = {
+	.name = "drm_connector",
+	.match = drm_connector_acpi_bus_match,
+	.find_companion = drm_connector_acpi_find_companion,
+};
+
+static void drm_sysfs_acpi_register(void)
+{
+	register_acpi_bus_type(&drm_connector_acpi_bus);
+}
+
+static void drm_sysfs_acpi_unregister(void)
+{
+	unregister_acpi_bus_type(&drm_connector_acpi_bus);
+}
+#else
+static void drm_sysfs_acpi_register(void) { }
+static void drm_sysfs_acpi_unregister(void) { }
+#endif
+
 static char *drm_devnode(struct device *dev, umode_t *mode)
 {
 	return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
@@ -89,6 +123,8 @@ int drm_sysfs_init(void)
 	}
 
 	drm_class->devnode = drm_devnode;
+
+	drm_sysfs_acpi_register();
 	return 0;
 }
 
@@ -101,6 +137,7 @@ void drm_sysfs_destroy(void)
 {
 	if (IS_ERR_OR_NULL(drm_class))
 		return;
+	drm_sysfs_acpi_unregister();
 	class_remove_file(drm_class, &class_attr_version.attr);
 	class_destroy(drm_class);
 	drm_class = NULL;
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 1647960c9e50..69dd488a2154 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1228,6 +1228,14 @@ struct drm_connector {
 	struct device *kdev;
 	/** @attr: sysfs attributes */
 	struct device_attribute *attr;
+	/**
+	 * @fwnode: associated fwnode supplied by platform firmware
+	 *
+	 * Drivers can set this to associate a fwnode with a connector, drivers
+	 * are expected to get a reference on the fwnode when setting this.
+	 * drm_connector_cleanup() will call fwnode_handle_put() on this.
+	 */
+	struct fwnode_handle *fwnode;
 
 	/**
 	 * @head:
-- 
2.31.1


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

* [PATCH 3/8] drm/connector: Add drm_connector_find_by_fwnode() function (v3)
  2021-08-17 21:51 [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend) Hans de Goede
  2021-08-17 21:51 ` [PATCH 1/8] drm/connector: Give connector sysfs devices there own device_type Hans de Goede
  2021-08-17 21:51 ` [PATCH 2/8] drm/connector: Add a fwnode pointer to drm_connector and register with ACPI (v2) Hans de Goede
@ 2021-08-17 21:51 ` Hans de Goede
  2021-08-17 21:51 ` [PATCH 4/8] drm/connector: Add support for out-of-band hotplug notification (v3) Hans de Goede
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2021-08-17 21:51 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Jani Nikula,
	Lyude, Joonas Lahtinen, Rodrigo Vivi, Imre Deak,
	Greg Kroah-Hartman, Guenter Roeck, Heikki Krogerus
  Cc: Hans de Goede, Daniel Vetter, David Airlie, intel-gfx, dri-devel,
	linux-usb

Add a function to find a connector based on a fwnode.

This will be used by the new drm_connector_oob_hotplug_event()
function which is added by the next patch in this patch-set.

Changes in v2:
- Complete rewrite to use a global connector list in drm_connector.c
  rather then using a class-dev-iter in drm_sysfs.c

Changes in v3:
- Add forward declaration for struct fwnode_handle to drm_crtc_internal.h
  (fixes warning reported by kernel test robot <lkp@intel.com>)

Tested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/gpu/drm/drm_connector.c     | 50 +++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_crtc_internal.h |  2 ++
 include/drm/drm_connector.h         |  8 +++++
 3 files changed, 60 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 3ad359a216ff..7d72bcefa4d6 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -65,6 +65,14 @@
  * support can instead use e.g. drm_helper_hpd_irq_event().
  */
 
+/*
+ * Global connector list for drm_connector_find_by_fwnode().
+ * Note drm_connector_[un]register() first take connector->lock and then
+ * take the connector_list_lock.
+ */
+static DEFINE_MUTEX(connector_list_lock);
+static LIST_HEAD(connector_list);
+
 struct drm_conn_prop_enum_list {
 	int type;
 	const char *name;
@@ -267,6 +275,7 @@ int drm_connector_init(struct drm_device *dev,
 		goto out_put_type_id;
 	}
 
+	INIT_LIST_HEAD(&connector->global_connector_list_entry);
 	INIT_LIST_HEAD(&connector->probed_modes);
 	INIT_LIST_HEAD(&connector->modes);
 	mutex_init(&connector->mutex);
@@ -534,6 +543,9 @@ int drm_connector_register(struct drm_connector *connector)
 	/* Let userspace know we have a new connector */
 	drm_sysfs_hotplug_event(connector->dev);
 
+	mutex_lock(&connector_list_lock);
+	list_add_tail(&connector->global_connector_list_entry, &connector_list);
+	mutex_unlock(&connector_list_lock);
 	goto unlock;
 
 err_debugfs:
@@ -562,6 +574,10 @@ void drm_connector_unregister(struct drm_connector *connector)
 		return;
 	}
 
+	mutex_lock(&connector_list_lock);
+	list_del_init(&connector->global_connector_list_entry);
+	mutex_unlock(&connector_list_lock);
+
 	if (connector->funcs->early_unregister)
 		connector->funcs->early_unregister(connector);
 
@@ -2545,6 +2561,40 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
 	return ret;
 }
 
+/**
+ * drm_connector_find_by_fwnode - Find a connector based on the associated fwnode
+ * @fwnode: fwnode for which to find the matching drm_connector
+ *
+ * This functions looks up a drm_connector based on its associated fwnode. When
+ * a connector is found a reference to the connector is returned. The caller must
+ * call drm_connector_put() to release this reference when it is done with the
+ * connector.
+ *
+ * Returns: A reference to the found connector or an ERR_PTR().
+ */
+struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode)
+{
+	struct drm_connector *connector, *found = ERR_PTR(-ENODEV);
+
+	if (!fwnode)
+		return ERR_PTR(-ENODEV);
+
+	mutex_lock(&connector_list_lock);
+
+	list_for_each_entry(connector, &connector_list, global_connector_list_entry) {
+		if (connector->fwnode == fwnode ||
+		    (connector->fwnode && connector->fwnode->secondary == fwnode)) {
+			drm_connector_get(connector);
+			found = connector;
+			break;
+		}
+	}
+
+	mutex_unlock(&connector_list_lock);
+
+	return found;
+}
+
 
 /**
  * DOC: Tile group
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index edb772947cb4..63279e984342 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -58,6 +58,7 @@ struct drm_property;
 struct edid;
 struct kref;
 struct work_struct;
+struct fwnode_handle;
 
 /* drm_crtc.c */
 int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
@@ -186,6 +187,7 @@ int drm_connector_set_obj_prop(struct drm_mode_object *obj,
 int drm_connector_create_standard_properties(struct drm_device *dev);
 const char *drm_get_connector_force_name(enum drm_connector_force force);
 void drm_connector_free_work_fn(struct work_struct *work);
+struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode);
 
 /* IOCTL */
 int drm_connector_property_set_ioctl(struct drm_device *dev,
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 69dd488a2154..8132c48b56ae 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1247,6 +1247,14 @@ struct drm_connector {
 	 */
 	struct list_head head;
 
+	/**
+	 * @global_connector_list_entry:
+	 *
+	 * Connector entry in the global connector-list, used by
+	 * drm_connector_find_by_fwnode().
+	 */
+	struct list_head global_connector_list_entry;
+
 	/** @base: base KMS object */
 	struct drm_mode_object base;
 
-- 
2.31.1


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

* [PATCH 4/8] drm/connector: Add support for out-of-band hotplug notification (v3)
  2021-08-17 21:51 [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend) Hans de Goede
                   ` (2 preceding siblings ...)
  2021-08-17 21:51 ` [PATCH 3/8] drm/connector: Add drm_connector_find_by_fwnode() function (v3) Hans de Goede
@ 2021-08-17 21:51 ` Hans de Goede
  2021-08-17 21:51 ` [PATCH 5/8] drm/i915: Associate ACPI connector nodes with connector entries (v2) Hans de Goede
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2021-08-17 21:51 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Jani Nikula,
	Lyude, Joonas Lahtinen, Rodrigo Vivi, Imre Deak,
	Greg Kroah-Hartman, Guenter Roeck, Heikki Krogerus
  Cc: Hans de Goede, Daniel Vetter, David Airlie, intel-gfx, dri-devel,
	linux-usb

Add a new drm_connector_oob_hotplug_event() function and
oob_hotplug_event drm_connector_funcs member.

On some hardware a hotplug event notification may come from outside the
display driver / device. An example of this is some USB Type-C setups
where the hardware muxes the DisplayPort data and aux-lines but does
not pass the altmode HPD status bit to the GPU's DP HPD pin.

In cases like this the new drm_connector_oob_hotplug_event() function can
be used to report these out-of-band events.

Changes in v2:
- Make drm_connector_oob_hotplug_event() take a fwnode as argument and
  have it call drm_connector_find_by_fwnode() internally. This allows
  making drm_connector_find_by_fwnode() a drm-internal function and
  avoids code outside the drm subsystem potentially holding on the
  a drm_connector reference for a longer period.

Changes in v3:
- Drop the data argument to the drm_connector_oob_hotplug_event
  function since it is not used atm. This can be re-added later when
  a use for it actually arises.

Tested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/gpu/drm/drm_connector.c | 27 +++++++++++++++++++++++++++
 include/drm/drm_connector.h     |  9 +++++++++
 2 files changed, 36 insertions(+)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 7d72bcefa4d6..e0a30e0ee86a 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -2595,6 +2595,33 @@ struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode)
 	return found;
 }
 
+/**
+ * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector
+ * @connector: connector to report the event on
+ *
+ * On some hardware a hotplug event notification may come from outside the display
+ * driver / device. An example of this is some USB Type-C setups where the hardware
+ * muxes the DisplayPort data and aux-lines but does not pass the altmode HPD
+ * status bit to the GPU's DP HPD pin.
+ *
+ * This function can be used to report these out-of-band events after obtaining
+ * a drm_connector reference through calling drm_connector_find_by_fwnode().
+ */
+void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode)
+{
+	struct drm_connector *connector;
+
+	connector = drm_connector_find_by_fwnode(connector_fwnode);
+	if (IS_ERR(connector))
+		return;
+
+	if (connector->funcs->oob_hotplug_event)
+		connector->funcs->oob_hotplug_event(connector);
+
+	drm_connector_put(connector);
+}
+EXPORT_SYMBOL(drm_connector_oob_hotplug_event);
+
 
 /**
  * DOC: Tile group
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 8132c48b56ae..79fa34e5ccdb 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1084,6 +1084,14 @@ struct drm_connector_funcs {
 	 */
 	void (*atomic_print_state)(struct drm_printer *p,
 				   const struct drm_connector_state *state);
+
+	/**
+	 * @oob_hotplug_event:
+	 *
+	 * This will get called when a hotplug-event for a drm-connector
+	 * has been received from a source outside the display driver / device.
+	 */
+	void (*oob_hotplug_event)(struct drm_connector *connector);
 };
 
 /**
@@ -1666,6 +1674,7 @@ drm_connector_is_unregistered(struct drm_connector *connector)
 		DRM_CONNECTOR_UNREGISTERED;
 }
 
+void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode);
 const char *drm_get_connector_type_name(unsigned int connector_type);
 const char *drm_get_connector_status_name(enum drm_connector_status status);
 const char *drm_get_subpixel_order_name(enum subpixel_order order);
-- 
2.31.1


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

* [PATCH 5/8] drm/i915: Associate ACPI connector nodes with connector entries (v2)
  2021-08-17 21:51 [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend) Hans de Goede
                   ` (3 preceding siblings ...)
  2021-08-17 21:51 ` [PATCH 4/8] drm/connector: Add support for out-of-band hotplug notification (v3) Hans de Goede
@ 2021-08-17 21:51 ` Hans de Goede
  2021-08-17 21:51 ` [PATCH 6/8] drm/i915/dp: Add support for out-of-bound hotplug events Hans de Goede
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2021-08-17 21:51 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Jani Nikula,
	Lyude, Joonas Lahtinen, Rodrigo Vivi, Imre Deak,
	Greg Kroah-Hartman, Guenter Roeck, Heikki Krogerus
  Cc: Hans de Goede, Daniel Vetter, David Airlie, intel-gfx, dri-devel,
	linux-usb

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

On Intel platforms we know that the ACPI connector device
node order will follow the order the driver (i915) decides.
The decision is made using the custom Intel ACPI OpRegion
(intel_opregion.c), though the driver does not actually know
that the values it sends to ACPI there are used for
associating a device node for the connectors, and assigning
address for them.

In reality that custom Intel ACPI OpRegion actually violates
ACPI specification (we supply dynamic information to objects
that are defined static, for example _ADR), however, it
makes assigning correct connector node for a connector entry
straightforward (it's one-on-one mapping).

Changes in v2 (Hans de goede):
- Take a reference on the fwnode which we assign to the connector,
  for ACPI nodes this is a no-op but in the future we may see
  software-fwnodes assigned to connectors which are ref-counted.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Tested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/gpu/drm/i915/display/intel_acpi.c    | 46 ++++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_acpi.h    |  3 ++
 drivers/gpu/drm/i915/display/intel_display.c |  1 +
 3 files changed, 50 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c b/drivers/gpu/drm/i915/display/intel_acpi.c
index 7cfe91fc05f2..72cac55c0f0f 100644
--- a/drivers/gpu/drm/i915/display/intel_acpi.c
+++ b/drivers/gpu/drm/i915/display/intel_acpi.c
@@ -282,3 +282,49 @@ void intel_acpi_device_id_update(struct drm_i915_private *dev_priv)
 	}
 	drm_connector_list_iter_end(&conn_iter);
 }
+
+/* NOTE: The connector order must be final before this is called. */
+void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915)
+{
+	struct drm_connector_list_iter conn_iter;
+	struct drm_device *drm_dev = &i915->drm;
+	struct fwnode_handle *fwnode = NULL;
+	struct drm_connector *connector;
+	struct acpi_device *adev;
+
+	drm_connector_list_iter_begin(drm_dev, &conn_iter);
+	drm_for_each_connector_iter(connector, &conn_iter) {
+		/* Always getting the next, even when the last was not used. */
+		fwnode = device_get_next_child_node(drm_dev->dev, fwnode);
+		if (!fwnode)
+			break;
+
+		switch (connector->connector_type) {
+		case DRM_MODE_CONNECTOR_LVDS:
+		case DRM_MODE_CONNECTOR_eDP:
+		case DRM_MODE_CONNECTOR_DSI:
+			/*
+			 * Integrated displays have a specific address 0x1f on
+			 * most Intel platforms, but not on all of them.
+			 */
+			adev = acpi_find_child_device(ACPI_COMPANION(drm_dev->dev),
+						      0x1f, 0);
+			if (adev) {
+				connector->fwnode =
+					fwnode_handle_get(acpi_fwnode_handle(adev));
+				break;
+			}
+			fallthrough;
+		default:
+			connector->fwnode = fwnode_handle_get(fwnode);
+			break;
+		}
+	}
+	drm_connector_list_iter_end(&conn_iter);
+	/*
+	 * device_get_next_child_node() takes a reference on the fwnode, if
+	 * we stopped iterating because we are out of connectors we need to
+	 * put this, otherwise fwnode is NULL and the put is a no-op.
+	 */
+	fwnode_handle_put(fwnode);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_acpi.h b/drivers/gpu/drm/i915/display/intel_acpi.h
index 9f197401c313..4a760a2baed9 100644
--- a/drivers/gpu/drm/i915/display/intel_acpi.h
+++ b/drivers/gpu/drm/i915/display/intel_acpi.h
@@ -13,6 +13,7 @@ void intel_register_dsm_handler(void);
 void intel_unregister_dsm_handler(void);
 void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915);
 void intel_acpi_device_id_update(struct drm_i915_private *i915);
+void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915);
 #else
 static inline void intel_register_dsm_handler(void) { return; }
 static inline void intel_unregister_dsm_handler(void) { return; }
@@ -20,6 +21,8 @@ static inline
 void intel_dsm_get_bios_data_funcs_supported(struct drm_i915_private *i915) { return; }
 static inline
 void intel_acpi_device_id_update(struct drm_i915_private *i915) { return; }
+static inline
+void intel_acpi_assign_connector_fwnodes(struct drm_i915_private *i915) { return; }
 #endif /* CONFIG_ACPI */
 
 #endif /* __INTEL_ACPI_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index a257e5dc381c..88e5fff64b8c 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -12561,6 +12561,7 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915)
 
 	drm_modeset_lock_all(dev);
 	intel_modeset_setup_hw_state(dev, dev->mode_config.acquire_ctx);
+	intel_acpi_assign_connector_fwnodes(i915);
 	drm_modeset_unlock_all(dev);
 
 	for_each_intel_crtc(dev, crtc) {
-- 
2.31.1


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

* [PATCH 6/8] drm/i915/dp: Add support for out-of-bound hotplug events
  2021-08-17 21:51 [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend) Hans de Goede
                   ` (4 preceding siblings ...)
  2021-08-17 21:51 ` [PATCH 5/8] drm/i915: Associate ACPI connector nodes with connector entries (v2) Hans de Goede
@ 2021-08-17 21:51 ` Hans de Goede
  2021-08-17 21:52 ` [PATCH 7/8] usb: typec: altmodes/displayport: Make dp_altmode_notify() more generic Hans de Goede
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2021-08-17 21:51 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Jani Nikula,
	Lyude, Joonas Lahtinen, Rodrigo Vivi, Imre Deak,
	Greg Kroah-Hartman, Guenter Roeck, Heikki Krogerus
  Cc: Hans de Goede, Daniel Vetter, David Airlie, intel-gfx, dri-devel,
	linux-usb

On some Cherry Trail devices, DisplayPort over Type-C is supported through
a USB-PD microcontroller (e.g. a fusb302) + a mux to switch the superspeed
datalines between USB-3 and DP (e.g. a pi3usb30532). The kernel in this
case does the PD/alt-mode negotiation itself, rather then everything being
handled in firmware.

So the kernel itself picks an alt-mode, tells the Type-C "dongle" to switch
to DP mode and sets the mux accordingly. In this setup the HPD pin is not
connected, so the i915 driver needs to respond to a software event and scan
the DP port for changes manually.

This commit adds support for this. Together with the recent addition of
DP alt-mode support to the Type-C subsystem this makes DP over Type-C
work on these devices.

Tested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 75d4ebc66941..e807ffc2d782 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4590,6 +4590,17 @@ static int intel_dp_connector_atomic_check(struct drm_connector *conn,
 	return intel_modeset_synced_crtcs(state, conn);
 }
 
+static void intel_dp_oob_hotplug_event(struct drm_connector *connector)
+{
+	struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector));
+	struct drm_i915_private *i915 = to_i915(connector->dev);
+
+	spin_lock_irq(&i915->irq_lock);
+	i915->hotplug.event_bits |= BIT(encoder->hpd_pin);
+	spin_unlock_irq(&i915->irq_lock);
+	queue_delayed_work(system_wq, &i915->hotplug.hotplug_work, 0);
+}
+
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
 	.force = intel_dp_force,
 	.fill_modes = drm_helper_probe_single_connector_modes,
@@ -4600,6 +4611,7 @@ static const struct drm_connector_funcs intel_dp_connector_funcs = {
 	.destroy = intel_connector_destroy,
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 	.atomic_duplicate_state = intel_digital_connector_duplicate_state,
+	.oob_hotplug_event = intel_dp_oob_hotplug_event,
 };
 
 static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = {
-- 
2.31.1


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

* [PATCH 7/8] usb: typec: altmodes/displayport: Make dp_altmode_notify() more generic
  2021-08-17 21:51 [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend) Hans de Goede
                   ` (5 preceding siblings ...)
  2021-08-17 21:51 ` [PATCH 6/8] drm/i915/dp: Add support for out-of-bound hotplug events Hans de Goede
@ 2021-08-17 21:52 ` Hans de Goede
  2021-08-17 21:52 ` [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events Hans de Goede
  2021-08-18 22:03 ` [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend) Lyude Paul
  8 siblings, 0 replies; 18+ messages in thread
From: Hans de Goede @ 2021-08-17 21:52 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Jani Nikula,
	Lyude, Joonas Lahtinen, Rodrigo Vivi, Imre Deak,
	Greg Kroah-Hartman, Guenter Roeck, Heikki Krogerus
  Cc: Hans de Goede, Daniel Vetter, David Airlie, intel-gfx, dri-devel,
	linux-usb

Make dp_altmode_notify() handle the dp->data.conf == 0 case too,
rather then having separate code-paths for this in various places
which call it.

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Tested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/usb/typec/altmodes/displayport.c | 35 +++++++++---------------
 1 file changed, 13 insertions(+), 22 deletions(-)

diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index b7f094435b00..aa669b9cf70e 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -66,10 +66,17 @@ struct dp_altmode {
 
 static int dp_altmode_notify(struct dp_altmode *dp)
 {
-	u8 state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf));
+	unsigned long conf;
+	u8 state;
+
+	if (dp->data.conf) {
+		state = get_count_order(DP_CONF_GET_PIN_ASSIGN(dp->data.conf));
+		conf = TYPEC_MODAL_STATE(state);
+	} else {
+		conf = TYPEC_STATE_USB;
+	}
 
-	return typec_altmode_notify(dp->alt, TYPEC_MODAL_STATE(state),
-				   &dp->data);
+	return typec_altmode_notify(dp->alt, conf, &dp->data);
 }
 
 static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
@@ -137,21 +144,10 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
 
 static int dp_altmode_configured(struct dp_altmode *dp)
 {
-	int ret;
-
 	sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration");
-
-	if (!dp->data.conf)
-		return typec_altmode_notify(dp->alt, TYPEC_STATE_USB,
-					    &dp->data);
-
-	ret = dp_altmode_notify(dp);
-	if (ret)
-		return ret;
-
 	sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment");
 
-	return 0;
+	return dp_altmode_notify(dp);
 }
 
 static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf)
@@ -172,13 +168,8 @@ static int dp_altmode_configure_vdm(struct dp_altmode *dp, u32 conf)
 	}
 
 	ret = typec_altmode_vdm(dp->alt, header, &conf, 2);
-	if (ret) {
-		if (DP_CONF_GET_PIN_ASSIGN(dp->data.conf))
-			dp_altmode_notify(dp);
-		else
-			typec_altmode_notify(dp->alt, TYPEC_STATE_USB,
-					     &dp->data);
-	}
+	if (ret)
+		dp_altmode_notify(dp);
 
 	return ret;
 }
-- 
2.31.1


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

* [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events
  2021-08-17 21:51 [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend) Hans de Goede
                   ` (6 preceding siblings ...)
  2021-08-17 21:52 ` [PATCH 7/8] usb: typec: altmodes/displayport: Make dp_altmode_notify() more generic Hans de Goede
@ 2021-08-17 21:52 ` Hans de Goede
  2021-09-16  3:20   ` Stephen Boyd
  2021-08-18 22:03 ` [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend) Lyude Paul
  8 siblings, 1 reply; 18+ messages in thread
From: Hans de Goede @ 2021-08-17 21:52 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Jani Nikula,
	Lyude, Joonas Lahtinen, Rodrigo Vivi, Imre Deak,
	Greg Kroah-Hartman, Guenter Roeck, Heikki Krogerus
  Cc: Hans de Goede, Daniel Vetter, David Airlie, intel-gfx, dri-devel,
	linux-usb

Use the new drm_connector_oob_hotplug_event() functions to let drm/kms
drivers know about DisplayPort over Type-C hotplug events.

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Tested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Changes in v3:
- Only call drm_connector_oob_hotplug_event() on hpd status bit change
- Adjust for drm_connector_oob_hotplug_event() no longer having a data
  argument

Changes in v2:
- Add missing depends on DRM to TYPEC_DP_ALTMODE Kconfig entry
---
 drivers/usb/typec/altmodes/Kconfig       |  1 +
 drivers/usb/typec/altmodes/displayport.c | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/drivers/usb/typec/altmodes/Kconfig b/drivers/usb/typec/altmodes/Kconfig
index 60d375e9c3c7..1a6b5e872b0d 100644
--- a/drivers/usb/typec/altmodes/Kconfig
+++ b/drivers/usb/typec/altmodes/Kconfig
@@ -4,6 +4,7 @@ menu "USB Type-C Alternate Mode drivers"
 
 config TYPEC_DP_ALTMODE
 	tristate "DisplayPort Alternate Mode driver"
+	depends on DRM
 	help
 	  DisplayPort USB Type-C Alternate Mode allows DisplayPort
 	  displays and adapters to be attached to the USB Type-C
diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index aa669b9cf70e..c1d8c23baa39 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -11,8 +11,10 @@
 #include <linux/delay.h>
 #include <linux/mutex.h>
 #include <linux/module.h>
+#include <linux/property.h>
 #include <linux/usb/pd_vdo.h>
 #include <linux/usb/typec_dp.h>
+#include <drm/drm_connector.h>
 #include "displayport.h"
 
 #define DP_HEADER(_dp, ver, cmd)	(VDO((_dp)->alt->svid, 1, ver, cmd)	\
@@ -57,11 +59,13 @@ struct dp_altmode {
 	struct typec_displayport_data data;
 
 	enum dp_state state;
+	bool hpd;
 
 	struct mutex lock; /* device lock */
 	struct work_struct work;
 	struct typec_altmode *alt;
 	const struct typec_altmode *port;
+	struct fwnode_handle *connector_fwnode;
 };
 
 static int dp_altmode_notify(struct dp_altmode *dp)
@@ -125,6 +129,7 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
 static int dp_altmode_status_update(struct dp_altmode *dp)
 {
 	bool configured = !!DP_CONF_GET_PIN_ASSIGN(dp->data.conf);
+	bool hpd = !!(dp->data.status & DP_STATUS_HPD_STATE);
 	u8 con = DP_STATUS_CONNECTION(dp->data.status);
 	int ret = 0;
 
@@ -137,6 +142,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
 		ret = dp_altmode_configure(dp, con);
 		if (!ret)
 			dp->state = DP_STATE_CONFIGURE;
+	} else {
+		if (dp->hpd != hpd) {
+			drm_connector_oob_hotplug_event(dp->connector_fwnode);
+			dp->hpd = hpd;
+		}
 	}
 
 	return ret;
@@ -512,6 +522,7 @@ static const struct attribute_group dp_altmode_group = {
 int dp_altmode_probe(struct typec_altmode *alt)
 {
 	const struct typec_altmode *port = typec_altmode_get_partner(alt);
+	struct fwnode_handle *fwnode;
 	struct dp_altmode *dp;
 	int ret;
 
@@ -540,6 +551,11 @@ int dp_altmode_probe(struct typec_altmode *alt)
 	alt->desc = "DisplayPort";
 	alt->ops = &dp_altmode_ops;
 
+	fwnode = dev_fwnode(alt->dev.parent->parent); /* typec_port fwnode */
+	dp->connector_fwnode = fwnode_find_reference(fwnode, "displayport", 0);
+	if (IS_ERR(dp->connector_fwnode))
+		dp->connector_fwnode = NULL;
+
 	typec_altmode_set_drvdata(alt, dp);
 
 	dp->state = DP_STATE_ENTER;
@@ -555,6 +571,13 @@ void dp_altmode_remove(struct typec_altmode *alt)
 
 	sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group);
 	cancel_work_sync(&dp->work);
+
+	if (dp->connector_fwnode) {
+		if (dp->hpd)
+			drm_connector_oob_hotplug_event(dp->connector_fwnode);
+
+		fwnode_handle_put(dp->connector_fwnode);
+	}
 }
 EXPORT_SYMBOL_GPL(dp_altmode_remove);
 
-- 
2.31.1


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

* Re: [PATCH 1/8] drm/connector: Give connector sysfs devices there own device_type
  2021-08-17 21:51 ` [PATCH 1/8] drm/connector: Give connector sysfs devices there own device_type Hans de Goede
@ 2021-08-18 21:35   ` Lyude Paul
  0 siblings, 0 replies; 18+ messages in thread
From: Lyude Paul @ 2021-08-18 21:35 UTC (permalink / raw)
  To: Hans de Goede, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
	Imre Deak, Greg Kroah-Hartman, Guenter Roeck, Heikki Krogerus
  Cc: Daniel Vetter, David Airlie, intel-gfx, dri-devel, linux-usb

On Tue, 2021-08-17 at 23:51 +0200, Hans de Goede wrote:
> Give connector sysfs devices there own device_type, this allows us to
> check if a device passed to functions dealing with generic devices is
> a drm_connector or not.
> 
> A check like this is necessary in the drm_connector_acpi_bus_match()
> function added in the next patch in this series.
> 
> Tested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  drivers/gpu/drm/drm_sysfs.c | 50 +++++++++++++++++++++++++++----------
>  1 file changed, 37 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
> index 968a9560b4aa..f9d92bbb1f98 100644
> --- a/drivers/gpu/drm/drm_sysfs.c
> +++ b/drivers/gpu/drm/drm_sysfs.c
> @@ -50,6 +50,10 @@ static struct device_type drm_sysfs_device_minor = {
>         .name = "drm_minor"
>  };
>  
> +static struct device_type drm_sysfs_device_connector = {
> +       .name = "drm_connector",
> +};
> +
>  struct class *drm_class;
>  
>  static char *drm_devnode(struct device *dev, umode_t *mode)
> @@ -102,6 +106,11 @@ void drm_sysfs_destroy(void)
>         drm_class = NULL;
>  }
>  
> +static void drm_sysfs_release(struct device *dev)
> +{
> +       kfree(dev);
> +}
> +
>  /*
>   * Connector properties
>   */
> @@ -273,27 +282,47 @@ static const struct attribute_group
> *connector_dev_groups[] = {
>  int drm_sysfs_connector_add(struct drm_connector *connector)
>  {
>         struct drm_device *dev = connector->dev;
> +       struct device *kdev;
> +       int r;
>  
>         if (connector->kdev)
>                 return 0;
>  
> -       connector->kdev =
> -               device_create_with_groups(drm_class, dev->primary->kdev, 0,
> -                                         connector, connector_dev_groups,
> -                                         "card%d-%s", dev->primary->index,
> -                                         connector->name);
> +       kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
> +       if (!kdev)
> +               return -ENOMEM;
> +
> +       device_initialize(kdev);
> +       kdev->class = drm_class;
> +       kdev->type = &drm_sysfs_device_connector;
> +       kdev->parent = dev->primary->kdev;
> +       kdev->groups = connector_dev_groups;
> +       kdev->release = drm_sysfs_release;
> +       dev_set_drvdata(kdev, connector);
> +
> +       r = dev_set_name(kdev, "card%d-%s", dev->primary->index, connector-
> >name);
> +       if (r)
> +               goto err_free;
> +
>         DRM_DEBUG("adding \"%s\" to sysfs\n",
>                   connector->name);
>  
> -       if (IS_ERR(connector->kdev)) {
> -               DRM_ERROR("failed to register connector device: %ld\n",
> PTR_ERR(connector->kdev));
> -               return PTR_ERR(connector->kdev);
> +       r = device_add(kdev);
> +       if (r) {
> +               DRM_ERROR("failed to register connector device: %d\n", r);
> +               goto err_free;

Should probably be using drm_err() here since we have access to struct
drm_device *

>         }
>  
> +       connector->kdev = kdev;
> +
>         if (connector->ddc)
>                 return sysfs_create_link(&connector->kdev->kobj,
>                                  &connector->ddc->dev.kobj, "ddc");
>         return 0;
> +
> +err_free:
> +       put_device(kdev);
> +       return r;
>  }
>  
>  void drm_sysfs_connector_remove(struct drm_connector *connector)
> @@ -374,11 +403,6 @@ void drm_sysfs_connector_status_event(struct
> drm_connector *connector,
>  }
>  EXPORT_SYMBOL(drm_sysfs_connector_status_event);
>  
> -static void drm_sysfs_release(struct device *dev)
> -{
> -       kfree(dev);
> -}
> -
>  struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
>  {
>         const char *minor_str;

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend)
  2021-08-17 21:51 [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend) Hans de Goede
                   ` (7 preceding siblings ...)
  2021-08-17 21:52 ` [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events Hans de Goede
@ 2021-08-18 22:03 ` Lyude Paul
  8 siblings, 0 replies; 18+ messages in thread
From: Lyude Paul @ 2021-08-18 22:03 UTC (permalink / raw)
  To: Hans de Goede, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
	Imre Deak, Greg Kroah-Hartman, Guenter Roeck, Heikki Krogerus
  Cc: Daniel Vetter, David Airlie, intel-gfx, dri-devel, linux-usb

This looks great to me! Wasn't much to comment on here as most of this looks
fine to me. For the whole series:

Reviewed-by: Lyude Paul <lyude@redhat.com>

This will be quite interesting to try getting working for nouveau

On Tue, 2021-08-17 at 23:51 +0200, Hans de Goede wrote:
> Hi all,
> 
> Here is a rebased-resend of v4 of my patchset making DP over Type-C work on
> devices where the Type-C controller does not drive the HPD pin on the GPU,
> but instead we need to forward HPD events from the Type-C controller to
> the DRM driver.
> 
> Changes in v4 resend:
> - Rebase on top of latest drm-tip
> 
> Changes in v4:
> - Rebase on top of latest drm-tip
> - Add forward declaration for struct fwnode_handle to drm_crtc_internal.h
>   (fixes warning reported by kernel test robot <lkp@intel.com>)
> - Add Heikki's Reviewed-by to patch 7 & 8
> - Add Heikki's Tested-by to the series
> 
> Changes in v3:
> - Base on top of latest drm-tip, which should fix the CI being unable to
>   apply (and thus to test) the patches
> - Make intel_acpi_assign_connector_fwnodes() take a ref on the fwnode
>   it stores in connector->fwnode and have drm_connector_cleanup() put
>   this reference
> - Drop data argument from drm_connector_oob_hotplug_event()
> - Make the Type-C DP altmode code only call
> drm_connector_oob_hotplug_event()
>   when the HPD bit in the status vdo changes
> - Drop the platform/x86/intel_cht_int33fe: Correct "displayport" fwnode
>   reference patch, this will be merged independently through the pdx86 tree
> 
> Changes in v2:
> - Replace the bogus "drm/connector: Make the drm_sysfs connector->kdev
>   device hold a reference to the connector" patch with:
>   "drm/connector: Give connector sysfs devices there own device_type"
>   the new patch is a dep for patch 2/9 see the patches
> 
> - Stop using a class-dev-iter, instead at a global connector list
>   to drm_connector.c and use that to find the connector by the fwnode,
>   similar to how we already do this in drm_panel.c and drm_bridge.c
> 
> - Make drm_connector_oob_hotplug_event() take a fwnode pointer as
>   argument, rather then a drm_connector pointer and let it do the
>   lookup itself. This allows making drm_connector_find_by_fwnode() a
>   drm-internal function and avoids code outside the drm subsystem
>   potentially holding on the a drm_connector reference for a longer
>   period.
> 
> This series not only touches drm subsys files but it also touches
> drivers/usb/typec/altmodes/typec_displayport.c, that file usually
> does not see a whole lot of changes. So I believe it would be best
> to just merge the entire series through drm-misc, Assuming we can
> get an ack from Greg for merging the typec_displayport.c changes
> this way.
> 
> Regards,
> 
> Hans
> 
> Hans de Goede (7):
>   drm/connector: Give connector sysfs devices there own device_type
>   drm/connector: Add a fwnode pointer to drm_connector and register with
>     ACPI (v2)
>   drm/connector: Add drm_connector_find_by_fwnode() function (v3)
>   drm/connector: Add support for out-of-band hotplug notification (v3)
>   drm/i915/dp: Add support for out-of-bound hotplug events
>   usb: typec: altmodes/displayport: Make dp_altmode_notify() more
>     generic
>   usb: typec: altmodes/displayport: Notify drm subsys of hotplug events
> 
> Heikki Krogerus (1):
>   drm/i915: Associate ACPI connector nodes with connector entries (v2)
> 
>  drivers/gpu/drm/drm_connector.c              | 79 ++++++++++++++++++
>  drivers/gpu/drm/drm_crtc_internal.h          |  2 +
>  drivers/gpu/drm/drm_sysfs.c                  | 87 +++++++++++++++++---
>  drivers/gpu/drm/i915/display/intel_acpi.c    | 46 +++++++++++
>  drivers/gpu/drm/i915/display/intel_acpi.h    |  3 +
>  drivers/gpu/drm/i915/display/intel_display.c |  1 +
>  drivers/gpu/drm/i915/display/intel_dp.c      | 12 +++
>  drivers/usb/typec/altmodes/Kconfig           |  1 +
>  drivers/usb/typec/altmodes/displayport.c     | 58 ++++++++-----
>  include/drm/drm_connector.h                  | 25 ++++++
>  10 files changed, 279 insertions(+), 35 deletions(-)
> 

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat


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

* Re: [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events
  2021-08-17 21:52 ` [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events Hans de Goede
@ 2021-09-16  3:20   ` Stephen Boyd
  2021-09-16 13:17     ` Hans de Goede
  0 siblings, 1 reply; 18+ messages in thread
From: Stephen Boyd @ 2021-09-16  3:20 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Guenter Roeck, Hans de Goede,
	Heikki Krogerus, Imre Deak, Jani Nikula, Joonas Lahtinen, Lyude,
	Maarten Lankhorst, Maxime Ripard, Rodrigo Vivi,
	Thomas Zimmermann, pmalani, robh
  Cc: Daniel Vetter, David Airlie, intel-gfx, dri-devel, linux-usb

Quoting Hans de Goede (2021-08-17 14:52:01)
> diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
> index aa669b9cf70e..c1d8c23baa39 100644
> --- a/drivers/usb/typec/altmodes/displayport.c
> +++ b/drivers/usb/typec/altmodes/displayport.c
> @@ -125,6 +129,7 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
>  static int dp_altmode_status_update(struct dp_altmode *dp)
>  {
>         bool configured = !!DP_CONF_GET_PIN_ASSIGN(dp->data.conf);
> +       bool hpd = !!(dp->data.status & DP_STATUS_HPD_STATE);
>         u8 con = DP_STATUS_CONNECTION(dp->data.status);
>         int ret = 0;
>
> @@ -137,6 +142,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
>                 ret = dp_altmode_configure(dp, con);
>                 if (!ret)
>                         dp->state = DP_STATE_CONFIGURE;
> +       } else {
> +               if (dp->hpd != hpd) {
> +                       drm_connector_oob_hotplug_event(dp->connector_fwnode);
> +                       dp->hpd = hpd;
> +               }
>         }
>
>         return ret;
> @@ -512,6 +522,7 @@ static const struct attribute_group dp_altmode_group = {
>  int dp_altmode_probe(struct typec_altmode *alt)
>  {
>         const struct typec_altmode *port = typec_altmode_get_partner(alt);
> +       struct fwnode_handle *fwnode;
>         struct dp_altmode *dp;
>         int ret;
>
> @@ -540,6 +551,11 @@ int dp_altmode_probe(struct typec_altmode *alt)
>         alt->desc = "DisplayPort";
>         alt->ops = &dp_altmode_ops;
>
> +       fwnode = dev_fwnode(alt->dev.parent->parent); /* typec_port fwnode */
> +       dp->connector_fwnode = fwnode_find_reference(fwnode, "displayport", 0);

I'm trying to figure out how to translate this over to DT bindings. Is
there a binding document for this fwnode reference? If not, can you
please update
Documentation/devicetree/bindings/connector/usb-connector.yaml with this
property?

I think this means that the type-c node would have a 'displayport =
<&some_phandle>' property in it that points to the display port hardware
device that's pumping out the DisplayPort data?

> +       if (IS_ERR(dp->connector_fwnode))
> +               dp->connector_fwnode = NULL;
> +
>         typec_altmode_set_drvdata(alt, dp);
>
>         dp->state = DP_STATE_ENTER;
> @@ -555,6 +571,13 @@ void dp_altmode_remove(struct typec_altmode *alt)
>
>         sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group);
>         cancel_work_sync(&dp->work);
> +
> +       if (dp->connector_fwnode) {
> +               if (dp->hpd)
> +                       drm_connector_oob_hotplug_event(dp->connector_fwnode);

I was hoping that we could make a type-c connector into a drm_bridge.
I'm thinking that it would be a DP-to-panel bridge. Then a panel could
be created as well on the end of the type-c connector and the bridge
would report hpd whenever the type-c logic figures out the cable has
been connected and hpd is asserted. The actual DisplayPort hardware
that's encoding data would then find the bridge through the graph
binding connected to the output node.

I'm not sure how MST is handled though. In that scenario maybe there's
more than one panel?

If you're interested the dts file that I'm trying to make this work for
is sc7180-trogdor.dtsi and I need to hook up mdss_dp's output port to
the two type-c connectors, usb_c0 and usb_c1, somehow. The two ports are
actually muxed by the EC (parent node) so only one type-c port can be
connected to the DP hardware at a time.

> +
> +               fwnode_handle_put(dp->connector_fwnode);
> +       }

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

* Re: [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events
  2021-09-16  3:20   ` Stephen Boyd
@ 2021-09-16 13:17     ` Hans de Goede
  2021-09-24 23:29       ` Stephen Boyd
  0 siblings, 1 reply; 18+ messages in thread
From: Hans de Goede @ 2021-09-16 13:17 UTC (permalink / raw)
  To: Stephen Boyd, Greg Kroah-Hartman, Guenter Roeck, Heikki Krogerus,
	Imre Deak, Jani Nikula, Joonas Lahtinen, Lyude,
	Maarten Lankhorst, Maxime Ripard, Rodrigo Vivi,
	Thomas Zimmermann, pmalani, robh
  Cc: Daniel Vetter, David Airlie, intel-gfx, dri-devel, linux-usb

Hi,

On 9/16/21 5:20 AM, Stephen Boyd wrote:
> Quoting Hans de Goede (2021-08-17 14:52:01)
>> diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
>> index aa669b9cf70e..c1d8c23baa39 100644
>> --- a/drivers/usb/typec/altmodes/displayport.c
>> +++ b/drivers/usb/typec/altmodes/displayport.c
>> @@ -125,6 +129,7 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
>>  static int dp_altmode_status_update(struct dp_altmode *dp)
>>  {
>>         bool configured = !!DP_CONF_GET_PIN_ASSIGN(dp->data.conf);
>> +       bool hpd = !!(dp->data.status & DP_STATUS_HPD_STATE);
>>         u8 con = DP_STATUS_CONNECTION(dp->data.status);
>>         int ret = 0;
>>
>> @@ -137,6 +142,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
>>                 ret = dp_altmode_configure(dp, con);
>>                 if (!ret)
>>                         dp->state = DP_STATE_CONFIGURE;
>> +       } else {
>> +               if (dp->hpd != hpd) {
>> +                       drm_connector_oob_hotplug_event(dp->connector_fwnode);
>> +                       dp->hpd = hpd;
>> +               }
>>         }
>>
>>         return ret;
>> @@ -512,6 +522,7 @@ static const struct attribute_group dp_altmode_group = {
>>  int dp_altmode_probe(struct typec_altmode *alt)
>>  {
>>         const struct typec_altmode *port = typec_altmode_get_partner(alt);
>> +       struct fwnode_handle *fwnode;
>>         struct dp_altmode *dp;
>>         int ret;
>>
>> @@ -540,6 +551,11 @@ int dp_altmode_probe(struct typec_altmode *alt)
>>         alt->desc = "DisplayPort";
>>         alt->ops = &dp_altmode_ops;
>>
>> +       fwnode = dev_fwnode(alt->dev.parent->parent); /* typec_port fwnode */
>> +       dp->connector_fwnode = fwnode_find_reference(fwnode, "displayport", 0);
> 
> I'm trying to figure out how to translate this over to DT bindings.

First of all let me say that it is great that people are looking
into using this functionality outside of the niche application
for which I wrote it.

> Is
> there a binding document for this fwnode reference? If not, can you
> please update
> Documentation/devicetree/bindings/connector/usb-connector.yaml with this
> property?

My use case is some Intel Cherry Trail based mini-laptops which use a
Intel Whiskey Cove PMIC with a FUSB302 Type-C controller + a
PI3USB30532 USB switch, specifically the GPD Win and GPD Pocket
(first generation of each).

These are ACPI/X86 devices so devicetree is not used there, the
connector_fwnode checked here is actually sw_node, this sw_node
reference gets setup here:

drivers/platform/x86/intel/int33fe/intel_cht_int33fe_typec.c

The setup/use of a sw_node reference for this was actually
designed by Heikki (in the Cc already), so he might be a better
person to answer your questions.

With that said, as to your question if I can document this in
usb-connector.yaml, no I cannot (sorry). Since this is a sw_node
setup by X86 code and not a normal devicetree fwnode reference,
atm this is purely a kernel internal API/binding really and the
DT-binding maintainers have repeatedly told me that I should NOT
submit DT-binding updates for these. Only once a real devicetree
user for this shows up will the accept DT-bindings patches for this.

The good news here though is, that if this turns out to be
non-ideal for the devicetree case we can still change things
as long as drivers/platform/x86/intel/int33fe/intel_cht_int33fe_typec.c
also gets updated so as to not break things.

> I think this means that the type-c node would have a 'displayport =
> <&some_phandle>' property in it that points to the display port hardware
> device that's pumping out the DisplayPort data?

It points to a fwnode belonging to the drm-connector for the DisplayPort
connector/pins to which the Type-C data-lines mux/switch is connected, see:

https://cgit.freedesktop.org/drm-misc/commit/?id=48c429c6d18db115c277b75000152d8fa4cd35d0
https://cgit.freedesktop.org/drm-misc/commit/?id=3d3f7c1e68691574c1d87cd0f9f2348323bc0199
https://cgit.freedesktop.org/drm-intel/commit/?id=a481d0e80eabbc3fed666103744aeaf47f63e708

So this get working with devicetree you would need something like this:

1. Have devicetree-node-s describing video-output connectors, similar
to how we have usb-connector nodes to describe usb-connectors

2. Have your drm/kms driver lookup these video-output-connector of_node-s
and assign them to drm_connector.fwnode, at least for the DP video-output
used.

3. Have the usb-connector node for your Type-C connector (the same of_node
as which has the source-pdos, sink-pdos, etc props) have a 
'displayport = <&some_phandle>' property pointing to the of_node for
the DP video-output used.

I hope this helps.

> 
>> +       if (IS_ERR(dp->connector_fwnode))
>> +               dp->connector_fwnode = NULL;
>> +
>>         typec_altmode_set_drvdata(alt, dp);
>>
>>         dp->state = DP_STATE_ENTER;
>> @@ -555,6 +571,13 @@ void dp_altmode_remove(struct typec_altmode *alt)
>>
>>         sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group);
>>         cancel_work_sync(&dp->work);
>> +
>> +       if (dp->connector_fwnode) {
>> +               if (dp->hpd)
>> +                       drm_connector_oob_hotplug_event(dp->connector_fwnode);
> 
> I was hoping that we could make a type-c connector into a drm_bridge.
> I'm thinking that it would be a DP-to-panel bridge. Then a panel could
> be created as well on the end of the type-c connector and the bridge
> would report hpd whenever the type-c logic figures out the cable has
> been connected and hpd is asserted. The actual DisplayPort hardware
> that's encoding data would then find the bridge through the graph
> binding connected to the output node.
> 
> I'm not sure how MST is handled though. In that scenario maybe there's
> more than one panel?

Yeah, given that MST over DP over Type-C is very much possible my
first instinct is that this drm_bridge + bridge-to-panel idea is
not going to work very well. Also the output could be anything, it
could be a projector, or the DP input of a video-grabber, or ...
so modelling this as a panel feels wrong.

Regards,

Hans


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

* Re: [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events
  2021-09-16 13:17     ` Hans de Goede
@ 2021-09-24 23:29       ` Stephen Boyd
  0 siblings, 0 replies; 18+ messages in thread
From: Stephen Boyd @ 2021-09-24 23:29 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Guenter Roeck, Hans de Goede,
	Heikki Krogerus, Imre Deak, Jani Nikula, Joonas Lahtinen, Lyude,
	Maarten Lankhorst, Maxime Ripard, Rodrigo Vivi,
	Thomas Zimmermann, pmalani, robh
  Cc: Daniel Vetter, David Airlie, intel-gfx, dri-devel, linux-usb,
	Laurent Pinchart

(Sorry for the slow reply)

Quoting Hans de Goede (2021-09-16 06:17:56)
> Hi,
>
> On 9/16/21 5:20 AM, Stephen Boyd wrote:
> > Quoting Hans de Goede (2021-08-17 14:52:01)
> >> diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
> >> index aa669b9cf70e..c1d8c23baa39 100644
> >> --- a/drivers/usb/typec/altmodes/displayport.c
> >> +++ b/drivers/usb/typec/altmodes/displayport.c
> >> @@ -125,6 +129,7 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
> >>  static int dp_altmode_status_update(struct dp_altmode *dp)
> >>  {
> >>         bool configured = !!DP_CONF_GET_PIN_ASSIGN(dp->data.conf);
> >> +       bool hpd = !!(dp->data.status & DP_STATUS_HPD_STATE);
> >>         u8 con = DP_STATUS_CONNECTION(dp->data.status);
> >>         int ret = 0;
> >>
> >> @@ -137,6 +142,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
> >>                 ret = dp_altmode_configure(dp, con);
> >>                 if (!ret)
> >>                         dp->state = DP_STATE_CONFIGURE;
> >> +       } else {
> >> +               if (dp->hpd != hpd) {
> >> +                       drm_connector_oob_hotplug_event(dp->connector_fwnode);
> >> +                       dp->hpd = hpd;
> >> +               }
> >>         }
> >>
> >>         return ret;
> >> @@ -512,6 +522,7 @@ static const struct attribute_group dp_altmode_group = {
> >>  int dp_altmode_probe(struct typec_altmode *alt)
> >>  {
> >>         const struct typec_altmode *port = typec_altmode_get_partner(alt);
> >> +       struct fwnode_handle *fwnode;
> >>         struct dp_altmode *dp;
> >>         int ret;
> >>
> >> @@ -540,6 +551,11 @@ int dp_altmode_probe(struct typec_altmode *alt)
> >>         alt->desc = "DisplayPort";
> >>         alt->ops = &dp_altmode_ops;
> >>
> >> +       fwnode = dev_fwnode(alt->dev.parent->parent); /* typec_port fwnode */
> >> +       dp->connector_fwnode = fwnode_find_reference(fwnode, "displayport", 0);
> >
> > I'm trying to figure out how to translate this over to DT bindings.
>
> First of all let me say that it is great that people are looking
> into using this functionality outside of the niche application
> for which I wrote it.

Glad to hear it! This sort of thing is the norm on ARM based SoCs. I
rarely ever see the HPD pin actually connected to the GPU/DPU hardware.
It almost always goes through some other chip and then software has to
deal with it by looking at the gpio or external hardware block, etc.

>
> > Is
> > there a binding document for this fwnode reference? If not, can you
> > please update
> > Documentation/devicetree/bindings/connector/usb-connector.yaml with this
> > property?
>
> My use case is some Intel Cherry Trail based mini-laptops which use a
> Intel Whiskey Cove PMIC with a FUSB302 Type-C controller + a
> PI3USB30532 USB switch, specifically the GPD Win and GPD Pocket
> (first generation of each).
>
> These are ACPI/X86 devices so devicetree is not used there, the
> connector_fwnode checked here is actually sw_node, this sw_node
> reference gets setup here:
>
> drivers/platform/x86/intel/int33fe/intel_cht_int33fe_typec.c
>
> The setup/use of a sw_node reference for this was actually
> designed by Heikki (in the Cc already), so he might be a better
> person to answer your questions.

Ok, thanks for the background.

>
> With that said, as to your question if I can document this in
> usb-connector.yaml, no I cannot (sorry). Since this is a sw_node
> setup by X86 code and not a normal devicetree fwnode reference,
> atm this is purely a kernel internal API/binding really and the
> DT-binding maintainers have repeatedly told me that I should NOT
> submit DT-binding updates for these. Only once a real devicetree
> user for this shows up will the accept DT-bindings patches for this.
>
> The good news here though is, that if this turns out to be
> non-ideal for the devicetree case we can still change things
> as long as drivers/platform/x86/intel/int33fe/intel_cht_int33fe_typec.c
> also gets updated so as to not break things.

I see. At least there's an escape hatch.

>
> > I think this means that the type-c node would have a 'displayport =
> > <&some_phandle>' property in it that points to the display port hardware
> > device that's pumping out the DisplayPort data?
>
> It points to a fwnode belonging to the drm-connector for the DisplayPort
> connector/pins to which the Type-C data-lines mux/switch is connected, see:
>
> https://cgit.freedesktop.org/drm-misc/commit/?id=48c429c6d18db115c277b75000152d8fa4cd35d0
> https://cgit.freedesktop.org/drm-misc/commit/?id=3d3f7c1e68691574c1d87cd0f9f2348323bc0199
> https://cgit.freedesktop.org/drm-intel/commit/?id=a481d0e80eabbc3fed666103744aeaf47f63e708
>
> So this get working with devicetree you would need something like this:
>
> 1. Have devicetree-node-s describing video-output connectors, similar
> to how we have usb-connector nodes to describe usb-connectors
>
> 2. Have your drm/kms driver lookup these video-output-connector of_node-s
> and assign them to drm_connector.fwnode, at least for the DP video-output
> used.
>
> 3. Have the usb-connector node for your Type-C connector (the same of_node
> as which has the source-pdos, sink-pdos, etc props) have a
> 'displayport = <&some_phandle>' property pointing to the of_node for
> the DP video-output used.
>
> I hope this helps.

Yep. For DT we already have a graph binding to show the output of the
display hardware (DPU). Right now it's not connected to anything though.

I'm currently thinking that a clean solution is to connect that graph
endpoint to some mux node and then have the mux node connect to each
type-c node. Then a driver that registers the mux and type-c connectors
can generate a drm_bridge instance (or instances) and drm can chain them
all together by walking the graph and connecting the DPU to the mux
bridge and then each type-c connector's bridge. I don't know how a mux
would work in the drm bridge design, so either that becomes a first
class type of operation or we register two bridges in the mux driver and
mux in the backend.

This feels similar to how we handle DSI-to-eDP bridges, except that the
end of the bridge chain is a type-c connector that could have MST to
deal with. I'm not super familiar with MST but maybe MST could also
become bridge aware and then we wouldn't have to do anything special.
I'll cross that bridge when I come to it.

I image the DPU would search the graph for a panel and then if there
isn't a panel downstream I think it would make one up, or do nothing?
I'm not very sure about this part either.

Anyway, I'm going to try to prototype out some code to do this unless
someone wants to say it's a terrible idea. Let me know.

>
> >
> >> +       if (IS_ERR(dp->connector_fwnode))
> >> +               dp->connector_fwnode = NULL;
> >> +
> >>         typec_altmode_set_drvdata(alt, dp);
> >>
> >>         dp->state = DP_STATE_ENTER;
> >> @@ -555,6 +571,13 @@ void dp_altmode_remove(struct typec_altmode *alt)
> >>
> >>         sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group);
> >>         cancel_work_sync(&dp->work);
> >> +
> >> +       if (dp->connector_fwnode) {
> >> +               if (dp->hpd)
> >> +                       drm_connector_oob_hotplug_event(dp->connector_fwnode);
> >
> > I was hoping that we could make a type-c connector into a drm_bridge.
> > I'm thinking that it would be a DP-to-panel bridge. Then a panel could
> > be created as well on the end of the type-c connector and the bridge
> > would report hpd whenever the type-c logic figures out the cable has
> > been connected and hpd is asserted. The actual DisplayPort hardware
> > that's encoding data would then find the bridge through the graph
> > binding connected to the output node.
> >
> > I'm not sure how MST is handled though. In that scenario maybe there's
> > more than one panel?
>
> Yeah, given that MST over DP over Type-C is very much possible my
> first instinct is that this drm_bridge + bridge-to-panel idea is
> not going to work very well. Also the output could be anything, it
> could be a projector, or the DP input of a video-grabber, or ...
> so modelling this as a panel feels wrong.

Agreed. I suppose making a panel in the connector is the wrong
direction, but making a bridge there should be OK.

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

* Re: [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events
  2021-06-04 19:48 ` [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events Hans de Goede
@ 2021-06-15  7:40   ` Greg Kroah-Hartman
  0 siblings, 0 replies; 18+ messages in thread
From: Greg Kroah-Hartman @ 2021-06-15  7:40 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Daniel Vetter, David Airlie, Jani Nikula, Joonas Lahtinen,
	Rodrigo Vivi, Imre Deak, Guenter Roeck, Heikki Krogerus,
	intel-gfx, dri-devel, platform-driver-x86, linux-usb

On Fri, Jun 04, 2021 at 09:48:40PM +0200, Hans de Goede wrote:
> Use the new drm_connector_oob_hotplug_event() functions to let drm/kms
> drivers know about DisplayPort over Type-C hotplug events.
> 
> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Tested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

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

* [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events
  2021-06-04 19:48 [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4) Hans de Goede
@ 2021-06-04 19:48 ` Hans de Goede
  2021-06-15  7:40   ` Greg Kroah-Hartman
  0 siblings, 1 reply; 18+ messages in thread
From: Hans de Goede @ 2021-06-04 19:48 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Daniel Vetter, David Airlie, Jani Nikula, Joonas Lahtinen,
	Rodrigo Vivi, Imre Deak, Greg Kroah-Hartman, Guenter Roeck,
	Heikki Krogerus
  Cc: Hans de Goede, intel-gfx, dri-devel, platform-driver-x86, linux-usb

Use the new drm_connector_oob_hotplug_event() functions to let drm/kms
drivers know about DisplayPort over Type-C hotplug events.

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Tested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Changes in v3:
- Only call drm_connector_oob_hotplug_event() on hpd status bit change
- Adjust for drm_connector_oob_hotplug_event() no longer having a data
  argument

Changes in v2:
- Add missing depends on DRM to TYPEC_DP_ALTMODE Kconfig entry
---
 drivers/usb/typec/altmodes/Kconfig       |  1 +
 drivers/usb/typec/altmodes/displayport.c | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/drivers/usb/typec/altmodes/Kconfig b/drivers/usb/typec/altmodes/Kconfig
index 60d375e9c3c7..1a6b5e872b0d 100644
--- a/drivers/usb/typec/altmodes/Kconfig
+++ b/drivers/usb/typec/altmodes/Kconfig
@@ -4,6 +4,7 @@ menu "USB Type-C Alternate Mode drivers"
 
 config TYPEC_DP_ALTMODE
 	tristate "DisplayPort Alternate Mode driver"
+	depends on DRM
 	help
 	  DisplayPort USB Type-C Alternate Mode allows DisplayPort
 	  displays and adapters to be attached to the USB Type-C
diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index aa669b9cf70e..c1d8c23baa39 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -11,8 +11,10 @@
 #include <linux/delay.h>
 #include <linux/mutex.h>
 #include <linux/module.h>
+#include <linux/property.h>
 #include <linux/usb/pd_vdo.h>
 #include <linux/usb/typec_dp.h>
+#include <drm/drm_connector.h>
 #include "displayport.h"
 
 #define DP_HEADER(_dp, ver, cmd)	(VDO((_dp)->alt->svid, 1, ver, cmd)	\
@@ -57,11 +59,13 @@ struct dp_altmode {
 	struct typec_displayport_data data;
 
 	enum dp_state state;
+	bool hpd;
 
 	struct mutex lock; /* device lock */
 	struct work_struct work;
 	struct typec_altmode *alt;
 	const struct typec_altmode *port;
+	struct fwnode_handle *connector_fwnode;
 };
 
 static int dp_altmode_notify(struct dp_altmode *dp)
@@ -125,6 +129,7 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
 static int dp_altmode_status_update(struct dp_altmode *dp)
 {
 	bool configured = !!DP_CONF_GET_PIN_ASSIGN(dp->data.conf);
+	bool hpd = !!(dp->data.status & DP_STATUS_HPD_STATE);
 	u8 con = DP_STATUS_CONNECTION(dp->data.status);
 	int ret = 0;
 
@@ -137,6 +142,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
 		ret = dp_altmode_configure(dp, con);
 		if (!ret)
 			dp->state = DP_STATE_CONFIGURE;
+	} else {
+		if (dp->hpd != hpd) {
+			drm_connector_oob_hotplug_event(dp->connector_fwnode);
+			dp->hpd = hpd;
+		}
 	}
 
 	return ret;
@@ -512,6 +522,7 @@ static const struct attribute_group dp_altmode_group = {
 int dp_altmode_probe(struct typec_altmode *alt)
 {
 	const struct typec_altmode *port = typec_altmode_get_partner(alt);
+	struct fwnode_handle *fwnode;
 	struct dp_altmode *dp;
 	int ret;
 
@@ -540,6 +551,11 @@ int dp_altmode_probe(struct typec_altmode *alt)
 	alt->desc = "DisplayPort";
 	alt->ops = &dp_altmode_ops;
 
+	fwnode = dev_fwnode(alt->dev.parent->parent); /* typec_port fwnode */
+	dp->connector_fwnode = fwnode_find_reference(fwnode, "displayport", 0);
+	if (IS_ERR(dp->connector_fwnode))
+		dp->connector_fwnode = NULL;
+
 	typec_altmode_set_drvdata(alt, dp);
 
 	dp->state = DP_STATE_ENTER;
@@ -555,6 +571,13 @@ void dp_altmode_remove(struct typec_altmode *alt)
 
 	sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group);
 	cancel_work_sync(&dp->work);
+
+	if (dp->connector_fwnode) {
+		if (dp->hpd)
+			drm_connector_oob_hotplug_event(dp->connector_fwnode);
+
+		fwnode_handle_put(dp->connector_fwnode);
+	}
 }
 EXPORT_SYMBOL_GPL(dp_altmode_remove);
 
-- 
2.31.1


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

* Re: [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events
  2021-05-05 16:24 ` [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events Hans de Goede
@ 2021-05-11  6:56   ` Heikki Krogerus
  0 siblings, 0 replies; 18+ messages in thread
From: Heikki Krogerus @ 2021-05-11  6:56 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Daniel Vetter, David Airlie, Jani Nikula, Joonas Lahtinen,
	Rodrigo Vivi, Imre Deak, Greg Kroah-Hartman, Guenter Roeck,
	intel-gfx, dri-devel, platform-driver-x86, linux-usb

On Wed, May 05, 2021 at 06:24:15PM +0200, Hans de Goede wrote:
> Use the new drm_connector_oob_hotplug_event() functions to let drm/kms
> drivers know about DisplayPort over Type-C hotplug events.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> ---
> Changes in v3:
> - Only call drm_connector_oob_hotplug_event() on hpd status bit change
> - Adjust for drm_connector_oob_hotplug_event() no longer having a data
>   argument
> 
> Changes in v2:
> - Add missing depends on DRM to TYPEC_DP_ALTMODE Kconfig entry
> ---
>  drivers/usb/typec/altmodes/Kconfig       |  1 +
>  drivers/usb/typec/altmodes/displayport.c | 23 +++++++++++++++++++++++
>  2 files changed, 24 insertions(+)
> 
> diff --git a/drivers/usb/typec/altmodes/Kconfig b/drivers/usb/typec/altmodes/Kconfig
> index 60d375e9c3c7..1a6b5e872b0d 100644
> --- a/drivers/usb/typec/altmodes/Kconfig
> +++ b/drivers/usb/typec/altmodes/Kconfig
> @@ -4,6 +4,7 @@ menu "USB Type-C Alternate Mode drivers"
>  
>  config TYPEC_DP_ALTMODE
>  	tristate "DisplayPort Alternate Mode driver"
> +	depends on DRM
>  	help
>  	  DisplayPort USB Type-C Alternate Mode allows DisplayPort
>  	  displays and adapters to be attached to the USB Type-C
> diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
> index aa669b9cf70e..c1d8c23baa39 100644
> --- a/drivers/usb/typec/altmodes/displayport.c
> +++ b/drivers/usb/typec/altmodes/displayport.c
> @@ -11,8 +11,10 @@
>  #include <linux/delay.h>
>  #include <linux/mutex.h>
>  #include <linux/module.h>
> +#include <linux/property.h>
>  #include <linux/usb/pd_vdo.h>
>  #include <linux/usb/typec_dp.h>
> +#include <drm/drm_connector.h>
>  #include "displayport.h"
>  
>  #define DP_HEADER(_dp, ver, cmd)	(VDO((_dp)->alt->svid, 1, ver, cmd)	\
> @@ -57,11 +59,13 @@ struct dp_altmode {
>  	struct typec_displayport_data data;
>  
>  	enum dp_state state;
> +	bool hpd;
>  
>  	struct mutex lock; /* device lock */
>  	struct work_struct work;
>  	struct typec_altmode *alt;
>  	const struct typec_altmode *port;
> +	struct fwnode_handle *connector_fwnode;
>  };
>  
>  static int dp_altmode_notify(struct dp_altmode *dp)
> @@ -125,6 +129,7 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
>  static int dp_altmode_status_update(struct dp_altmode *dp)
>  {
>  	bool configured = !!DP_CONF_GET_PIN_ASSIGN(dp->data.conf);
> +	bool hpd = !!(dp->data.status & DP_STATUS_HPD_STATE);
>  	u8 con = DP_STATUS_CONNECTION(dp->data.status);
>  	int ret = 0;
>  
> @@ -137,6 +142,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
>  		ret = dp_altmode_configure(dp, con);
>  		if (!ret)
>  			dp->state = DP_STATE_CONFIGURE;
> +	} else {
> +		if (dp->hpd != hpd) {
> +			drm_connector_oob_hotplug_event(dp->connector_fwnode);
> +			dp->hpd = hpd;
> +		}
>  	}
>  
>  	return ret;
> @@ -512,6 +522,7 @@ static const struct attribute_group dp_altmode_group = {
>  int dp_altmode_probe(struct typec_altmode *alt)
>  {
>  	const struct typec_altmode *port = typec_altmode_get_partner(alt);
> +	struct fwnode_handle *fwnode;
>  	struct dp_altmode *dp;
>  	int ret;
>  
> @@ -540,6 +551,11 @@ int dp_altmode_probe(struct typec_altmode *alt)
>  	alt->desc = "DisplayPort";
>  	alt->ops = &dp_altmode_ops;
>  
> +	fwnode = dev_fwnode(alt->dev.parent->parent); /* typec_port fwnode */
> +	dp->connector_fwnode = fwnode_find_reference(fwnode, "displayport", 0);
> +	if (IS_ERR(dp->connector_fwnode))
> +		dp->connector_fwnode = NULL;
> +
>  	typec_altmode_set_drvdata(alt, dp);
>  
>  	dp->state = DP_STATE_ENTER;
> @@ -555,6 +571,13 @@ void dp_altmode_remove(struct typec_altmode *alt)
>  
>  	sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group);
>  	cancel_work_sync(&dp->work);
> +
> +	if (dp->connector_fwnode) {
> +		if (dp->hpd)
> +			drm_connector_oob_hotplug_event(dp->connector_fwnode);
> +
> +		fwnode_handle_put(dp->connector_fwnode);
> +	}
>  }
>  EXPORT_SYMBOL_GPL(dp_altmode_remove);
>  
> -- 
> 2.31.1

-- 
heikki

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

* [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events
  2021-05-05 16:24 [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v3) Hans de Goede
@ 2021-05-05 16:24 ` Hans de Goede
  2021-05-11  6:56   ` Heikki Krogerus
  0 siblings, 1 reply; 18+ messages in thread
From: Hans de Goede @ 2021-05-05 16:24 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	Daniel Vetter, David Airlie, Jani Nikula, Joonas Lahtinen,
	Rodrigo Vivi, Imre Deak, Greg Kroah-Hartman, Guenter Roeck,
	Heikki Krogerus
  Cc: Hans de Goede, intel-gfx, dri-devel, platform-driver-x86, linux-usb

Use the new drm_connector_oob_hotplug_event() functions to let drm/kms
drivers know about DisplayPort over Type-C hotplug events.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Changes in v3:
- Only call drm_connector_oob_hotplug_event() on hpd status bit change
- Adjust for drm_connector_oob_hotplug_event() no longer having a data
  argument

Changes in v2:
- Add missing depends on DRM to TYPEC_DP_ALTMODE Kconfig entry
---
 drivers/usb/typec/altmodes/Kconfig       |  1 +
 drivers/usb/typec/altmodes/displayport.c | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/drivers/usb/typec/altmodes/Kconfig b/drivers/usb/typec/altmodes/Kconfig
index 60d375e9c3c7..1a6b5e872b0d 100644
--- a/drivers/usb/typec/altmodes/Kconfig
+++ b/drivers/usb/typec/altmodes/Kconfig
@@ -4,6 +4,7 @@ menu "USB Type-C Alternate Mode drivers"
 
 config TYPEC_DP_ALTMODE
 	tristate "DisplayPort Alternate Mode driver"
+	depends on DRM
 	help
 	  DisplayPort USB Type-C Alternate Mode allows DisplayPort
 	  displays and adapters to be attached to the USB Type-C
diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index aa669b9cf70e..c1d8c23baa39 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -11,8 +11,10 @@
 #include <linux/delay.h>
 #include <linux/mutex.h>
 #include <linux/module.h>
+#include <linux/property.h>
 #include <linux/usb/pd_vdo.h>
 #include <linux/usb/typec_dp.h>
+#include <drm/drm_connector.h>
 #include "displayport.h"
 
 #define DP_HEADER(_dp, ver, cmd)	(VDO((_dp)->alt->svid, 1, ver, cmd)	\
@@ -57,11 +59,13 @@ struct dp_altmode {
 	struct typec_displayport_data data;
 
 	enum dp_state state;
+	bool hpd;
 
 	struct mutex lock; /* device lock */
 	struct work_struct work;
 	struct typec_altmode *alt;
 	const struct typec_altmode *port;
+	struct fwnode_handle *connector_fwnode;
 };
 
 static int dp_altmode_notify(struct dp_altmode *dp)
@@ -125,6 +129,7 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con)
 static int dp_altmode_status_update(struct dp_altmode *dp)
 {
 	bool configured = !!DP_CONF_GET_PIN_ASSIGN(dp->data.conf);
+	bool hpd = !!(dp->data.status & DP_STATUS_HPD_STATE);
 	u8 con = DP_STATUS_CONNECTION(dp->data.status);
 	int ret = 0;
 
@@ -137,6 +142,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp)
 		ret = dp_altmode_configure(dp, con);
 		if (!ret)
 			dp->state = DP_STATE_CONFIGURE;
+	} else {
+		if (dp->hpd != hpd) {
+			drm_connector_oob_hotplug_event(dp->connector_fwnode);
+			dp->hpd = hpd;
+		}
 	}
 
 	return ret;
@@ -512,6 +522,7 @@ static const struct attribute_group dp_altmode_group = {
 int dp_altmode_probe(struct typec_altmode *alt)
 {
 	const struct typec_altmode *port = typec_altmode_get_partner(alt);
+	struct fwnode_handle *fwnode;
 	struct dp_altmode *dp;
 	int ret;
 
@@ -540,6 +551,11 @@ int dp_altmode_probe(struct typec_altmode *alt)
 	alt->desc = "DisplayPort";
 	alt->ops = &dp_altmode_ops;
 
+	fwnode = dev_fwnode(alt->dev.parent->parent); /* typec_port fwnode */
+	dp->connector_fwnode = fwnode_find_reference(fwnode, "displayport", 0);
+	if (IS_ERR(dp->connector_fwnode))
+		dp->connector_fwnode = NULL;
+
 	typec_altmode_set_drvdata(alt, dp);
 
 	dp->state = DP_STATE_ENTER;
@@ -555,6 +571,13 @@ void dp_altmode_remove(struct typec_altmode *alt)
 
 	sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group);
 	cancel_work_sync(&dp->work);
+
+	if (dp->connector_fwnode) {
+		if (dp->hpd)
+			drm_connector_oob_hotplug_event(dp->connector_fwnode);
+
+		fwnode_handle_put(dp->connector_fwnode);
+	}
 }
 EXPORT_SYMBOL_GPL(dp_altmode_remove);
 
-- 
2.31.1


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

end of thread, other threads:[~2021-09-24 23:29 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-17 21:51 [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend) Hans de Goede
2021-08-17 21:51 ` [PATCH 1/8] drm/connector: Give connector sysfs devices there own device_type Hans de Goede
2021-08-18 21:35   ` Lyude Paul
2021-08-17 21:51 ` [PATCH 2/8] drm/connector: Add a fwnode pointer to drm_connector and register with ACPI (v2) Hans de Goede
2021-08-17 21:51 ` [PATCH 3/8] drm/connector: Add drm_connector_find_by_fwnode() function (v3) Hans de Goede
2021-08-17 21:51 ` [PATCH 4/8] drm/connector: Add support for out-of-band hotplug notification (v3) Hans de Goede
2021-08-17 21:51 ` [PATCH 5/8] drm/i915: Associate ACPI connector nodes with connector entries (v2) Hans de Goede
2021-08-17 21:51 ` [PATCH 6/8] drm/i915/dp: Add support for out-of-bound hotplug events Hans de Goede
2021-08-17 21:52 ` [PATCH 7/8] usb: typec: altmodes/displayport: Make dp_altmode_notify() more generic Hans de Goede
2021-08-17 21:52 ` [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events Hans de Goede
2021-09-16  3:20   ` Stephen Boyd
2021-09-16 13:17     ` Hans de Goede
2021-09-24 23:29       ` Stephen Boyd
2021-08-18 22:03 ` [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4 resend) Lyude Paul
  -- strict thread matches above, loose matches on Subject: below --
2021-06-04 19:48 [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v4) Hans de Goede
2021-06-04 19:48 ` [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events Hans de Goede
2021-06-15  7:40   ` Greg Kroah-Hartman
2021-05-05 16:24 [PATCH 0/8] drm + usb-type-c: Add support for out-of-band hotplug notification (v3) Hans de Goede
2021-05-05 16:24 ` [PATCH 8/8] usb: typec: altmodes/displayport: Notify drm subsys of hotplug events Hans de Goede
2021-05-11  6:56   ` Heikki Krogerus

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).