drm/msm/hdmi: Enable HPD after HDMI IRQ is set up
authorTodor Tomov <todor.tomov@linaro.org>
Fri, 19 Oct 2018 14:07:22 +0000 (17:07 +0300)
committerSean Paul <seanpaul@chromium.org>
Mon, 3 Dec 2018 13:46:13 +0000 (08:46 -0500)
SoCs that contain MDP5 have a top level wrapper called MDSS that
manages locks, power and irq for the sub-blocks within it.

Irq for HDMI is also routed through the MDSS.

Shortly after the Hot Plug Detection (HPD) is enabled in HDMI,
HDMI interrupts are recieved by the MDSS interrupt handler.
However at this moment the HDMI irq is still not mapped to
the MDSS irq domain so the HDMI irq handler cannot be called
to process the interrupts.

This leads to a flood of HDMI interrupts on CPU 0.

If we are lucky to have the HDMI initialization running on a
different CPU, it will eventually map the HDMI irq to MDSS irq
domain, the next HDMI interrupt will be handled by the HDMI irq
handler, the interrupt flood will stop and we will recover.

If the HDMI initialization is running on CPU 0, then it cannot
complete and there is nothing to stop the interrupt flood on
CPU 0. The system is stuck.

Fix this by moving the HPD enablement after the HDMI irq is
mapped to the MDSS irq domain.

Signed-off-by: Todor Tomov <todor.tomov@linaro.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Sean Paul <seanpaul@chromium.org>
drivers/gpu/drm/msm/hdmi/hdmi.c
drivers/gpu/drm/msm/hdmi/hdmi.h
drivers/gpu/drm/msm/hdmi/hdmi_connector.c

index c79659ca570655da77888052fc47a16bc53cf409..33e083f71a170e5c2c05823be647df5a1081fd7d 100644 (file)
@@ -332,6 +332,12 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
                goto fail;
        }
 
+       ret = msm_hdmi_hpd_enable(hdmi->connector);
+       if (ret < 0) {
+               DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);
+               goto fail;
+       }
+
        encoder->bridge = hdmi->bridge;
 
        priv->bridges[priv->num_bridges++]       = hdmi->bridge;
index accc9a61611d35bf9718d66fe09ce6c6e40a549f..5c5df6ab2a573421726a5ca69fbf619841c8303a 100644 (file)
@@ -245,6 +245,7 @@ void msm_hdmi_bridge_destroy(struct drm_bridge *bridge);
 
 void msm_hdmi_connector_irq(struct drm_connector *connector);
 struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi);
+int msm_hdmi_hpd_enable(struct drm_connector *connector);
 
 /*
  * i2c adapter for ddc:
index e9c9a0af508e8c41bc12e91fc13d2f23b5041f33..30e908dfded7ed888267d2c7a4a8211764fc6a22 100644 (file)
@@ -167,8 +167,9 @@ static void enable_hpd_clocks(struct hdmi *hdmi, bool enable)
        }
 }
 
-static int hpd_enable(struct hdmi_connector *hdmi_connector)
+int msm_hdmi_hpd_enable(struct drm_connector *connector)
 {
+       struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
        struct hdmi *hdmi = hdmi_connector->hdmi;
        const struct hdmi_platform_config *config = hdmi->config;
        struct device *dev = &hdmi->pdev->dev;
@@ -450,7 +451,6 @@ struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
 {
        struct drm_connector *connector = NULL;
        struct hdmi_connector *hdmi_connector;
-       int ret;
 
        hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);
        if (!hdmi_connector)
@@ -471,12 +471,6 @@ struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
        connector->interlace_allowed = 0;
        connector->doublescan_allowed = 0;
 
-       ret = hpd_enable(hdmi_connector);
-       if (ret) {
-               dev_err(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);
-               return ERR_PTR(ret);
-       }
-
        drm_connector_attach_encoder(connector, hdmi->encoder);
 
        return connector;