Message ID | 1308032036-23115-2-git-send-email-airlied@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, Jun 14, 2011 at 2:13 AM, Dave Airlie <airlied@gmail.com> wrote: > From: Dave Airlie <airlied@linux.ie> > > Some RS690 chipsets seem to end up with floating connectors, either > a DVI connector isn't actually populated, or an add-in HDMI card > is available but not installed. In this case we seem to get a NULL byte > response for each byte of the i2c transaction, so we detect this > case and if we see it we don't do anymore DDC transactions on this > connector. > > I've tested this on my RS690 without the HDMI card installed and > it seems to work fine. > > Signed-off-by: Dave Airlie <airlied@redhat.com> Just one comment below, but other than that: Reviewed-by: Alex Deucher <alexdeucher@gmail.com> > --- > drivers/gpu/drm/drm_edid.c | 15 +++++++++++++++ > drivers/gpu/drm/radeon/radeon_connectors.c | 7 +++++++ > include/drm/drm_crtc.h | 2 ++ > 3 files changed, 24 insertions(+), 0 deletions(-) > > diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c > index 3618d29..0929219 100644 > --- a/drivers/gpu/drm/drm_edid.c > +++ b/drivers/gpu/drm/drm_edid.c > @@ -258,6 +258,17 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, > return ret == 2 ? 0 : -1; > } > > +static bool drm_edid_is_zero(u8 *in_edid, int length) > +{ > + int i; > + u32 *raw_edid = (u32 *)in_edid; > + > + for (i = 0; i < length / 4; i++) > + if (*(raw_edid + i) != 0) > + return false; > + return true; > +} > + > static u8 * > drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) > { > @@ -273,6 +284,10 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) > goto out; > if (drm_edid_block_valid(block)) > break; > + if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) { > + connector->null_edid_counter++; > + goto carp; > + } > } > if (i == 4) > goto carp; > diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c > index 9c2929c..5c3393f 100644 > --- a/drivers/gpu/drm/radeon/radeon_connectors.c > +++ b/drivers/gpu/drm/radeon/radeon_connectors.c > @@ -836,6 +836,13 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) > if (!radeon_connector->edid) { > DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", > drm_get_connector_name(connector)); > + /* rs690 seems to have a problem with connectors not existing and always > + * return a block of 0's. If we see this just stop polling on this output */ > + if ((rdev->family == CHIP_RS690) && radeon_connector->base.null_edid_counter) { You may want to extend this to RS740 as well since IIRC they were pin compatible with RS690 and showed up in a lot of similar setups. > + ret = connector_status_disconnected; > + DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector)); > + radeon_connector->ddc_bus = NULL; > + } > } else { > radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); > > diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h > index 9573e0c..33d12f8 100644 > --- a/include/drm/drm_crtc.h > +++ b/include/drm/drm_crtc.h > @@ -520,6 +520,8 @@ struct drm_connector { > uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; > uint32_t force_encoder_id; > struct drm_encoder *encoder; /* currently active encoder */ > + > + int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */ > }; > > /** > -- > 1.7.5.2 > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel >
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 3618d29..0929219 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -258,6 +258,17 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, return ret == 2 ? 0 : -1; } +static bool drm_edid_is_zero(u8 *in_edid, int length) +{ + int i; + u32 *raw_edid = (u32 *)in_edid; + + for (i = 0; i < length / 4; i++) + if (*(raw_edid + i) != 0) + return false; + return true; +} + static u8 * drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) { @@ -273,6 +284,10 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) goto out; if (drm_edid_block_valid(block)) break; + if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) { + connector->null_edid_counter++; + goto carp; + } } if (i == 4) goto carp; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 9c2929c..5c3393f 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -836,6 +836,13 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) if (!radeon_connector->edid) { DRM_ERROR("%s: probed a monitor but no|invalid EDID\n", drm_get_connector_name(connector)); + /* rs690 seems to have a problem with connectors not existing and always + * return a block of 0's. If we see this just stop polling on this output */ + if ((rdev->family == CHIP_RS690) && radeon_connector->base.null_edid_counter) { + ret = connector_status_disconnected; + DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector)); + radeon_connector->ddc_bus = NULL; + } } else { radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 9573e0c..33d12f8 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -520,6 +520,8 @@ struct drm_connector { uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER]; uint32_t force_encoder_id; struct drm_encoder *encoder; /* currently active encoder */ + + int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */ }; /**