Reiplace HDMI unplug polling with HPD line reading.
authorStuart Abercrombie <sabercrombie@chromium.org>
Thu, 17 Jan 2013 00:52:17 +0000 (16:52 -0800)
committerChromeBot <chrome-bot@google.com>
Thu, 17 Jan 2013 02:31:52 +0000 (18:31 -0800)
It looked as if this didn't work at the HW level, but it actually does.
Polling cost us about 100mW if an HDMI monitor was attached.
This also responds more quickly to unplugging.

Based on upstream change:
http://lists.freedesktop.org/archives/intel-gfx/2012-December/023314.html

BUG=chromium-os:37674
TEST=HDMI hotplug works and responds immediately
Change-Id: I9e88671b1ac0e6204feda2666608f30427c8bb79
Reviewed-on: https://gerrit.chromium.org/gerrit/41474
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
Tested-by: Stuart Abercrombie <sabercrombie@chromium.org>
Commit-Queue: Stuart Abercrombie <sabercrombie@chromium.org>

drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/i915/intel_hdmi.c
include/drm/drm_crtc.h

index 678f1b8..ec8a192 100644 (file)
@@ -937,13 +937,9 @@ static void output_poll_execute(struct work_struct *work)
                   TV out for instance */
                if (!connector->polled)
                        continue;
-
-               if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT)) {
-                       if (connector->polled & DRM_CONNECTOR_POLL_DISCONNECT_ONLY)
-                               repoll = (connector->status == connector_status_connected);
-                       else
-                               repoll = true;
-               }
+               else if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
+                        DRM_CONNECTOR_POLL_DISCONNECT))
+                       repoll = true;
 
                old_status = connector->status;
                /* if we are connected and don't want to poll for disconnect
index 6f943d5..e2bd489 100644 (file)
@@ -336,6 +336,41 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
        return true;
 }
 
+/*
+ * intel_hdmi_hpd- is the specified port connected?
+ * @dev_priv: i915 private structure
+ * @intel_hdmi: the HDMI port to test
+ *
+ * Returns true if @intel_hdmi is connected, false otherwise.
+ */
+static bool intel_hdmi_hpd(struct drm_i915_private *dev_priv,
+                                          struct intel_hdmi *intel_hdmi)
+{
+       u32 bit;
+
+       /* XXX: IBX has different SDEISR bits */
+       if (HAS_PCH_IBX(dev_priv->dev))
+               return true;
+
+       switch (intel_hdmi->sdvox_reg) {
+       case HDMIB:
+       case SDVOB:
+               bit = SDE_PORTB_HOTPLUG_CPT;
+               break;
+       case HDMIC:
+       case SDVOC:
+               bit = SDE_PORTC_HOTPLUG_CPT;
+               break;
+       case HDMID:
+               bit = SDE_PORTD_HOTPLUG_CPT;
+               break;
+       default:
+               return true;
+       }
+
+       return I915_READ(SDEISR) & bit;
+}
+
 static enum drm_connector_status
 intel_hdmi_detect(struct drm_connector *connector, bool force)
 {
@@ -346,6 +381,11 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
 
        intel_hdmi->has_hdmi_sink = false;
        intel_hdmi->has_audio = false;
+
+       if (HAS_PCH_SPLIT(connector->dev) &&
+           !intel_hdmi_hpd(dev_priv, intel_hdmi))
+               return status;
+
        edid = drm_get_edid(connector,
                            intel_gmbus_get_adapter(dev_priv,
                                                    intel_hdmi->ddc_bus));
@@ -532,7 +572,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 
        intel_encoder->type = INTEL_OUTPUT_HDMI;
 
-       connector->polled = DRM_CONNECTOR_POLL_DISCONNECT | DRM_CONNECTOR_POLL_DISCONNECT_ONLY;
+       connector->polled = DRM_CONNECTOR_POLL_HPD;
        connector->interlace_allowed = 1;
        connector->doublescan_allowed = 0;
        intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
index 4abc198..f1a0764 100644 (file)
@@ -499,8 +499,6 @@ enum drm_connector_force {
 /* can cleanly poll for disconnections without flickering the screen */
 /* DACs should rarely do this without a lot of testing */
 #define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
-/* Only poll for disconnections. */
-#define DRM_CONNECTOR_POLL_DISCONNECT_ONLY (1 << 3)
 
 #define MAX_ELD_BYTES  128