From f50de597dd9b4f84f6c41cec644c6dcad147e67a Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Tue, 30 Jun 2020 14:32:02 +0900 Subject: [PATCH] drm/vc4: add extcon hdmi connection uevent 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 Signed-off-by: Hoegeun Kwon --- drivers/gpu/drm/vc4/vc4_hdmi.c | 42 ++++++++++++++++++++++++++++++++++++++++-- drivers/gpu/drm/vc4/vc4_hdmi.h | 9 +++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 031d4e5..200f30b 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -114,6 +115,7 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) { struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); bool connected = false; + enum drm_connector_status status; if (vc4_hdmi->hpd_gpio) { if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^ @@ -134,10 +136,22 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) kfree(edid); } } - return connector_status_connected; + status = connector_status_connected; + goto out; } cec_phys_addr_invalidate(vc4_hdmi->cec_adap); - return connector_status_disconnected; + status = connector_status_disconnected; + +out: +#ifdef CONFIG_EXTCON + if (status != vc4_hdmi->status) { + extcon_set_state_sync(vc4_hdmi->edev, EXTCON_DISP_HDMI, + (status == connector_status_connected ? + true : false)); + vc4_hdmi->status = status; + } +#endif + return status; } static void vc4_hdmi_connector_destroy(struct drm_connector *connector) @@ -1640,6 +1654,13 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) return 0; } +#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) { struct platform_device *pdev = to_platform_device(dev); @@ -1677,6 +1698,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. */ diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 60f7bf9..c3125587 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -26,6 +26,10 @@ struct drm_display_mode; struct vc4_hdmi; struct vc4_hdmi_register; +#ifdef CONFIG_EXTCON +struct extcon_dev; +#endif + enum vc4_hdmi_phy_channel { PHY_LANE_0 = 0, PHY_LANE_1, @@ -161,6 +165,11 @@ struct vc4_hdmi { struct debugfs_regset32 hdmi_regset; struct debugfs_regset32 hd_regset; + +#ifdef CONFIG_EXTCON + enum drm_connector_status status; + struct extcon_dev *edev; +#endif }; static inline struct vc4_hdmi * -- 2.7.4