drm/vc4: add extcon hdmi connection uevent
authorSeung-Woo Kim <sw0312.kim@samsung.com>
Tue, 30 Jun 2020 05:32:02 +0000 (14:32 +0900)
committerHoegeun Kwon <hoegeun.kwon@samsung.com>
Thu, 3 Aug 2023 08:46:03 +0000 (17:46 +0900)
Add extcon hdmi connection and disconnection uevent when extcon
module is enabled.

The vc4_hdmi detection is done by polling way, so extcon uevent
for connection is a bit slow after changing real hdmi cable state.

Change-Id: I962f7a39b7a3344f9793e436ef28c36b123571a8
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Signed-off-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
 Conflicts:
drivers/gpu/drm/vc4/vc4_hdmi.h
drivers/gpu/drm/vc4/vc4_hdmi.c

Signed-off-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/gpu/drm/vc4/vc4_hdmi.h

index 65868eb..8c0c0b5 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/gpio/consumer.h>
+#include <linux/extcon-provider.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -412,6 +413,7 @@ static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi,
 {
        struct drm_connector *connector = &vc4_hdmi->connector;
        struct edid *edid;
+       int ret;
 
        /*
         * NOTE: This function should really be called with
@@ -445,6 +447,15 @@ static void vc4_hdmi_handle_hotplug(struct vc4_hdmi *vc4_hdmi,
        kfree(edid);
 
        vc4_hdmi_reset_link(connector, ctx);
+
+#ifdef CONFIG_EXTCON
+       if (ret != vc4_hdmi->status) {
+               extcon_set_state_sync(vc4_hdmi->edev, EXTCON_DISP_HDMI,
+                                     (status == connector_status_connected ?
+                                     true : false));
+               vc4_hdmi->status = ret;
+       }
+#endif
 }
 
 static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector,
@@ -3642,6 +3653,13 @@ static void vc4_hdmi_put_ddc_device(void *ptr)
        put_device(&vc4_hdmi->ddc->dev);
 }
 
+#ifdef CONFIG_EXTCON
+static const unsigned int vc4_hdmi_extcon_cable[] = {
+       EXTCON_DISP_HDMI,
+       EXTCON_NONE,
+};
+#endif
+
 static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
        const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
@@ -3704,6 +3722,23 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
        if (ret)
                return ret;
 
+#ifdef CONFIG_EXTCON
+       vc4_hdmi->status = connector_status_disconnected;
+
+       /* Initialize extcon device */
+       vc4_hdmi->edev = devm_extcon_dev_allocate(dev, vc4_hdmi_extcon_cable);
+       if (IS_ERR(vc4_hdmi->edev)) {
+               dev_err(dev, "failed to allocate memory for extcon\n");
+               return PTR_ERR(vc4_hdmi->edev);
+       }
+
+       ret = devm_extcon_dev_register(dev, vc4_hdmi->edev);
+       if (ret) {
+               dev_err(dev, "failed to register extcon device\n");
+               return ret;
+       }
+#endif
+
        /* Only use the GPIO HPD pin if present in the DT, otherwise
         * we'll use the HDMI core's register.
         */
index 724b145..2c599db 100644 (file)
@@ -12,6 +12,10 @@ struct vc4_hdmi;
 struct vc4_hdmi_register;
 struct vc4_hdmi_connector_state;
 
+#ifdef CONFIG_EXTCON
+struct extcon_dev;
+#endif
+
 enum vc4_hdmi_phy_channel {
        PHY_LANE_0 = 0,
        PHY_LANE_1,
@@ -235,6 +239,11 @@ struct vc4_hdmi {
        struct debugfs_regset32 phy_regset;
        struct debugfs_regset32 ram_regset;
        struct debugfs_regset32 rm_regset;
+
+#ifdef CONFIG_EXTCON
+       enum drm_connector_status status;
+       struct extcon_dev *edev;
+#endif
 };
 
 static inline struct vc4_hdmi *