diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 6de97fc..54d098c 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -428,8 +428,34 @@ static void intel_crt_destroy(struct drm_connector *connector) static int intel_crt_get_modes(struct drm_connector *connector) { + int ret; struct intel_output *intel_output = to_intel_output(connector); - return intel_ddc_get_modes(intel_output); + struct intel_i2c_chan *ddcbus; + struct drm_device *dev = connector->dev; + + ddcbus = intel_output->ddc_bus; + + ret = intel_ddc_get_modes(intel_output); + if (ret || !IS_G4X(dev)) + goto end; + + /* Try to probe digital port for output in DVI-I -> VGA mode. */ + intel_output->ddc_bus = + intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D"); + + if (!intel_output->ddc_bus) { + dev_printk(KERN_ERR, &connector->dev->pdev->dev, + "DDC bus registration failed for CRTDDC_D.\n"); + goto end; + } + /* Try to get modes by GPIOD port */ + ret = intel_ddc_get_modes(intel_output); + intel_i2c_destroy(intel_output->ddc_bus); + +end: + intel_output->ddc_bus = ddcbus; + return ret; + } static int intel_crt_set_property(struct drm_connector *connector, diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 9e30daa..26b473d 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -130,37 +130,29 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, } static enum drm_connector_status -intel_hdmi_edid_detect(struct drm_connector *connector) +intel_hdmi_edid_detect(struct drm_connector *connector, struct edid *edid) { struct intel_output *intel_output = to_intel_output(connector); struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; - struct edid *edid = NULL; - enum drm_connector_status status = connector_status_disconnected; - edid = drm_get_edid(&intel_output->base, - intel_output->ddc_bus); hdmi_priv->has_hdmi_sink = false; - if (edid) { - if (edid->input & DRM_EDID_INPUT_DIGITAL) { - status = connector_status_connected; - hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); - } + if (edid != NULL) { + hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); intel_output->base.display_info.raw_edid = NULL; kfree(edid); } - return status; + return connector_status_connected; } static enum drm_connector_status -igdng_hdmi_detect(struct drm_connector *connector) +igdng_hdmi_detect(struct drm_connector *connector, struct edid *edid) { struct intel_output *intel_output = to_intel_output(connector); - struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; + /* FIXME hotplug detect */ - hdmi_priv->has_hdmi_sink = false; - return intel_hdmi_edid_detect(connector); + return intel_hdmi_edid_detect(connector, edid); } static enum drm_connector_status @@ -170,10 +162,25 @@ intel_hdmi_detect(struct drm_connector *connector) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_output *intel_output = to_intel_output(connector); struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; + struct edid *edid = NULL; u32 temp, bit; + /* probe connect status by EDID */ + edid = drm_get_edid(&intel_output->base, + intel_output->ddc_bus); + + if (edid != NULL) { + if ((edid->input & DRM_EDID_INPUT_DIGITAL) == 0) { + /* This is analog monitor */ + kfree(edid); + intel_output->base.display_info.raw_edid = NULL; + return connector_status_disconnected; + } + return intel_hdmi_edid_detect(connector, edid); + } + if (IS_IGDNG(dev)) - return igdng_hdmi_detect(connector); + return igdng_hdmi_detect(connector, edid); temp = I915_READ(PORT_HOTPLUG_EN); @@ -204,7 +211,7 @@ intel_hdmi_detect(struct drm_connector *connector) } if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) - return intel_hdmi_edid_detect(connector); + return intel_hdmi_edid_detect(connector, edid); else return connector_status_disconnected; }