Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/hch/vfs...
[pandora-kernel.git] / drivers / gpu / drm / i915 / intel_sdvo.c
index aa94110..6db3b1c 100644 (file)
@@ -92,6 +92,11 @@ struct intel_sdvo {
        */
        uint16_t attached_output;
 
+       /*
+        * Hotplug activation bits for this device
+        */
+       uint8_t hotplug_active[2];
+
        /**
         * This is used to select the color range of RBG outputs in HDMI mode.
         * It is only valid when using TMDS encoding and 8 bit per color mode.
@@ -1208,81 +1213,26 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in
        return true;
 }
 
-/* No use! */
-#if 0
-struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB)
-{
-       struct drm_connector *connector = NULL;
-       struct intel_sdvo *iout = NULL;
-       struct intel_sdvo *sdvo;
-
-       /* find the sdvo connector */
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               iout = to_intel_sdvo(connector);
-
-               if (iout->type != INTEL_OUTPUT_SDVO)
-                       continue;
-
-               sdvo = iout->dev_priv;
-
-               if (sdvo->sdvo_reg == SDVOB && sdvoB)
-                       return connector;
-
-               if (sdvo->sdvo_reg == SDVOC && !sdvoB)
-                       return connector;
-
-       }
-
-       return NULL;
-}
-
-int intel_sdvo_supports_hotplug(struct drm_connector *connector)
+static int intel_sdvo_supports_hotplug(struct intel_sdvo *intel_sdvo)
 {
        u8 response[2];
-       u8 status;
-       struct intel_sdvo *intel_sdvo;
-       DRM_DEBUG_KMS("\n");
-
-       if (!connector)
-               return 0;
-
-       intel_sdvo = to_intel_sdvo(connector);
 
        return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT,
                                    &response, 2) && response[0];
 }
 
-void intel_sdvo_set_hotplug(struct drm_connector *connector, int on)
+static void intel_sdvo_enable_hotplug(struct intel_encoder *encoder)
 {
-       u8 response[2];
-       u8 status;
-       struct intel_sdvo *intel_sdvo = to_intel_sdvo(connector);
-
-       intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0);
-       intel_sdvo_read_response(intel_sdvo, &response, 2);
+       struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
 
-       if (on) {
-               intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0);
-               status = intel_sdvo_read_response(intel_sdvo, &response, 2);
-
-               intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
-       } else {
-               response[0] = 0;
-               response[1] = 0;
-               intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
-       }
-
-       intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0);
-       intel_sdvo_read_response(intel_sdvo, &response, 2);
+       intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &intel_sdvo->hotplug_active, 2);
 }
-#endif
 
 static bool
 intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo)
 {
        /* Is there more than one type of output? */
-       int caps = intel_sdvo->caps.output_flags & 0xf;
-       return caps & -caps;
+       return hweight16(intel_sdvo->caps.output_flags) > 1;
 }
 
 static struct edid *
@@ -1303,7 +1253,7 @@ intel_sdvo_get_analog_edid(struct drm_connector *connector)
 }
 
 enum drm_connector_status
-intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
+intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
 {
        struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
        enum drm_connector_status status;
@@ -1398,7 +1348,7 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
        if ((intel_sdvo_connector->output_flag & response) == 0)
                ret = connector_status_disconnected;
        else if (IS_TMDS(intel_sdvo_connector))
-               ret = intel_sdvo_hdmi_sink_detect(connector);
+               ret = intel_sdvo_tmds_sink_detect(connector);
        else {
                struct edid *edid;
 
@@ -1945,7 +1895,7 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
                          struct intel_sdvo *sdvo, u32 reg)
 {
        struct sdvo_device_mapping *mapping;
-       u8 pin, speed;
+       u8 pin;
 
        if (IS_SDVOB(reg))
                mapping = &dev_priv->sdvo_mappings[0];
@@ -1953,18 +1903,16 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
                mapping = &dev_priv->sdvo_mappings[1];
 
        pin = GMBUS_PORT_DPB;
-       speed = GMBUS_RATE_1MHZ >> 8;
-       if (mapping->initialized) {
+       if (mapping->initialized)
                pin = mapping->i2c_pin;
-               speed = mapping->i2c_speed;
-       }
 
        if (pin < GMBUS_NUM_PORTS) {
                sdvo->i2c = &dev_priv->gmbus[pin].adapter;
-               intel_gmbus_set_speed(sdvo->i2c, speed);
+               intel_gmbus_set_speed(sdvo->i2c, GMBUS_RATE_1MHZ);
                intel_gmbus_force_bit(sdvo->i2c, true);
-       } else
+       } else {
                sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter;
+       }
 }
 
 static bool
@@ -2045,6 +1993,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
 {
        struct drm_encoder *encoder = &intel_sdvo->base.base;
        struct drm_connector *connector;
+       struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
        struct intel_connector *intel_connector;
        struct intel_sdvo_connector *intel_sdvo_connector;
 
@@ -2062,7 +2011,17 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
 
        intel_connector = &intel_sdvo_connector->base;
        connector = &intel_connector->base;
-       connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
+       if (intel_sdvo_supports_hotplug(intel_sdvo) & (1 << device)) {
+               connector->polled = DRM_CONNECTOR_POLL_HPD;
+               intel_sdvo->hotplug_active[0] |= 1 << device;
+               /* Some SDVO devices have one-shot hotplug interrupts.
+                * Ensure that they get re-enabled when an interrupt happens.
+                */
+               intel_encoder->hot_plug = intel_sdvo_enable_hotplug;
+               intel_sdvo_enable_hotplug(intel_encoder);
+       }
+       else
+               connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
        encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
        connector->connector_type = DRM_MODE_CONNECTOR_DVID;
 
@@ -2244,7 +2203,7 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags)
                              bytes[0], bytes[1]);
                return false;
        }
-       intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1);
+       intel_sdvo->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
        return true;
 }
@@ -2569,6 +2528,14 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)
        if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
                goto err;
 
+       /* Set up hotplug command - note paranoia about contents of reply.
+        * We assume that the hardware is in a sane state, and only touch
+        * the bits we think we understand.
+        */
+       intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG,
+                            &intel_sdvo->hotplug_active, 2);
+       intel_sdvo->hotplug_active[0] &= ~0x3;
+
        if (intel_sdvo_output_setup(intel_sdvo,
                                    intel_sdvo->caps.output_flags) != true) {
                DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n",