drm/i915: hdmi detection according by reading edid

According to investigations from windows team ,hw team,
and our test results on all 4x platofrms available
(gm45, g45b, q45, g45a, g45c, g41a, and g41), we find
currently Hot plug live status and Hot plug interrupt
detection are not reliable, sometime the results from
the two approaches are contradicts. So we chose edid
detection for hdmi output.

Signed-off-by: Ma Ling <ling.ma@intel.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
ling.ma@intel.com 2009-07-16 17:23:09 +08:00 committed by Eric Anholt
parent 2a2430f454
commit 2ded9e2747
1 changed files with 4 additions and 60 deletions

View File

@ -130,16 +130,17 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
} }
static enum drm_connector_status static enum drm_connector_status
intel_hdmi_edid_detect(struct drm_connector *connector) intel_hdmi_detect(struct drm_connector *connector)
{ {
struct intel_output *intel_output = to_intel_output(connector); struct intel_output *intel_output = to_intel_output(connector);
struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv;
struct edid *edid = NULL; struct edid *edid = NULL;
enum drm_connector_status status = connector_status_disconnected; enum drm_connector_status status = connector_status_disconnected;
hdmi_priv->has_hdmi_sink = false;
edid = drm_get_edid(&intel_output->base, edid = drm_get_edid(&intel_output->base,
intel_output->ddc_bus); intel_output->ddc_bus);
hdmi_priv->has_hdmi_sink = false;
if (edid) { if (edid) {
if (edid->input & DRM_EDID_INPUT_DIGITAL) { if (edid->input & DRM_EDID_INPUT_DIGITAL) {
status = connector_status_connected; status = connector_status_connected;
@ -148,67 +149,10 @@ intel_hdmi_edid_detect(struct drm_connector *connector)
intel_output->base.display_info.raw_edid = NULL; intel_output->base.display_info.raw_edid = NULL;
kfree(edid); kfree(edid);
} }
return status; return status;
} }
static enum drm_connector_status
igdng_hdmi_detect(struct drm_connector *connector)
{
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);
}
static enum drm_connector_status
intel_hdmi_detect(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
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;
u32 temp, bit;
if (IS_IGDNG(dev))
return igdng_hdmi_detect(connector);
temp = I915_READ(PORT_HOTPLUG_EN);
switch (hdmi_priv->sdvox_reg) {
case SDVOB:
temp |= HDMIB_HOTPLUG_INT_EN;
break;
case SDVOC:
temp |= HDMIC_HOTPLUG_INT_EN;
break;
default:
return connector_status_unknown;
}
I915_WRITE(PORT_HOTPLUG_EN, temp);
POSTING_READ(PORT_HOTPLUG_EN);
switch (hdmi_priv->sdvox_reg) {
case SDVOB:
bit = HDMIB_HOTPLUG_INT_STATUS;
break;
case SDVOC:
bit = HDMIC_HOTPLUG_INT_STATUS;
break;
default:
return connector_status_unknown;
}
if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0)
return intel_hdmi_edid_detect(connector);
else
return connector_status_disconnected;
}
static int intel_hdmi_get_modes(struct drm_connector *connector) static int intel_hdmi_get_modes(struct drm_connector *connector)
{ {
struct intel_output *intel_output = to_intel_output(connector); struct intel_output *intel_output = to_intel_output(connector);