From f0038cffa843697501c442eff4468e3ab37031f1 Mon Sep 17 00:00:00 2001 From: Won Chung Date: Wed, 29 Mar 2023 01:44:55 +0000 Subject: drm/sysfs: Expose DRM connector id in each connector sysfs Expose DRM connector id in device sysfs so that we can map the connector id to the connector syspath. Currently, even if we can derive the connector id from modeset, we do not have a way to find the corresponding connector's syspath. This is helpful when determining the root connector of MST tree. When a tree of multiple MST hub is connected to the system, modeset describes the tree in the PATH blob. For example, consider the following scenario. +-------------+ | Source | +-------------+ | (Device) | | BranchX | | | | (MST) | | [conn6]--->| [port1]--->DisplayA +-------------+ | | | | +-------------+ | | | BranchY | | | | (MST) | | [port2]--->| [port1]----->DisplayB +-------------+ | | | [port2]----->DisplayC +-------------+ DPMST connector of DisplayA would have "mst:6-1" PATH. DPMST connector of DisplayB would have "mst:6-2-1" PATH. DPMST connector of DisplayC would have "mst:6-2-2" PATH. Given that connector id of 6 is the root of the MST connector tree, we can utilize this patch to parse through DRM connectors sysfs and find which connector syspath corresponds to the root connector (id == 6). ChromeOS intend to use this information for metrics collection. For example, we want to tell which port is deriving which displays even with a MST hub. Chromium patch for parsing DRM connector id from the kernel is at http://crrev.com/c/4317207. Signed-off-by: Won Chung Reviewed-by: Manasi Navare Signed-off-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20230329014455.1990104-1-wonchung@google.com --- drivers/gpu/drm/drm_sysfs.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/gpu/drm/drm_sysfs.c') diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 183130355997..11f98c5d6103 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -282,16 +282,27 @@ static ssize_t modes_show(struct device *device, return written; } +static ssize_t connector_id_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + struct drm_connector *connector = to_drm_connector(device); + + return sysfs_emit(buf, "%d\n", connector->base.id); +} + static DEVICE_ATTR_RW(status); static DEVICE_ATTR_RO(enabled); static DEVICE_ATTR_RO(dpms); static DEVICE_ATTR_RO(modes); +static DEVICE_ATTR_RO(connector_id); static struct attribute *connector_dev_attrs[] = { &dev_attr_status.attr, &dev_attr_enabled.attr, &dev_attr_dpms.attr, &dev_attr_modes.attr, + &dev_attr_connector_id.attr, NULL }; -- cgit v1.2.3 From c5c51b2420625faa1f0e363f21dba1de53806ff7 Mon Sep 17 00:00:00 2001 From: Won Chung Date: Thu, 27 Apr 2023 16:58:13 +0000 Subject: drm/sysfs: Link DRM connectors to corresponding Type-C connectors Create a symlink pointing to USB Type-C connector for DRM connectors when they are created. The link will be created only if the firmware is able to describe the connection beween the two connectors. Currently, even if a display uses a USB Type-C port, there is no way for the userspace to find which port is used for which display. With the symlink, display information would be accessible from Type-C connectors and port information would be accessible from DRM connectors. Associating the two subsystems, userspace would have potential to expose and utilize more complex information. ChromeOS intend to use this information for metrics collection. For example, we want to tell which port is deriving which displays. Also, combined with USB PD information, we can tell whether user is charging their device through display. Chromium patch for parsing the symlink from the kernel is at http://crrev.com/c/4317207. We already have a framework in typec port-mapper.c where it goes through component devices and runs the bind functions for those with matching _PLD (physical location of device). https://elixir.bootlin.com/linux/v5.18.1/source/drivers/usb/typec/ port-mapper.c Since _PLD is ACPI specific field, this linking would only work on ACPI x86 as long as _PLD field for Type-C connectors and DRM connectors are correctly added to the firmware. Currently, USB ports and USB4 ports are added as components to create a symlink with Type C connector. USB: https://lore.kernel.org/all/20211223082349.45616-1-heikki.krogerus @linux.intel.com/ USB4: https://lore.kernel.org/all/20220418175932.1809770-3-wonchung@google.com/ So, we follow the same pattern in this patch. Signed-off-by: Won Chung Acked-by: Heikki Krogerus Reviewed-by: Manasi Navare Signed-off-by: Manasi Navare Link: https://patchwork.freedesktop.org/patch/msgid/20230427165813.2844530-1-wonchung@google.com --- drivers/gpu/drm/drm_sysfs.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'drivers/gpu/drm/drm_sysfs.c') diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 11f98c5d6103..62ce80b3eebc 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -11,12 +11,14 @@ */ #include +#include #include #include #include #include #include #include +#include #include #include @@ -96,6 +98,34 @@ static char *drm_devnode(const struct device *dev, umode_t *mode) return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev)); } +static int typec_connector_bind(struct device *dev, + struct device *typec_connector, void *data) +{ + int ret; + + ret = sysfs_create_link(&dev->kobj, &typec_connector->kobj, "typec_connector"); + if (ret) + return ret; + + ret = sysfs_create_link(&typec_connector->kobj, &dev->kobj, "drm_connector"); + if (ret) + sysfs_remove_link(&dev->kobj, "typec_connector"); + + return ret; +} + +static void typec_connector_unbind(struct device *dev, + struct device *typec_connector, void *data) +{ + sysfs_remove_link(&typec_connector->kobj, "drm_connector"); + sysfs_remove_link(&dev->kobj, "typec_connector"); +} + +static const struct component_ops typec_connector_ops = { + .bind = typec_connector_bind, + .unbind = typec_connector_unbind, +}; + static CLASS_ATTR_STRING(version, S_IRUGO, "drm 1.1.0 20060810"); /** @@ -364,9 +394,16 @@ int drm_sysfs_connector_add(struct drm_connector *connector) connector->kdev = kdev; + if (dev_fwnode(kdev)) { + r = component_add(kdev, &typec_connector_ops); + if (r) + drm_err(dev, "failed to add component to create link to typec connector\n"); + } + if (connector->ddc) return sysfs_create_link(&connector->kdev->kobj, &connector->ddc->dev.kobj, "ddc"); + return 0; err_free: @@ -382,6 +419,9 @@ void drm_sysfs_connector_remove(struct drm_connector *connector) if (connector->ddc) sysfs_remove_link(&connector->kdev->kobj, "ddc"); + if (dev_fwnode(connector->kdev)) + component_del(connector->kdev, &typec_connector_ops); + DRM_DEBUG("removing \"%s\" from sysfs\n", connector->name); -- cgit v1.2.3