[PATCH 2/3] drm/radeon: workaround a hw bug on some radeon chipsets with all-0 EDIDs.

Alex Deucher alexdeucher at gmail.com
Mon Jun 13 23:31:55 PDT 2011


On Tue, Jun 14, 2011 at 2:13 AM, Dave Airlie <airlied at gmail.com> wrote:
> From: Dave Airlie <airlied at 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 at redhat.com>

Just one comment below, but other than that:

Reviewed-by: Alex Deucher <alexdeucher at 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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>


More information about the dri-devel mailing list