From 3187deef82d1f7c9eeeb3f46c5a1879cd3e61be1 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Wed, 6 Nov 2019 11:06:59 +0800 Subject: [PATCH] drm: bridge: dw-hdmi: using extcon instead of switch Switch is no longer available in kernel 4.19, so we use extcon instead. the hdmi connect status node: /sys/class/extcon/extconX/state HDMI=0: hdmi is disconnected HDMI=1: hdmi is connected Change-Id: I806d8fd5b9b4b36f15aa6aec275fad2ecf122e91 Signed-off-by: Algea Cao --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 46 +++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 1a53af4564d0..99216b84c45c 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include #include @@ -49,6 +51,11 @@ #define HDMI14_MAX_TMDSCLK 340000000 +static const unsigned int dw_hdmi_cable[] = { + EXTCON_DISP_HDMI, + EXTCON_NONE, +}; + enum hdmi_datamap { RGB444_8B = 0x01, RGB444_10B = 0x03, @@ -256,6 +263,8 @@ struct dw_hdmi { unsigned int audio_n; bool audio_enable; + struct extcon_dev *extcon; + unsigned int reg_shift; struct regmap *regm; void (*enable_audio)(struct dw_hdmi *hdmi); @@ -334,6 +343,8 @@ static void repo_hpd_event(struct work_struct *p_work) drm_helper_hpd_irq_event(hdmi->bridge.dev); drm_bridge_hpd_notify(&hdmi->bridge, status); } + + extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, hdmi->hpd_state); } static bool check_hdmi_irq(struct dw_hdmi *hdmi, int intr_stat, @@ -2715,6 +2726,16 @@ static void dw_hdmi_connector_force(struct drm_connector *connector) connector); mutex_lock(&hdmi->mutex); + + if (!hdmi->disabled && hdmi->force != connector->force) { + if (connector->force == DRM_FORCE_OFF) + extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, + false); + else if (connector->force == DRM_FORCE_ON) + extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, + true); + } + hdmi->force = connector->force; dw_hdmi_update_power(hdmi); dw_hdmi_update_phy_mask(hdmi); @@ -3650,6 +3671,8 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, mutex_init(&hdmi->cec_notifier_mutex); spin_lock_init(&hdmi->audio_lock); + dev_set_name(dev, "hdmi"); + ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); if (ddc_node) { hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node); @@ -3874,6 +3897,29 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev, hdmi->cec = platform_device_register_full(&pdevinfo); } + hdmi->extcon = devm_extcon_dev_allocate(hdmi->dev, dw_hdmi_cable); + if (IS_ERR(hdmi->extcon)) { + ret = PTR_ERR(hdmi->extcon); + dev_err(hdmi->dev, "allocate extcon failed: %d\n", ret); + goto err_iahb; + } + + ret = devm_extcon_dev_register(hdmi->dev, hdmi->extcon); + if (ret) { + dev_err(hdmi->dev, "failed to register extcon: %d\n", + ret); + goto err_iahb; + } + + ret = extcon_set_property_capability(hdmi->extcon, EXTCON_DISP_HDMI, + EXTCON_PROP_DISP_HPD); + if (ret) { + dev_err(hdmi->dev, + "failed to set USB property capability: %d\n", + ret); + goto err_iahb; + } + drm_bridge_add(&hdmi->bridge); dw_hdmi_register_debugfs(dev, hdmi);