drm/msm/hdmi: use gpio and HPD polling
authorRob Clark <robdclark@gmail.com>
Mon, 19 May 2014 17:53:20 +0000 (13:53 -0400)
committerRob Clark <robdclark@gmail.com>
Fri, 30 May 2014 19:32:42 +0000 (15:32 -0400)
The hotplug detect and irq does not seem to be reliable on all devices
for some reason.  For now it is more reliable to use polling, and give
preference to raw gpio status if it disagrees with the debounced hpd
status.

Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/hdmi/hdmi_connector.c

index 7dedfdd120759d51c7bd5a940bb01e874b87f579..e56a6196867c6609c4940555d359cd898a4155bd 100644 (file)
@@ -247,36 +247,49 @@ void hdmi_connector_irq(struct drm_connector *connector)
        }
 }
 
+static enum drm_connector_status detect_reg(struct hdmi *hdmi)
+{
+       uint32_t hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
+       return (hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED) ?
+                       connector_status_connected : connector_status_disconnected;
+}
+
+static enum drm_connector_status detect_gpio(struct hdmi *hdmi)
+{
+       const struct hdmi_platform_config *config = hdmi->config;
+       return gpio_get_value(config->hpd_gpio) ?
+                       connector_status_connected :
+                       connector_status_disconnected;
+}
+
 static enum drm_connector_status hdmi_connector_detect(
                struct drm_connector *connector, bool force)
 {
        struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
        struct hdmi *hdmi = hdmi_connector->hdmi;
-       const struct hdmi_platform_config *config = hdmi->config;
-       uint32_t hpd_int_status;
+       enum drm_connector_status stat_gpio, stat_reg;
        int retry = 20;
 
-       hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
+       do {
+               stat_gpio = detect_gpio(hdmi);
+               stat_reg  = detect_reg(hdmi);
 
-       /* sense seems to in some cases be momentarily de-asserted, don't
-        * let that trick us into thinking the monitor is gone:
-        */
-       while (retry-- && !(hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED)) {
-               /* hdmi debounce logic seems to get stuck sometimes,
-                * read directly the gpio to get a second opinion:
-                */
-               if (gpio_get_value(config->hpd_gpio)) {
-                       DBG("gpio tells us we are connected!");
-                       hpd_int_status |= HDMI_HPD_INT_STATUS_CABLE_DETECTED;
+               if (stat_gpio == stat_reg)
                        break;
-               }
+
                mdelay(10);
-               hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
-               DBG("status=%08x", hpd_int_status);
+       } while (--retry);
+
+       /* the status we get from reading gpio seems to be more reliable,
+        * so trust that one the most if we didn't manage to get hdmi and
+        * gpio status to agree:
+        */
+       if (stat_gpio != stat_reg) {
+               DBG("HDMI_HPD_INT_STATUS tells us: %d", stat_reg);
+               DBG("hpd gpio tells us: %d", stat_gpio);
        }
 
-       return (hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED) ?
-                       connector_status_connected : connector_status_disconnected;
+       return stat_gpio;
 }
 
 static void hdmi_connector_destroy(struct drm_connector *connector)
@@ -389,7 +402,8 @@ struct drm_connector *hdmi_connector_init(struct hdmi *hdmi)
                        DRM_MODE_CONNECTOR_HDMIA);
        drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);
 
-       connector->polled = DRM_CONNECTOR_POLL_HPD;
+       connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+                       DRM_CONNECTOR_POLL_DISCONNECT;
 
        connector->interlace_allowed = 1;
        connector->doublescan_allowed = 0;
This page took 0.052423 seconds and 5 git commands to generate.