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>
Mon, 7 Feb 2022 07:12:46 +0000 (16:12 +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

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

index f1e0e00..54b588f 100644 (file)
@@ -38,6 +38,7 @@
 #include <drm/drm_scdc_helper.h>
 #include <linux/clk.h>
 #include <linux/component.h>
+#include <linux/extcon-provider.h>
 #include <linux/i2c.h>
 #include <linux/of_address.h>
 #include <linux/of_gpio.h>
@@ -242,6 +243,7 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
        struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
        enum drm_connector_status ret = connector_status_disconnected;
        bool connected = false;
+       enum drm_connector_status status;
 
        mutex_lock(&vc4_hdmi->mutex);
 
@@ -283,6 +285,15 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
 out:
        pm_runtime_put(&vc4_hdmi->pdev->dev);
        mutex_unlock(&vc4_hdmi->mutex);
+
+#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
        return ret;
 }
 
@@ -3042,6 +3053,13 @@ static int vc4_hdmi_runtime_resume(struct device *dev)
 }
 #endif
 
+#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);
@@ -3097,6 +3115,23 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
                return -EPROBE_DEFER;
        }
 
+#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 fa57d85..2492353 100644 (file)
@@ -24,6 +24,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,
@@ -262,6 +266,11 @@ struct vc4_hdmi {
         * for use outside of KMS hooks. Protected by @mutex.
         */
        int broadcast_rgb;
+
+#ifdef CONFIG_EXTCON
+       enum drm_connector_status status;
+       struct extcon_dev *edev;
+#endif
 };
 
 static inline struct vc4_hdmi *