Skip to content

Commit

Permalink
drm/i915: Be extra careful about A/D matching for multifunction SDVO
Browse files Browse the repository at this point in the history
If we're both RGB and TMDS capable, we'll have set up one connector for
each.  When determining connectivity, require analog/digital state in
the EDID block to match analog/digital support in the connector.
Otherwise, both DVI and VGA will appear to be connected.

Signed-off-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
  • Loading branch information
Adam Jackson authored and Eric Anholt committed May 10, 2010
1 parent b108333 commit 149c36a
Showing 1 changed file with 21 additions and 24 deletions.
45 changes: 21 additions & 24 deletions drivers/gpu/drm/i915/intel_sdvo.c
Original file line number Diff line number Diff line change
Expand Up @@ -1504,16 +1504,17 @@ intel_analog_is_connected(struct drm_device *dev)
}

enum drm_connector_status
intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
{
struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct intel_sdvo_priv *sdvo_priv = intel_encoder->dev_priv;
struct intel_connector *intel_connector = to_intel_connector(connector);
struct intel_sdvo_connector *sdvo_connector = intel_connector->dev_priv;
enum drm_connector_status status = connector_status_connected;
struct edid *edid = NULL;

edid = drm_get_edid(connector,
intel_encoder->ddc_bus);
edid = drm_get_edid(connector, intel_encoder->ddc_bus);

/* This is only applied to SDVO cards with multiple outputs */
if (edid == NULL && intel_sdvo_multifunc_encoder(intel_encoder)) {
Expand All @@ -1526,8 +1527,7 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
*/
while(temp_ddc > 1) {
sdvo_priv->ddc_bus = temp_ddc;
edid = drm_get_edid(connector,
intel_encoder->ddc_bus);
edid = drm_get_edid(connector, intel_encoder->ddc_bus);
if (edid) {
/*
* When we can get the EDID, maybe it is the
Expand All @@ -1544,28 +1544,25 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector, u16 response)
/* when there is no edid and no monitor is connected with VGA
* port, try to use the CRT ddc to read the EDID for DVI-connector
*/
if (edid == NULL &&
sdvo_priv->analog_ddc_bus &&
if (edid == NULL && sdvo_priv->analog_ddc_bus &&
!intel_analog_is_connected(connector->dev))
edid = drm_get_edid(connector,
sdvo_priv->analog_ddc_bus);
edid = drm_get_edid(connector, sdvo_priv->analog_ddc_bus);

if (edid != NULL) {
/* Don't report the output as connected if it's a DVI-I
* connector with a non-digital EDID coming out.
*/
if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)) {
if (edid->input & DRM_EDID_INPUT_DIGITAL)
sdvo_priv->is_hdmi =
drm_detect_hdmi_monitor(edid);
else
status = connector_status_disconnected;
}
bool is_digital = !!(edid->input & DRM_EDID_INPUT_DIGITAL);
bool need_digital = !!(sdvo_connector->output_flag & SDVO_TMDS_MASK);

kfree(edid);
connector->display_info.raw_edid = NULL;
/* DDC bus is shared, match EDID to connector type */
if (is_digital && need_digital)
sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid);
else if (is_digital != need_digital)
status = connector_status_disconnected;

} else if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
connector->display_info.raw_edid = NULL;
} else
status = connector_status_disconnected;

kfree(edid);

return status;
}
Expand Down Expand Up @@ -1601,8 +1598,8 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect

if ((sdvo_connector->output_flag & response) == 0)
ret = connector_status_disconnected;
else if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
ret = intel_sdvo_hdmi_sink_detect(connector, response);
else if (response & SDVO_TMDS_MASK)
ret = intel_sdvo_hdmi_sink_detect(connector);
else
ret = connector_status_connected;

Expand Down

0 comments on commit 149c36a

Please sign in to comment.