All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
@ 2011-06-21 15:31 ` Thomas Reim
  0 siblings, 0 replies; 50+ messages in thread
From: Thomas Reim @ 2011-06-21 15:31 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel
  Cc: dri-devel, linux-kernel, Thomas Reim

Some integrated ATI Radeon  chipset implementations
(e. g. Asus M2A-VM HDMI) indicate the availability
of a DDC even when there's no monitor connected.
In this case, drm_get_edid and drm_edid_block_valid
periodically dump data and kernel errors into system
log files and onto terminals, which lead to an unacceptable
system behaviour.

Tested since kernel 2.35 on Asus M2A-VM HDMI board

Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
---
 drivers/gpu/drm/radeon/radeon_connectors.c |   10 +++++
 drivers/gpu/drm/radeon/radeon_display.c    |   11 +++++
 drivers/gpu/drm/radeon/radeon_i2c.c        |   60 ++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/radeon_mode.h       |    1 +
 4 files changed, 82 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index cbfca3a..7a76e45 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -828,6 +828,16 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 
 	if (radeon_connector->ddc_bus)
 		dret = radeon_ddc_probe(radeon_connector);
+
+	/* Asus M2A-VM HDMI DDC quirk:
+	 * Some integrated ATI Radeon chipset implementations (e. g. Asus
+	 * M2A-VM HDMI) indicate the availability of a DDC even when there's
+	 * no monitor connected.The following check prevents drm_get_edid()
+	 * and drm_edid_block_valid() of periodically dumping data and kernel
+	 * errors into the logs and onto the terminal, which would lead to an
+	 * unacceptable system behaviour */
+	if (dret && connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)
+		dret = radeon_ddc_edid_probe(radeon_connector);
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 292f73f..550f143 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -715,6 +715,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
 	if (ret) {
 		radeon_setup_encoder_clones(dev);
 		radeon_print_display_setup(dev);
+		/* Is this really required here?
+		   Seems to just force drm to dump EDID errors
+		   to kernel logs */
 		list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
 			radeon_ddc_dump(drm_connector);
 	}
@@ -777,8 +780,16 @@ static int radeon_ddc_dump(struct drm_connector *connector)
 	if (!radeon_connector->ddc_bus)
 		return -1;
 	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
+	/* Asus M2A-VM HDMI DDC quirk: Log EDID retrieval status here once,
+	 * instead of periodically dumping data and kernel errors into the
+	 * logs, if a monitor is not connected to HDMI */
 	if (edid) {
+		DRM_INFO("Radeon display connector %s: Found valid EDID",
+				drm_get_connector_name(connector));
 		kfree(edid);
+	} else {
+		DRM_INFO("Radeon display connector %s: No display connected or invalid EDID",
+				drm_get_connector_name(connector));
 	}
 	return ret;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 781196d..1d6decd 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -63,6 +63,66 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 	return false;
 }
 
+/**
+ * Probe EDID information via I2C.
+ *
+ * \param adapter : i2c device adaptor
+ * \param buf     : EDID data buffer to be filled
+ * \param len     : EDID data buffer length
+ * \return 0 on success or -1 on failure.
+ *
+ * Try to fetch EDID information by calling i2c driver function and
+ * probe for EDID header information.
+ *
+ * Remark:
+ * This function has been added, because there are integrated ATI Radeon
+ * chipset implementations (e. g. Asus M2A-VM HDMI that indicate the
+ * availability of a DDC even when there's no monitor connected.
+ * In this case, drm_get_edid and drm_edid_block_valid periodically dump
+ * data and kernel errors into the logs and onto the terminal, which lead to
+ * an unacceptable system behaviour.
+ */
+bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector)
+{
+	u8 out_buf[] = { 0x0, 0x0};
+	u8 block[20];
+	int ret;
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= 0x50,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= out_buf,
+		}, {
+			.addr	= 0x50,
+			.flags	= I2C_M_RD,
+			.len	= 20,
+			.buf	= block,
+		}
+	};
+
+	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
+	if (ret == 2)
+		if ((block[0] == 0x00) &&
+		    (block[7] == 0x00) &&
+		    (block[1] == 0xff) &&
+		    (block[2] == 0xff) &&
+		    (block[3] == 0xff) &&
+		    (block[4] == 0xff) &&
+		    (block[5] == 0xff) &&
+		    (block[6] == 0xff))
+			/* EDID header starts with:
+			 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00;
+			 * seems to be an EDID */
+			if ((block[18] != 0x00) || (block[19] != 0x00))
+				/* EDID headers end with EDID version and
+				 * revision number: EDID version is not 0.0 =>
+				 * EDID should be available */
+				return true;
+	/* Couldn't find an accessible EDID on this connector. */
+	return false;
+}
+
 /* bit banging i2c */
 
 static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 6df4e3c..14710fc 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -515,6 +515,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
 extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
+extern bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
@ 2011-06-21 15:31 ` Thomas Reim
  0 siblings, 0 replies; 50+ messages in thread
From: Thomas Reim @ 2011-06-21 15:31 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare, Tyson Whitehead
  Cc: dri-devel, linux-kernel, Thomas Reim

Some integrated ATI Radeon  chipset implementations
(e. g. Asus M2A-VM HDMI) indicate the availability
of a DDC even when there's no monitor connected.
In this case, drm_get_edid and drm_edid_block_valid
periodically dump data and kernel errors into system
log files and onto terminals, which lead to an unacceptable
system behaviour.

Tested since kernel 2.35 on Asus M2A-VM HDMI board

Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
---
 drivers/gpu/drm/radeon/radeon_connectors.c |   10 +++++
 drivers/gpu/drm/radeon/radeon_display.c    |   11 +++++
 drivers/gpu/drm/radeon/radeon_i2c.c        |   60 ++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/radeon_mode.h       |    1 +
 4 files changed, 82 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index cbfca3a..7a76e45 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -828,6 +828,16 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 
 	if (radeon_connector->ddc_bus)
 		dret = radeon_ddc_probe(radeon_connector);
+
+	/* Asus M2A-VM HDMI DDC quirk:
+	 * Some integrated ATI Radeon chipset implementations (e. g. Asus
+	 * M2A-VM HDMI) indicate the availability of a DDC even when there's
+	 * no monitor connected.The following check prevents drm_get_edid()
+	 * and drm_edid_block_valid() of periodically dumping data and kernel
+	 * errors into the logs and onto the terminal, which would lead to an
+	 * unacceptable system behaviour */
+	if (dret && connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)
+		dret = radeon_ddc_edid_probe(radeon_connector);
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 292f73f..550f143 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -715,6 +715,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
 	if (ret) {
 		radeon_setup_encoder_clones(dev);
 		radeon_print_display_setup(dev);
+		/* Is this really required here?
+		   Seems to just force drm to dump EDID errors
+		   to kernel logs */
 		list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
 			radeon_ddc_dump(drm_connector);
 	}
@@ -777,8 +780,16 @@ static int radeon_ddc_dump(struct drm_connector *connector)
 	if (!radeon_connector->ddc_bus)
 		return -1;
 	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
+	/* Asus M2A-VM HDMI DDC quirk: Log EDID retrieval status here once,
+	 * instead of periodically dumping data and kernel errors into the
+	 * logs, if a monitor is not connected to HDMI */
 	if (edid) {
+		DRM_INFO("Radeon display connector %s: Found valid EDID",
+				drm_get_connector_name(connector));
 		kfree(edid);
+	} else {
+		DRM_INFO("Radeon display connector %s: No display connected or invalid EDID",
+				drm_get_connector_name(connector));
 	}
 	return ret;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 781196d..1d6decd 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -63,6 +63,66 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 	return false;
 }
 
+/**
+ * Probe EDID information via I2C.
+ *
+ * \param adapter : i2c device adaptor
+ * \param buf     : EDID data buffer to be filled
+ * \param len     : EDID data buffer length
+ * \return 0 on success or -1 on failure.
+ *
+ * Try to fetch EDID information by calling i2c driver function and
+ * probe for EDID header information.
+ *
+ * Remark:
+ * This function has been added, because there are integrated ATI Radeon
+ * chipset implementations (e. g. Asus M2A-VM HDMI that indicate the
+ * availability of a DDC even when there's no monitor connected.
+ * In this case, drm_get_edid and drm_edid_block_valid periodically dump
+ * data and kernel errors into the logs and onto the terminal, which lead to
+ * an unacceptable system behaviour.
+ */
+bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector)
+{
+	u8 out_buf[] = { 0x0, 0x0};
+	u8 block[20];
+	int ret;
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= 0x50,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= out_buf,
+		}, {
+			.addr	= 0x50,
+			.flags	= I2C_M_RD,
+			.len	= 20,
+			.buf	= block,
+		}
+	};
+
+	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
+	if (ret == 2)
+		if ((block[0] == 0x00) &&
+		    (block[7] == 0x00) &&
+		    (block[1] == 0xff) &&
+		    (block[2] == 0xff) &&
+		    (block[3] == 0xff) &&
+		    (block[4] == 0xff) &&
+		    (block[5] == 0xff) &&
+		    (block[6] == 0xff))
+			/* EDID header starts with:
+			 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00;
+			 * seems to be an EDID */
+			if ((block[18] != 0x00) || (block[19] != 0x00))
+				/* EDID headers end with EDID version and
+				 * revision number: EDID version is not 0.0 =>
+				 * EDID should be available */
+				return true;
+	/* Couldn't find an accessible EDID on this connector. */
+	return false;
+}
+
 /* bit banging i2c */
 
 static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 6df4e3c..14710fc 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -515,6 +515,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
 extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
+extern bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-21 15:31 ` Thomas Reim
  (?)
@ 2011-06-21 15:37 ` Alex Deucher
  2011-06-21 18:03   ` Thomas Reim
  -1 siblings, 1 reply; 50+ messages in thread
From: Alex Deucher @ 2011-06-21 15:37 UTC (permalink / raw)
  To: Thomas Reim
  Cc: Dave Airlie, Mario Kleiner, Jean Delvare, Tyson Whitehead,
	Jason Wessel, dri-devel, linux-kernel, Thomas Reim

On Tue, Jun 21, 2011 at 11:31 AM, Thomas Reim <reimth@googlemail.com> wrote:
> Some integrated ATI Radeon  chipset implementations
> (e. g. Asus M2A-VM HDMI) indicate the availability
> of a DDC even when there's no monitor connected.
> In this case, drm_get_edid and drm_edid_block_valid
> periodically dump data and kernel errors into system
> log files and onto terminals, which lead to an unacceptable
> system behaviour.
>
> Tested since kernel 2.35 on Asus M2A-VM HDMI board
>
> Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>

Does this patch fix the issue:
http://git.kernel.org/?p=linux/kernel/git/airlied/drm-2.6.git;a=commitdiff;h=4a9a8b71e12d41abb71c4e741bff524f016cfef4

Alex

> ---
>  drivers/gpu/drm/radeon/radeon_connectors.c |   10 +++++
>  drivers/gpu/drm/radeon/radeon_display.c    |   11 +++++
>  drivers/gpu/drm/radeon/radeon_i2c.c        |   60 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/radeon/radeon_mode.h       |    1 +
>  4 files changed, 82 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> index cbfca3a..7a76e45 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -828,6 +828,16 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
>
>        if (radeon_connector->ddc_bus)
>                dret = radeon_ddc_probe(radeon_connector);
> +
> +       /* Asus M2A-VM HDMI DDC quirk:
> +        * Some integrated ATI Radeon chipset implementations (e. g. Asus
> +        * M2A-VM HDMI) indicate the availability of a DDC even when there's
> +        * no monitor connected.The following check prevents drm_get_edid()
> +        * and drm_edid_block_valid() of periodically dumping data and kernel
> +        * errors into the logs and onto the terminal, which would lead to an
> +        * unacceptable system behaviour */
> +       if (dret && connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)
> +               dret = radeon_ddc_edid_probe(radeon_connector);
>        if (dret) {
>                if (radeon_connector->edid) {
>                        kfree(radeon_connector->edid);
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index 292f73f..550f143 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -715,6 +715,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
>        if (ret) {
>                radeon_setup_encoder_clones(dev);
>                radeon_print_display_setup(dev);
> +               /* Is this really required here?
> +                  Seems to just force drm to dump EDID errors
> +                  to kernel logs */
>                list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
>                        radeon_ddc_dump(drm_connector);
>        }
> @@ -777,8 +780,16 @@ static int radeon_ddc_dump(struct drm_connector *connector)
>        if (!radeon_connector->ddc_bus)
>                return -1;
>        edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
> +       /* Asus M2A-VM HDMI DDC quirk: Log EDID retrieval status here once,
> +        * instead of periodically dumping data and kernel errors into the
> +        * logs, if a monitor is not connected to HDMI */
>        if (edid) {
> +               DRM_INFO("Radeon display connector %s: Found valid EDID",
> +                               drm_get_connector_name(connector));
>                kfree(edid);
> +       } else {
> +               DRM_INFO("Radeon display connector %s: No display connected or invalid EDID",
> +                               drm_get_connector_name(connector));
>        }
>        return ret;
>  }
> diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
> index 781196d..1d6decd 100644
> --- a/drivers/gpu/drm/radeon/radeon_i2c.c
> +++ b/drivers/gpu/drm/radeon/radeon_i2c.c
> @@ -63,6 +63,66 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
>        return false;
>  }
>
> +/**
> + * Probe EDID information via I2C.
> + *
> + * \param adapter : i2c device adaptor
> + * \param buf     : EDID data buffer to be filled
> + * \param len     : EDID data buffer length
> + * \return 0 on success or -1 on failure.
> + *
> + * Try to fetch EDID information by calling i2c driver function and
> + * probe for EDID header information.
> + *
> + * Remark:
> + * This function has been added, because there are integrated ATI Radeon
> + * chipset implementations (e. g. Asus M2A-VM HDMI that indicate the
> + * availability of a DDC even when there's no monitor connected.
> + * In this case, drm_get_edid and drm_edid_block_valid periodically dump
> + * data and kernel errors into the logs and onto the terminal, which lead to
> + * an unacceptable system behaviour.
> + */
> +bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector)
> +{
> +       u8 out_buf[] = { 0x0, 0x0};
> +       u8 block[20];
> +       int ret;
> +       struct i2c_msg msgs[] = {
> +               {
> +                       .addr   = 0x50,
> +                       .flags  = 0,
> +                       .len    = 1,
> +                       .buf    = out_buf,
> +               }, {
> +                       .addr   = 0x50,
> +                       .flags  = I2C_M_RD,
> +                       .len    = 20,
> +                       .buf    = block,
> +               }
> +       };
> +
> +       ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
> +       if (ret == 2)
> +               if ((block[0] == 0x00) &&
> +                   (block[7] == 0x00) &&
> +                   (block[1] == 0xff) &&
> +                   (block[2] == 0xff) &&
> +                   (block[3] == 0xff) &&
> +                   (block[4] == 0xff) &&
> +                   (block[5] == 0xff) &&
> +                   (block[6] == 0xff))
> +                       /* EDID header starts with:
> +                        * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00;
> +                        * seems to be an EDID */
> +                       if ((block[18] != 0x00) || (block[19] != 0x00))
> +                               /* EDID headers end with EDID version and
> +                                * revision number: EDID version is not 0.0 =>
> +                                * EDID should be available */
> +                               return true;
> +       /* Couldn't find an accessible EDID on this connector. */
> +       return false;
> +}
> +
>  /* bit banging i2c */
>
>  static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index 6df4e3c..14710fc 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -515,6 +515,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
>  extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
>  extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
>  extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
> +extern bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector);
>  extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
>
>  extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
> --
> 1.7.1
>
>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-21 15:37 ` Alex Deucher
@ 2011-06-21 18:03   ` Thomas Reim
  0 siblings, 0 replies; 50+ messages in thread
From: Thomas Reim @ 2011-06-21 18:03 UTC (permalink / raw)
  To: Alex Deucher
  Cc: Thomas Reim, Dave Airlie, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel, dri-devel, linux-kernel,
	Thomas Reim

Dear Alex, 

yes, the proposed fix should also fix the 'drm/radeon: workaround a hw
bug on some radeon chipsets with all-0 EDIDs.' issue. The trick is, that
we check within the Radeon domain directly on i2c interface level, if an
EDID can be retrieved at all, before we hand over to the main drm edid
functions. 

If you can provide some logs from Dave, I can double-check.

Regards,

  Thomas

> On Tue, Jun 21, 2011 at 11:31 AM, Thomas Reim <reimth@googlemail.com> wrote:
> > Some integrated ATI Radeon chipset implementations
> > (e. g. Asus M2A-VM HDMI) indicate the availability
> > of a DDC even when there's no monitor connected.
> > In this case, drm_get_edid and drm_edid_block_valid
> > periodically dump data and kernel errors into system
> > log files and onto terminals, which lead to an unacceptable
> > system behaviour.
> >
> > Tested since kernel 2.35 on Asus M2A-VM HDMI board
> >
> > Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
> 
> Does this patch fix the issue:
> http://git.kernel.org/?p=linux/kernel/git/airlied/drm-2.6.git;a=commitdiff;h=4a9a8b71e12d41abb71c4e741bff524f016cfef4
> 
> Alex
> 
> > ---
> >  drivers/gpu/drm/radeon/radeon_connectors.c |   10 +++++
> >  drivers/gpu/drm/radeon/radeon_display.c    |   11 +++++
> >  drivers/gpu/drm/radeon/radeon_i2c.c        |   60 ++++++++++++++++++++++++++++
> >  drivers/gpu/drm/radeon/radeon_mode.h       |    1 +
> >  4 files changed, 82 insertions(+), 0 deletions(-)
> >



^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-21 15:31 ` Thomas Reim
@ 2011-06-21 19:27   ` Jean Delvare
  -1 siblings, 0 replies; 50+ messages in thread
From: Jean Delvare @ 2011-06-21 19:27 UTC (permalink / raw)
  To: Thomas Reim
  Cc: Dave Airlie, Alex Deucher, Mario Kleiner, Tyson Whitehead,
	Jason Wessel, dri-devel, linux-kernel, Thomas Reim

Hi Thomas,

On Tue, 21 Jun 2011 17:31:45 +0200, Thomas Reim wrote:
> Some integrated ATI Radeon  chipset implementations
> (e. g. Asus M2A-VM HDMI) indicate the availability
> of a DDC even when there's no monitor connected.
> In this case, drm_get_edid and drm_edid_block_valid
> periodically dump data and kernel errors into system
> log files and onto terminals, which lead to an unacceptable
> system behaviour.
> 
> Tested since kernel 2.35 on Asus M2A-VM HDMI board

I don't like your implementation (see below.) Also, your comment above
suggests that your main problem here is that logging is too verbose.
Maybe that's what you should be fixing.

> 
> Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
> ---
>  drivers/gpu/drm/radeon/radeon_connectors.c |   10 +++++
>  drivers/gpu/drm/radeon/radeon_display.c    |   11 +++++
>  drivers/gpu/drm/radeon/radeon_i2c.c        |   60 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/radeon/radeon_mode.h       |    1 +
>  4 files changed, 82 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> index cbfca3a..7a76e45 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -828,6 +828,16 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
>  
>  	if (radeon_connector->ddc_bus)
>  		dret = radeon_ddc_probe(radeon_connector);
> +
> +	/* Asus M2A-VM HDMI DDC quirk:
> +	 * Some integrated ATI Radeon chipset implementations (e. g. Asus
> +	 * M2A-VM HDMI) indicate the availability of a DDC even when there's
> +	 * no monitor connected.The following check prevents drm_get_edid()
> +	 * and drm_edid_block_valid() of periodically dumping data and kernel
> +	 * errors into the logs and onto the terminal, which would lead to an
> +	 * unacceptable system behaviour */
> +	if (dret && connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)
> +		dret = radeon_ddc_edid_probe(radeon_connector);

I don't like this. radeon_ddc_edid_probe() is partly redundant with
radeon_ddc_probe() and also partly redundant with drm_get_edid() and
drm_edid_is_valid(). It will add yet another round of I2C transactions,
and these transactions are slow, so the fewer we have at driver load
time, the happier we are. This is even more true these days when every
graphics card gets 8 I2C buses created.

If nothing else, you should call radeon_ddc_edid_probe() instead of,
not after, radeon_ddc_probe(), to save a transaction.

But the root cause is most certainly that the underlying I2C bus is not
working. I bet that SDA is stuck low, which causes every sent byte
(including the slave address) to look like it was acked [1], and every
read byte to be zero. So the key problem is that radeon_ddc_probe()
isn't able to detect this case. Either the bus should be tested first
(see i2c-algo-bit for a test function) or radeon_ddc_probe() should be
improved to detect this case. It doesn't have to go to the extent of
your new radeon_ddc_edid_probe() function. It would be enough to read 2
bytes from the supposed EDID EEPROM, and check that they are not both 0.

Properly checking for stuck bus would have the advantage that you don't
have to retest later (contrary to missing EDID which can show up later
when a monitor gets plugged.)

[1] Incidentally I had a similar case reported a few days ago:
    http://lists.lm-sensors.org/pipermail/lm-sensors/2011-June/032959.html

Further comments below are just for completeness, as I don't think the
route your took is appropriate.

>  	if (dret) {
>  		if (radeon_connector->edid) {
>  			kfree(radeon_connector->edid);
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index 292f73f..550f143 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -715,6 +715,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
>  	if (ret) {
>  		radeon_setup_encoder_clones(dev);
>  		radeon_print_display_setup(dev);
> +		/* Is this really required here?
> +		   Seems to just force drm to dump EDID errors
> +		   to kernel logs */
>  		list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
>  			radeon_ddc_dump(drm_connector);
>  	}
> @@ -777,8 +780,16 @@ static int radeon_ddc_dump(struct drm_connector *connector)
>  	if (!radeon_connector->ddc_bus)
>  		return -1;
>  	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
> +	/* Asus M2A-VM HDMI DDC quirk: Log EDID retrieval status here once,
> +	 * instead of periodically dumping data and kernel errors into the
> +	 * logs, if a monitor is not connected to HDMI */
>  	if (edid) {
> +		DRM_INFO("Radeon display connector %s: Found valid EDID",
> +				drm_get_connector_name(connector));
>  		kfree(edid);
> +	} else {
> +		DRM_INFO("Radeon display connector %s: No display connected or invalid EDID",
> +				drm_get_connector_name(connector));
>  	}
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
> index 781196d..1d6decd 100644
> --- a/drivers/gpu/drm/radeon/radeon_i2c.c
> +++ b/drivers/gpu/drm/radeon/radeon_i2c.c
> @@ -63,6 +63,66 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
>  	return false;
>  }
>  
> +/**
> + * Probe EDID information via I2C.
> + *
> + * \param adapter : i2c device adaptor
> + * \param buf     : EDID data buffer to be filled
> + * \param len     : EDID data buffer length
> + * \return 0 on success or -1 on failure.

It doesn't look like the standard kernel documentation style. At least
I've never seen such \ before. And worse, it doesn't describe the
function below at all.

> + *
> + * Try to fetch EDID information by calling i2c driver function and
> + * probe for EDID header information.
> + *
> + * Remark:
> + * This function has been added, because there are integrated ATI Radeon
> + * chipset implementations (e. g. Asus M2A-VM HDMI that indicate the
> + * availability of a DDC even when there's no monitor connected.
> + * In this case, drm_get_edid and drm_edid_block_valid periodically dump
> + * data and kernel errors into the logs and onto the terminal, which lead to
> + * an unacceptable system behaviour.
> + */
> +bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector)
> +{
> +	u8 out_buf[] = { 0x0, 0x0};

You only use the first byte (same in radeon_ddc_probe, could be
optimized.)

> +	u8 block[20];
> +	int ret;
> +	struct i2c_msg msgs[] = {
> +		{
> +			.addr	= 0x50,
> +			.flags	= 0,
> +			.len	= 1,
> +			.buf	= out_buf,
> +		}, {
> +			.addr	= 0x50,
> +			.flags	= I2C_M_RD,
> +			.len	= 20,
> +			.buf	= block,
> +		}
> +	};
> +
> +	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);

You are reading 20 bytes when you really only need 10. It would be more
efficient to read 8 bytes first, and only if needed, the two remaining
ones..

> +	if (ret == 2)
> +		if ((block[0] == 0x00) &&
> +		    (block[7] == 0x00) &&
> +		    (block[1] == 0xff) &&
> +		    (block[2] == 0xff) &&
> +		    (block[3] == 0xff) &&
> +		    (block[4] == 0xff) &&
> +		    (block[5] == 0xff) &&
> +		    (block[6] == 0xff))
> +			/* EDID header starts with:
> +			 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00;
> +			 * seems to be an EDID */
> +			if ((block[18] != 0x00) || (block[19] != 0x00))

You can drop many parentheses in these tests.

> +				/* EDID headers end with EDID version and
> +				 * revision number: EDID version is not 0.0 =>
> +				 * EDID should be available */
> +				return true;
> +	/* Couldn't find an accessible EDID on this connector. */
> +	return false;
> +}
> +
>  /* bit banging i2c */
>  
>  static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index 6df4e3c..14710fc 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -515,6 +515,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
>  extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
>  extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
>  extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
> +extern bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector);
>  extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
>  
>  extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);


-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
@ 2011-06-21 19:27   ` Jean Delvare
  0 siblings, 0 replies; 50+ messages in thread
From: Jean Delvare @ 2011-06-21 19:27 UTC (permalink / raw)
  To: Thomas Reim
  Cc: Tyson Whitehead, linux-kernel, dri-devel, Thomas Reim,
	Mario Kleiner, Jason Wessel, Dave Airlie

Hi Thomas,

On Tue, 21 Jun 2011 17:31:45 +0200, Thomas Reim wrote:
> Some integrated ATI Radeon  chipset implementations
> (e. g. Asus M2A-VM HDMI) indicate the availability
> of a DDC even when there's no monitor connected.
> In this case, drm_get_edid and drm_edid_block_valid
> periodically dump data and kernel errors into system
> log files and onto terminals, which lead to an unacceptable
> system behaviour.
> 
> Tested since kernel 2.35 on Asus M2A-VM HDMI board

I don't like your implementation (see below.) Also, your comment above
suggests that your main problem here is that logging is too verbose.
Maybe that's what you should be fixing.

> 
> Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
> ---
>  drivers/gpu/drm/radeon/radeon_connectors.c |   10 +++++
>  drivers/gpu/drm/radeon/radeon_display.c    |   11 +++++
>  drivers/gpu/drm/radeon/radeon_i2c.c        |   60 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/radeon/radeon_mode.h       |    1 +
>  4 files changed, 82 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> index cbfca3a..7a76e45 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -828,6 +828,16 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
>  
>  	if (radeon_connector->ddc_bus)
>  		dret = radeon_ddc_probe(radeon_connector);
> +
> +	/* Asus M2A-VM HDMI DDC quirk:
> +	 * Some integrated ATI Radeon chipset implementations (e. g. Asus
> +	 * M2A-VM HDMI) indicate the availability of a DDC even when there's
> +	 * no monitor connected.The following check prevents drm_get_edid()
> +	 * and drm_edid_block_valid() of periodically dumping data and kernel
> +	 * errors into the logs and onto the terminal, which would lead to an
> +	 * unacceptable system behaviour */
> +	if (dret && connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)
> +		dret = radeon_ddc_edid_probe(radeon_connector);

I don't like this. radeon_ddc_edid_probe() is partly redundant with
radeon_ddc_probe() and also partly redundant with drm_get_edid() and
drm_edid_is_valid(). It will add yet another round of I2C transactions,
and these transactions are slow, so the fewer we have at driver load
time, the happier we are. This is even more true these days when every
graphics card gets 8 I2C buses created.

If nothing else, you should call radeon_ddc_edid_probe() instead of,
not after, radeon_ddc_probe(), to save a transaction.

But the root cause is most certainly that the underlying I2C bus is not
working. I bet that SDA is stuck low, which causes every sent byte
(including the slave address) to look like it was acked [1], and every
read byte to be zero. So the key problem is that radeon_ddc_probe()
isn't able to detect this case. Either the bus should be tested first
(see i2c-algo-bit for a test function) or radeon_ddc_probe() should be
improved to detect this case. It doesn't have to go to the extent of
your new radeon_ddc_edid_probe() function. It would be enough to read 2
bytes from the supposed EDID EEPROM, and check that they are not both 0.

Properly checking for stuck bus would have the advantage that you don't
have to retest later (contrary to missing EDID which can show up later
when a monitor gets plugged.)

[1] Incidentally I had a similar case reported a few days ago:
    http://lists.lm-sensors.org/pipermail/lm-sensors/2011-June/032959.html

Further comments below are just for completeness, as I don't think the
route your took is appropriate.

>  	if (dret) {
>  		if (radeon_connector->edid) {
>  			kfree(radeon_connector->edid);
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index 292f73f..550f143 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -715,6 +715,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
>  	if (ret) {
>  		radeon_setup_encoder_clones(dev);
>  		radeon_print_display_setup(dev);
> +		/* Is this really required here?
> +		   Seems to just force drm to dump EDID errors
> +		   to kernel logs */
>  		list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
>  			radeon_ddc_dump(drm_connector);
>  	}
> @@ -777,8 +780,16 @@ static int radeon_ddc_dump(struct drm_connector *connector)
>  	if (!radeon_connector->ddc_bus)
>  		return -1;
>  	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
> +	/* Asus M2A-VM HDMI DDC quirk: Log EDID retrieval status here once,
> +	 * instead of periodically dumping data and kernel errors into the
> +	 * logs, if a monitor is not connected to HDMI */
>  	if (edid) {
> +		DRM_INFO("Radeon display connector %s: Found valid EDID",
> +				drm_get_connector_name(connector));
>  		kfree(edid);
> +	} else {
> +		DRM_INFO("Radeon display connector %s: No display connected or invalid EDID",
> +				drm_get_connector_name(connector));
>  	}
>  	return ret;
>  }
> diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
> index 781196d..1d6decd 100644
> --- a/drivers/gpu/drm/radeon/radeon_i2c.c
> +++ b/drivers/gpu/drm/radeon/radeon_i2c.c
> @@ -63,6 +63,66 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
>  	return false;
>  }
>  
> +/**
> + * Probe EDID information via I2C.
> + *
> + * \param adapter : i2c device adaptor
> + * \param buf     : EDID data buffer to be filled
> + * \param len     : EDID data buffer length
> + * \return 0 on success or -1 on failure.

It doesn't look like the standard kernel documentation style. At least
I've never seen such \ before. And worse, it doesn't describe the
function below at all.

> + *
> + * Try to fetch EDID information by calling i2c driver function and
> + * probe for EDID header information.
> + *
> + * Remark:
> + * This function has been added, because there are integrated ATI Radeon
> + * chipset implementations (e. g. Asus M2A-VM HDMI that indicate the
> + * availability of a DDC even when there's no monitor connected.
> + * In this case, drm_get_edid and drm_edid_block_valid periodically dump
> + * data and kernel errors into the logs and onto the terminal, which lead to
> + * an unacceptable system behaviour.
> + */
> +bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector)
> +{
> +	u8 out_buf[] = { 0x0, 0x0};

You only use the first byte (same in radeon_ddc_probe, could be
optimized.)

> +	u8 block[20];
> +	int ret;
> +	struct i2c_msg msgs[] = {
> +		{
> +			.addr	= 0x50,
> +			.flags	= 0,
> +			.len	= 1,
> +			.buf	= out_buf,
> +		}, {
> +			.addr	= 0x50,
> +			.flags	= I2C_M_RD,
> +			.len	= 20,
> +			.buf	= block,
> +		}
> +	};
> +
> +	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);

You are reading 20 bytes when you really only need 10. It would be more
efficient to read 8 bytes first, and only if needed, the two remaining
ones..

> +	if (ret == 2)
> +		if ((block[0] == 0x00) &&
> +		    (block[7] == 0x00) &&
> +		    (block[1] == 0xff) &&
> +		    (block[2] == 0xff) &&
> +		    (block[3] == 0xff) &&
> +		    (block[4] == 0xff) &&
> +		    (block[5] == 0xff) &&
> +		    (block[6] == 0xff))
> +			/* EDID header starts with:
> +			 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00;
> +			 * seems to be an EDID */
> +			if ((block[18] != 0x00) || (block[19] != 0x00))

You can drop many parentheses in these tests.

> +				/* EDID headers end with EDID version and
> +				 * revision number: EDID version is not 0.0 =>
> +				 * EDID should be available */
> +				return true;
> +	/* Couldn't find an accessible EDID on this connector. */
> +	return false;
> +}
> +
>  /* bit banging i2c */
>  
>  static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index 6df4e3c..14710fc 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -515,6 +515,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
>  extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
>  extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
>  extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
> +extern bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector);
>  extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
>  
>  extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);


-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-21 19:27   ` Jean Delvare
  (?)
@ 2011-06-22  1:11   ` Thomas Reim
  2011-06-22 13:53       ` Jean Delvare
  -1 siblings, 1 reply; 50+ messages in thread
From: Thomas Reim @ 2011-06-22  1:11 UTC (permalink / raw)
  To: Jean Delvare
  Cc: Thomas Reim, Dave Airlie, Alex Deucher, Mario Kleiner,
	Tyson Whitehead, Jason Wessel, dri-devel, linux-kernel,
	Thomas Reim

Salut Jean, 

thank you for the detailed reply. If I got you right you rose the
following main points:
1. Root cause leading to flooding problem (you assume i2c bus not 
   working correctly, i. e. "stuck bus") not adequately addressed by 
   the fix 
2. Alternative proposal: Fix the verbose logging issue
3. i2c EDID probing inefficiently implemented
4. Strange coding and commenting style

Point 1:
The Asus M2A-VM HDMI EDID error flooding problem was already addressed
in this mailing list in April this year
(https://lkml.org/lkml/2011/4/15/36). But it was not further discussed,
maybe due to missing bug information. I wanted to provide this
information to that thread, but your mail was faster :-). In the
following, you can see the i2c dump of the DVI connector of the AMD 690G
chip, where the monitor is connected to:
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 00 ff ff ff ff ff ff 00 4c 2d ed 00 39 31 49 44    ........L-?.91ID
10: 2d 0e 01 03 80 26 1e 78 2a ee 95 a3 54 4c 99 26    -????&?x*???TL?&
20: 0f 50 54 bf ef 80 81 80 71 4f 01 01 01 01 01 01    ?PT?????qO??????
30: 01 01 01 01 01 01 30 2a 00 98 51 00 2a 40 30 70    ??????0*.?Q.*@0p
40: 13 00 78 2d 11 00 00 1e 00 00 00 fd 00 38 4c 1e    ?.x-?..?...?.8L?
50: 51 0e 00 0a 20 20 20 20 20 20 00 00 00 fc 00 53    Q?.?      ...?.S
60: 79 6e 63 4d 61 73 74 65 72 0a 20 20 00 00 00 ff    yncMaster?  ....
70: 00 48 34 4a 58 42 30 31 35 30 33 0a 20 20 00 e4    .H4JXB01503?  .?
80: 00 ff ff ff ff ff ff 00 4c 2d ed 00 39 31 49 44    ........L-?.91ID
90: 2d 0e 01 03 80 26 1e 78 2a ee 95 a3 54 4c 99 26    -????&?x*???TL?&
a0: 0f 50 54 bf ef 80 81 80 71 4f 01 01 01 01 01 01    ?PT?????qO??????
b0: 01 01 01 01 01 01 30 2a 00 98 51 00 2a 40 30 70    ??????0*.?Q.*@0p
c0: 13 00 78 2d 11 00 00 1e 00 00 00 fd 00 38 4c 1e    ?.x-?..?...?.8L?
d0: 51 0e 00 0a 20 20 20 20 20 20 00 00 00 fc 00 53    Q?.?      ...?.S
e0: 79 6e 63 4d 61 73 74 65 72 0a 20 20 00 00 00 ff    yncMaster?  ....
f0: 00 48 34 4a 58 42 30 31 35 30 33 0a 20 20 00 e4    .H4JXB01503?  .?

Then we have the i2c dump of the HDMI connector with no monitor
connected: 
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 00 00 00 00 00 00 00 00 00 00 1f 00 00 00 00 00    ..........?.....
10: 00 00 00 00 00 XX 00 01 00 00 00 00 1f 00 00 00    .....X.?....?...
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
30: 00 00 00 00 00 XX 00 00 00 00 00 7f 00 00 00 00    .....X.....?....
40: 00 00 1f 00 00 00 00 00 00 00 00 00 00 00 00 00    ..?.............
50: 00 00 00 00 00 07 00 01 00 00 00 00 00 00 00 00    .....?.?........
60: 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00    .....?..........
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
80: 00 00 ff 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
90: 00 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00    .....?..........
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
b0: 00 00 00 00 00 ff 00 00 3f 00 00 00 00 00 00 00    ........?.......
c0: 00 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00    .........?......
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
f0: 00 00 00 00 XX 00 00 7f 00 00 00 00 00 00 00 00    ....X..?........

For this connector radeon_ddc_probe() reports a working DDC, which leads
to the catastrophic situation that drm_get_edid() and
drm_edid_block_valid() flood the logs with EDID error messages and
dumps.

Finally, we have the i2c dump of the VGA connector, where also no
monitor is connected to:
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
20: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
30: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
40: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
50: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
60: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
70: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
80: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
90: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
a0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
b0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
c0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
d0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
e0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
f0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX

radeon_ddc_probe() reports no DDC.

Do you really believe that this is caused by a stuck i2c bus? Following
the i2c dumps it really makes sense to add a limited check of some major
EDID parts from i2c register for DDC probing. Current radeon_ddc_probe()
just checks that we CAN get data from i2c register 0x50 and leaves the
rest to the log flooding drm_edid functions.

Point 2:
Your proposal has been intensively discussed after release of kernel
2.35. Many users suffered from this log flooding. Many people proposed
fixes, e. g. log EDID errors only once. None of the proposals was taken
over by the kernel developers. The linux distributions' bug lists are
full of these unsolved bug reports. Also in kernel 3.0 no solution was
released. For me that means, kernel people have stringent reasons to NOT
touch the log flooding functions in DRM. Therefore, I spent my time to
fix the problem in the hardware related domain. And the few changes in
radeon code have solved the problem from 2.35 up to the latest 3.0 git
version.

Point 3:
> I don't like this. radeon_ddc_edid_probe() is partly redundant with
> radeon_ddc_probe() and also partly redundant with drm_get_edid() and
> drm_edid_is_valid(). It will add yet another round of I2C transactions,
> and these transactions are slow, so the fewer we have at driver load
> time, the happier we are. This is even more true these days when every
> graphics card gets 8 I2C buses created.
> 
> If nothing else, you should call radeon_ddc_edid_probe() instead of,
> not after, radeon_ddc_probe(), to save a transaction.

This is correct, I was not sure about possible side effects. Therefore,
I used both functions in my first proposal but limited the new one to
the DRM_MODE_CONNECTOR_HDMIA types of the eight i2c busses. 

> +bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector)
> > +{
> > +	u8 out_buf[] = { 0x0, 0x0};
> 
> You only use the first byte (same in radeon_ddc_probe, could be
> optimized.)
> 
> > +	u8 block[20];
> > +	int ret;
> > +	struct i2c_msg msgs[] = {
> > +		{
> > +			.addr	= 0x50,
> > +			.flags	= 0,
> > +			.len	= 1,
> > +			.buf	= out_buf,
> > +		}, {
> > +			.addr	= 0x50,
> > +			.flags	= I2C_M_RD,
> > +			.len	= 20,
> > +			.buf	= block,
> > +		}
> > +	};
> > +
> > +	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
> 
> You are reading 20 bytes when you really only need 10. It would be more
> efficient to read 8 bytes first, and only if needed, the two remaining
> ones..
> 

What shall we do? On the one hand you complain about the intensive use
of the slow i2c bus. On the other hand you ask to add a second check for
the good case, when we get a valid EDID via i2c. I'm not experienced at
all in i2c bus driver handling. How would we have to change both
radeon_ddc probing functions to request only the first byte?


Point 4:
I've checked your comments and updated the patch. Hopefully, it fits now
better to the linux kernel coding style. Thank you for the hints.


A subsequent mail will contain the updated patch proposal. 

Best regards

Thomas


^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-21 15:31 ` Thomas Reim
@ 2011-06-22  1:20   ` reimth
  -1 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-06-22  1:20 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel
  Cc: dri-devel, linux-kernel, Thomas Reim

From: Thomas Reim <rdratlos@yahoo.co.uk>

Some integrated ATI Radeon chipset implementations
(e. g. Asus M2A-VM HDMI) indicate the availability
of a DDC even when there's no monitor connected.
In this case, drm_get_edid() and drm_edid_block_valid()
periodically dump data and kernel errors into system
log files and onto terminals, which lead to an unacceptable
system behaviour.

Tested since kernel 2.35 on Asus M2A-VM HDMI board

Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
---
 drivers/gpu/drm/radeon/radeon_connectors.c |   21 +++++++++--
 drivers/gpu/drm/radeon/radeon_display.c    |   11 ++++++
 drivers/gpu/drm/radeon/radeon_i2c.c        |   55 ++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/radeon_mode.h       |    1 +
 4 files changed, 85 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index cbfca3a..497e32a 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -825,9 +825,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 	int i;
 	enum drm_connector_status ret = connector_status_disconnected;
 	bool dret = false;
-
-	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector);
+
+	if (radeon_connector->ddc_bus) {
+		/* AMD 690 chipset series HDMI DDC quirk:
+		 * Some integrated ATI Radeon chipset implementations (e. g.
+		 * Asus M2A-VM HDMI) indicate the availability of a DDC even
+		 * when there's no monitor connected to HDMI. For HDMI
+		 * connectors we check for the availability of EDID with
+		 * at least a correct EDID header and EDID version/revision
+		 * information. Only then, DDC is assumed to be available.
+		 * This prevents drm_get_edid() and drm_edid_block_valid() of
+		 * periodically dumping data and kernel errors into the logs
+		 * and onto the terminal, which would lead to an unacceptable
+		 * system behaviour */
+		if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)
+			dret = radeon_ddc_edid_probe(radeon_connector);
+		else
+			dret = radeon_ddc_probe(radeon_connector);
+	}
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 292f73f..550f143 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -715,6 +715,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
 	if (ret) {
 		radeon_setup_encoder_clones(dev);
 		radeon_print_display_setup(dev);
+		/* Is this really required here?
+		   Seems to just force drm to dump EDID errors
+		   to kernel logs */
 		list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
 			radeon_ddc_dump(drm_connector);
 	}
@@ -777,8 +780,16 @@ static int radeon_ddc_dump(struct drm_connector *connector)
 	if (!radeon_connector->ddc_bus)
 		return -1;
 	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
+	/* Asus M2A-VM HDMI DDC quirk: Log EDID retrieval status here once,
+	 * instead of periodically dumping data and kernel errors into the
+	 * logs, if a monitor is not connected to HDMI */
 	if (edid) {
+		DRM_INFO("Radeon display connector %s: Found valid EDID",
+				drm_get_connector_name(connector));
 		kfree(edid);
+	} else {
+		DRM_INFO("Radeon display connector %s: No display connected or invalid EDID",
+				drm_get_connector_name(connector));
 	}
 	return ret;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 781196d..80b871f 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -63,6 +63,61 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 	return false;
 }
 
+/*
+ * Probe EDID information via I2C:
+ * Try to fetch EDID information by calling i2c_transfer driver function and
+ * probe for valid EDID header and version information.
+ *
+ * AMD 690 chipset series HDMI DDC quirk:
+ * Some integrated ATI Radeon chipset implementations (e. g. Asus M2A-VM HDMI
+ * indicate the availability of a DDC even when there's no monitor connected.
+ * Invalid EDID leads to flooding of logs and terminals with error messages
+ */
+bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector)
+{
+	u8 out_buf[] = {0x0, 0x0};
+	u8 block[20];
+	int ret;
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= 0x50,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= out_buf,
+		}, {
+			.addr	= 0x50,
+			.flags	= I2C_M_RD,
+			.len	= 20,
+			.buf	= block,
+		}
+	};
+
+	/* on hw with routers, select right port */
+	if (radeon_connector->router.ddc_valid)
+		radeon_router_select_ddc_port(radeon_connector);
+
+	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
+	if (ret == 2)
+		if (block[0] == 0x00 &&
+		    block[7] == 0x00 &&
+		    block[1] == 0xff &&
+		    block[2] == 0xff &&
+		    block[3] == 0xff &&
+		    block[4] == 0xff &&
+		    block[5] == 0xff &&
+		    block[6] == 0xff)
+			/* EDID header starts with:
+			 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00
+			 */
+			if (block[18] != 0x00 || block[19] != 0x00)
+				/* EDID header ends with EDID version and
+				 * revision number <> 0.0
+				 */
+				return true;
+	/* Couldn't find an accessible EDID on this connector */
+	return false;
+}
+
 /* bit banging i2c */
 
 static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 6df4e3c..14710fc 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -515,6 +515,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
 extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
+extern bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
@ 2011-06-22  1:20   ` reimth
  0 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-06-22  1:20 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare, Tyson Whitehead
  Cc: dri-devel, linux-kernel, Thomas Reim

From: Thomas Reim <rdratlos@yahoo.co.uk>

Some integrated ATI Radeon chipset implementations
(e. g. Asus M2A-VM HDMI) indicate the availability
of a DDC even when there's no monitor connected.
In this case, drm_get_edid() and drm_edid_block_valid()
periodically dump data and kernel errors into system
log files and onto terminals, which lead to an unacceptable
system behaviour.

Tested since kernel 2.35 on Asus M2A-VM HDMI board

Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
---
 drivers/gpu/drm/radeon/radeon_connectors.c |   21 +++++++++--
 drivers/gpu/drm/radeon/radeon_display.c    |   11 ++++++
 drivers/gpu/drm/radeon/radeon_i2c.c        |   55 ++++++++++++++++++++++++++++
 drivers/gpu/drm/radeon/radeon_mode.h       |    1 +
 4 files changed, 85 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index cbfca3a..497e32a 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -825,9 +825,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 	int i;
 	enum drm_connector_status ret = connector_status_disconnected;
 	bool dret = false;
-
-	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector);
+
+	if (radeon_connector->ddc_bus) {
+		/* AMD 690 chipset series HDMI DDC quirk:
+		 * Some integrated ATI Radeon chipset implementations (e. g.
+		 * Asus M2A-VM HDMI) indicate the availability of a DDC even
+		 * when there's no monitor connected to HDMI. For HDMI
+		 * connectors we check for the availability of EDID with
+		 * at least a correct EDID header and EDID version/revision
+		 * information. Only then, DDC is assumed to be available.
+		 * This prevents drm_get_edid() and drm_edid_block_valid() of
+		 * periodically dumping data and kernel errors into the logs
+		 * and onto the terminal, which would lead to an unacceptable
+		 * system behaviour */
+		if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)
+			dret = radeon_ddc_edid_probe(radeon_connector);
+		else
+			dret = radeon_ddc_probe(radeon_connector);
+	}
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 292f73f..550f143 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -715,6 +715,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
 	if (ret) {
 		radeon_setup_encoder_clones(dev);
 		radeon_print_display_setup(dev);
+		/* Is this really required here?
+		   Seems to just force drm to dump EDID errors
+		   to kernel logs */
 		list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
 			radeon_ddc_dump(drm_connector);
 	}
@@ -777,8 +780,16 @@ static int radeon_ddc_dump(struct drm_connector *connector)
 	if (!radeon_connector->ddc_bus)
 		return -1;
 	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
+	/* Asus M2A-VM HDMI DDC quirk: Log EDID retrieval status here once,
+	 * instead of periodically dumping data and kernel errors into the
+	 * logs, if a monitor is not connected to HDMI */
 	if (edid) {
+		DRM_INFO("Radeon display connector %s: Found valid EDID",
+				drm_get_connector_name(connector));
 		kfree(edid);
+	} else {
+		DRM_INFO("Radeon display connector %s: No display connected or invalid EDID",
+				drm_get_connector_name(connector));
 	}
 	return ret;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 781196d..80b871f 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -63,6 +63,61 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 	return false;
 }
 
+/*
+ * Probe EDID information via I2C:
+ * Try to fetch EDID information by calling i2c_transfer driver function and
+ * probe for valid EDID header and version information.
+ *
+ * AMD 690 chipset series HDMI DDC quirk:
+ * Some integrated ATI Radeon chipset implementations (e. g. Asus M2A-VM HDMI
+ * indicate the availability of a DDC even when there's no monitor connected.
+ * Invalid EDID leads to flooding of logs and terminals with error messages
+ */
+bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector)
+{
+	u8 out_buf[] = {0x0, 0x0};
+	u8 block[20];
+	int ret;
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= 0x50,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= out_buf,
+		}, {
+			.addr	= 0x50,
+			.flags	= I2C_M_RD,
+			.len	= 20,
+			.buf	= block,
+		}
+	};
+
+	/* on hw with routers, select right port */
+	if (radeon_connector->router.ddc_valid)
+		radeon_router_select_ddc_port(radeon_connector);
+
+	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
+	if (ret == 2)
+		if (block[0] == 0x00 &&
+		    block[7] == 0x00 &&
+		    block[1] == 0xff &&
+		    block[2] == 0xff &&
+		    block[3] == 0xff &&
+		    block[4] == 0xff &&
+		    block[5] == 0xff &&
+		    block[6] == 0xff)
+			/* EDID header starts with:
+			 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00
+			 */
+			if (block[18] != 0x00 || block[19] != 0x00)
+				/* EDID header ends with EDID version and
+				 * revision number <> 0.0
+				 */
+				return true;
+	/* Couldn't find an accessible EDID on this connector */
+	return false;
+}
+
 /* bit banging i2c */
 
 static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 6df4e3c..14710fc 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -515,6 +515,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
 extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
+extern bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-22  1:20   ` reimth
  (?)
@ 2011-06-22  1:28   ` Alex Deucher
  2011-06-22 15:17     ` Thomas Reim
  -1 siblings, 1 reply; 50+ messages in thread
From: Alex Deucher @ 2011-06-22  1:28 UTC (permalink / raw)
  To: reimth
  Cc: Dave Airlie, Mario Kleiner, Jean Delvare, Tyson Whitehead,
	Jason Wessel, dri-devel, linux-kernel, Thomas Reim

On Tue, Jun 21, 2011 at 9:20 PM,  <reimth@googlemail.com> wrote:
> From: Thomas Reim <rdratlos@yahoo.co.uk>
>
> Some integrated ATI Radeon chipset implementations
> (e. g. Asus M2A-VM HDMI) indicate the availability
> of a DDC even when there's no monitor connected.
> In this case, drm_get_edid() and drm_edid_block_valid()
> periodically dump data and kernel errors into system
> log files and onto terminals, which lead to an unacceptable
> system behaviour.
>
> Tested since kernel 2.35 on Asus M2A-VM HDMI board
>
> Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
> ---
>  drivers/gpu/drm/radeon/radeon_connectors.c |   21 +++++++++--
>  drivers/gpu/drm/radeon/radeon_display.c    |   11 ++++++
>  drivers/gpu/drm/radeon/radeon_i2c.c        |   55 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/radeon/radeon_mode.h       |    1 +
>  4 files changed, 85 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> index cbfca3a..497e32a 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -825,9 +825,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
>        int i;
>        enum drm_connector_status ret = connector_status_disconnected;
>        bool dret = false;
> -
> -       if (radeon_connector->ddc_bus)
> -               dret = radeon_ddc_probe(radeon_connector);
> +
> +       if (radeon_connector->ddc_bus) {
> +               /* AMD 690 chipset series HDMI DDC quirk:
> +                * Some integrated ATI Radeon chipset implementations (e. g.
> +                * Asus M2A-VM HDMI) indicate the availability of a DDC even
> +                * when there's no monitor connected to HDMI. For HDMI
> +                * connectors we check for the availability of EDID with
> +                * at least a correct EDID header and EDID version/revision
> +                * information. Only then, DDC is assumed to be available.
> +                * This prevents drm_get_edid() and drm_edid_block_valid() of
> +                * periodically dumping data and kernel errors into the logs
> +                * and onto the terminal, which would lead to an unacceptable
> +                * system behaviour */
> +               if (connector->connector_type == DRM_MODE_CONNECTOR_HDMIA)

This is going to enable your quirk on every board with an HDMI port.
If we need to add a quirk for your board, let's make it board
specific.  It might be better to just disable edid polling for certain
connectors on certain boards if they cause problems when no monitor is
detected.

Alex

> +                       dret = radeon_ddc_edid_probe(radeon_connector);
> +               else
> +                       dret = radeon_ddc_probe(radeon_connector);
> +       }
>        if (dret) {
>                if (radeon_connector->edid) {
>                        kfree(radeon_connector->edid);
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index 292f73f..550f143 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -715,6 +715,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
>        if (ret) {
>                radeon_setup_encoder_clones(dev);
>                radeon_print_display_setup(dev);
> +               /* Is this really required here?
> +                  Seems to just force drm to dump EDID errors
> +                  to kernel logs */
>                list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
>                        radeon_ddc_dump(drm_connector);
>        }
> @@ -777,8 +780,16 @@ static int radeon_ddc_dump(struct drm_connector *connector)
>        if (!radeon_connector->ddc_bus)
>                return -1;
>        edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
> +       /* Asus M2A-VM HDMI DDC quirk: Log EDID retrieval status here once,
> +        * instead of periodically dumping data and kernel errors into the
> +        * logs, if a monitor is not connected to HDMI */
>        if (edid) {
> +               DRM_INFO("Radeon display connector %s: Found valid EDID",
> +                               drm_get_connector_name(connector));
>                kfree(edid);
> +       } else {
> +               DRM_INFO("Radeon display connector %s: No display connected or invalid EDID",
> +                               drm_get_connector_name(connector));
>        }
>        return ret;
>  }
> diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
> index 781196d..80b871f 100644
> --- a/drivers/gpu/drm/radeon/radeon_i2c.c
> +++ b/drivers/gpu/drm/radeon/radeon_i2c.c
> @@ -63,6 +63,61 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
>        return false;
>  }
>
> +/*
> + * Probe EDID information via I2C:
> + * Try to fetch EDID information by calling i2c_transfer driver function and
> + * probe for valid EDID header and version information.
> + *
> + * AMD 690 chipset series HDMI DDC quirk:
> + * Some integrated ATI Radeon chipset implementations (e. g. Asus M2A-VM HDMI
> + * indicate the availability of a DDC even when there's no monitor connected.
> + * Invalid EDID leads to flooding of logs and terminals with error messages
> + */
> +bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector)
> +{
> +       u8 out_buf[] = {0x0, 0x0};
> +       u8 block[20];
> +       int ret;
> +       struct i2c_msg msgs[] = {
> +               {
> +                       .addr   = 0x50,
> +                       .flags  = 0,
> +                       .len    = 1,
> +                       .buf    = out_buf,
> +               }, {
> +                       .addr   = 0x50,
> +                       .flags  = I2C_M_RD,
> +                       .len    = 20,
> +                       .buf    = block,
> +               }
> +       };
> +
> +       /* on hw with routers, select right port */
> +       if (radeon_connector->router.ddc_valid)
> +               radeon_router_select_ddc_port(radeon_connector);
> +
> +       ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
> +       if (ret == 2)
> +               if (block[0] == 0x00 &&
> +                   block[7] == 0x00 &&
> +                   block[1] == 0xff &&
> +                   block[2] == 0xff &&
> +                   block[3] == 0xff &&
> +                   block[4] == 0xff &&
> +                   block[5] == 0xff &&
> +                   block[6] == 0xff)
> +                       /* EDID header starts with:
> +                        * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00
> +                        */
> +                       if (block[18] != 0x00 || block[19] != 0x00)
> +                               /* EDID header ends with EDID version and
> +                                * revision number <> 0.0
> +                                */
> +                               return true;
> +       /* Couldn't find an accessible EDID on this connector */
> +       return false;
> +}
> +
>  /* bit banging i2c */
>
>  static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index 6df4e3c..14710fc 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -515,6 +515,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
>  extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
>  extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
>  extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
> +extern bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector);
>  extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
>
>  extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
> --
> 1.7.1
>
>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error  flooding problem
  2011-06-22  1:11   ` Thomas Reim
@ 2011-06-22 13:53       ` Jean Delvare
  0 siblings, 0 replies; 50+ messages in thread
From: Jean Delvare @ 2011-06-22 13:53 UTC (permalink / raw)
  To: Thomas Reim
  Cc: Thomas Reim, Dave Airlie, Alex Deucher, Mario Kleiner,
	Tyson Whitehead, Jason Wessel, dri-devel, linux-kernel,
	Thomas Reim

Hallo Thomas,

On Wed, 22 Jun 2011 03:11:24 +0200, Thomas Reim wrote:
> Salut Jean, 
> 
> thank you for the detailed reply. If I got you right you rose the
> following main points:
> 1. Root cause leading to flooding problem (you assume i2c bus not 
>    working correctly, i. e. "stuck bus") not adequately addressed by 
>    the fix 
> 2. Alternative proposal: Fix the verbose logging issue
> 3. i2c EDID probing inefficiently implemented
> 4. Strange coding and commenting style

Yes, this is a good summary.

> 
> Point 1:
> The Asus M2A-VM HDMI EDID error flooding problem was already addressed
> in this mailing list in April this year
> (https://lkml.org/lkml/2011/4/15/36). But it was not further discussed,

This is more of a workaround than a bug fix.

> maybe due to missing bug information. I wanted to provide this
> information to that thread, but your mail was faster :-). In the
> following, you can see the i2c dump of the DVI connector of the AMD 690G
> chip, where the monitor is connected to:
>      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
> 00: 00 ff ff ff ff ff ff 00 4c 2d ed 00 39 31 49 44    ........L-?.91ID
> 10: 2d 0e 01 03 80 26 1e 78 2a ee 95 a3 54 4c 99 26    -????&?x*???TL?&
> 20: 0f 50 54 bf ef 80 81 80 71 4f 01 01 01 01 01 01    ?PT?????qO??????
> 30: 01 01 01 01 01 01 30 2a 00 98 51 00 2a 40 30 70    ??????0*.?Q.*@0p
> 40: 13 00 78 2d 11 00 00 1e 00 00 00 fd 00 38 4c 1e    ?.x-?..?...?.8L?
> 50: 51 0e 00 0a 20 20 20 20 20 20 00 00 00 fc 00 53    Q?.?      ...?.S
> 60: 79 6e 63 4d 61 73 74 65 72 0a 20 20 00 00 00 ff    yncMaster?  ....
> 70: 00 48 34 4a 58 42 30 31 35 30 33 0a 20 20 00 e4    .H4JXB01503?  .?
> 80: 00 ff ff ff ff ff ff 00 4c 2d ed 00 39 31 49 44    ........L-?.91ID
> 90: 2d 0e 01 03 80 26 1e 78 2a ee 95 a3 54 4c 99 26    -????&?x*???TL?&
> a0: 0f 50 54 bf ef 80 81 80 71 4f 01 01 01 01 01 01    ?PT?????qO??????
> b0: 01 01 01 01 01 01 30 2a 00 98 51 00 2a 40 30 70    ??????0*.?Q.*@0p
> c0: 13 00 78 2d 11 00 00 1e 00 00 00 fd 00 38 4c 1e    ?.x-?..?...?.8L?
> d0: 51 0e 00 0a 20 20 20 20 20 20 00 00 00 fc 00 53    Q?.?      ...?.S
> e0: 79 6e 63 4d 61 73 74 65 72 0a 20 20 00 00 00 ff    yncMaster?  ....
> f0: 00 48 34 4a 58 42 30 31 35 30 33 0a 20 20 00 e4    .H4JXB01503?  .?

Looks very good.

> 
> Then we have the i2c dump of the HDMI connector with no monitor
> connected: 
>      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
> 00: 00 00 00 00 00 00 00 00 00 00 1f 00 00 00 00 00    ..........?.....
> 10: 00 00 00 00 00 XX 00 01 00 00 00 00 1f 00 00 00    .....X.?....?...
> 20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
> 30: 00 00 00 00 00 XX 00 00 00 00 00 7f 00 00 00 00    .....X.....?....
> 40: 00 00 1f 00 00 00 00 00 00 00 00 00 00 00 00 00    ..?.............
> 50: 00 00 00 00 00 07 00 01 00 00 00 00 00 00 00 00    .....?.?........
> 60: 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00    .....?..........
> 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
> 80: 00 00 ff 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
> 90: 00 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00    .....?..........
> a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
> b0: 00 00 00 00 00 ff 00 00 3f 00 00 00 00 00 00 00    ........?.......
> c0: 00 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00    .........?......
> d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
> e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
> f0: 00 00 00 00 XX 00 00 7f 00 00 00 00 00 00 00 00    ....X..?........

Obviously bogus. Is the result similar with a second dump, or is this
"moving noise"?

Can you post the output of i2cdetect for this i2c adapter?

I guess that the I2C adapter doesn't get created at all if you pass
bit_test=1 to module i2c-algo-bit?

I admit that the above is a little different from what I expected (all
zeroes). My initial proposal of only reading the first 2 bytes of the
EEPROM is too weak given the output above, but reading 3 or 4 bytes
should be sufficient.

Did you try connecting a monitor to the HDMI port? I am curious if
reading the EDID will work reliably or not. This is a very important
point to figure out what exactly is going on at the hardware level.
Even better would be if you could try with several monitors, and/or
compare the same EDID read from your system over HDMI and read from
another, known good system (or yours over DVI for example.)

Could the problem come from the fact that the HDMI connector is on a
separate riser card on your board, which maybe you don't use at all? If
so, could you please plug it in and see if it helps?

> 
> For this connector radeon_ddc_probe() reports a working DDC, which leads
> to the catastrophic situation that drm_get_edid() and
> drm_edid_block_valid() flood the logs with EDID error messages and
> dumps.

I understand that.

> 
> Finally, we have the i2c dump of the VGA connector, where also no
> monitor is connected to:
>      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
> 00: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 20: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 30: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 40: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 50: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 60: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 70: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 80: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 90: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> a0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> b0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> c0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> d0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> e0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> f0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 
> radeon_ddc_probe() reports no DDC.

Yes, this is what the HDMI port should report as well: no ack from the
EEPROM chip, as there is no EEPROM at all.

> 
> Do you really believe that this is caused by a stuck i2c bus?

Almost. A SDA line stuck low would report zeroes all around the place,
which isn't the case here. Normally the neutral state of an I2C bus is
SCL and SDA high, so you should have pull-up resistors on each wire.
Only if a master or slave actively pulls the lines down, should they go
low. This is obviously not the case on your HDMI connector, as we see
noise in the dump.

If there no alternative way to know if an HDMI connector is populated
or not?

> Following
> the i2c dumps it really makes sense to add a limited check of some major
> EDID parts from i2c register for DDC probing. Current radeon_ddc_probe()
> just checks that we CAN get data from i2c register 0x50 and leaves the
> rest to the log flooding drm_edid functions.

Correct.

> Point 2:
> Your proposal has been intensively discussed after release of kernel
> 2.35. Many users suffered from this log flooding. Many people proposed
> fixes, e. g. log EDID errors only once. None of the proposals was taken
> over by the kernel developers. The linux distributions' bug lists are
> full of these unsolved bug reports. Also in kernel 3.0 no solution was
> released. For me that means, kernel people have stringent reasons to NOT
> touch the log flooding functions in DRM. Therefore, I spent my time to
> fix the problem in the hardware related domain. And the few changes in
> radeon code have solved the problem from 2.35 up to the latest 3.0 git
> version.

Probably preaching in the desert if this was discussed before, but...

IHMO, this error message reporting should be disabled when EDID polling
is enabled. Not just for your specific case, but in general. If the
EDID is invalid for any reason (including damaged EEPROM or
non-conforming display) it won't get fixed magically, so an error once
means an error forever, and it's pointless to repeat the same error
message forever.

Alternatively, we could remember that the error message was printed,
and stop printing it until at least one validation passes (different
screen connected, or transient error gone.)

> Point 3:
> > I don't like this. radeon_ddc_edid_probe() is partly redundant with
> > radeon_ddc_probe() and also partly redundant with drm_get_edid() and
> > drm_edid_is_valid(). It will add yet another round of I2C transactions,
> > and these transactions are slow, so the fewer we have at driver load
> > time, the happier we are. This is even more true these days when every
> > graphics card gets 8 I2C buses created.
> > 
> > If nothing else, you should call radeon_ddc_edid_probe() instead of,
> > not after, radeon_ddc_probe(), to save a transaction.
> 
> This is correct, I was not sure about possible side effects. Therefore,
> I used both functions in my first proposal but limited the new one to
> the DRM_MODE_CONNECTOR_HDMIA types of the eight i2c busses. 

I understand that you wanted to be as little intrusive as possible.
However, your current approach will still slow down probing on many
unrelated systems (many cards have an HDMI connector... most recent
cards, I'd say), while still not addressing the general case: what if
another system has similar problems on a different connector type?

So you are half-way to a generic fix. I'd rather got for a board
specific fix (as Alex Deucher proposed) or a truly generic fix (not
limited to a specific connector type.)

> > +bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector)
> > > +{
> > > +	u8 out_buf[] = { 0x0, 0x0};
> > 
> > You only use the first byte (same in radeon_ddc_probe, could be
> > optimized.)
> > 
> > > +	u8 block[20];
> > > +	int ret;
> > > +	struct i2c_msg msgs[] = {
> > > +		{
> > > +			.addr	= 0x50,
> > > +			.flags	= 0,
> > > +			.len	= 1,
> > > +			.buf	= out_buf,
> > > +		}, {
> > > +			.addr	= 0x50,
> > > +			.flags	= I2C_M_RD,
> > > +			.len	= 20,
> > > +			.buf	= block,
> > > +		}
> > > +	};
> > > +
> > > +	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
> > 
> > You are reading 20 bytes when you really only need 10. It would be more
> > efficient to read 8 bytes first, and only if needed, the two remaining
> > ones..
> 
> What shall we do? On the one hand you complain about the intensive use
> of the slow i2c bus. On the other hand you ask to add a second check for
> the good case, when we get a valid EDID via i2c.

My point was simply that it is faster to read 8 bytes and then 2 bytes
than 20 bytes. As a side bonus, you don't even have to read the last 2
bytes, if the 8 first aren't OK. But again this was really a
theoretical point, as I don't think there is any point in reading that
much from the EDID, when the problem is already visible within the
first few bytes.

> I'm not experienced at
> all in i2c bus driver handling. How would we have to change both
> radeon_ddc probing functions to request only the first byte?

radeon_ddc_probe() is already doing exactly that. My proposal (if and
only if we want to go for a generic fix) is to simply extend
radeon_ddc_probe() to read a few more bytes. That being said, we have
to be cautious: looking at drm_edid_block_valid(), I can see that it
has some tolerance and accepts EDID where only 6 of the first 8 bytes
match the standard signature. Your own proposal is stricter than this.

This really makes me believe that the layering between the drm helpers
and the radeon driver is not optimal. drm_edid_block_valid() is being
called too late in the chain, when apparently this is what you'd need
(at least the first part) to detect the broken I2C bus on your HDMI
connector early.

The sole fact that function radeon_ddc_probe() exists in driver radeon
while it has very little radeon-specific logic in it [1], seems wrong.
Ignoring this thought for a moment, an easy, general workaround for
your problem would be:

---
 drivers/gpu/drm/drm_edid.c          |   23 ++++++++++++++++++-----
 drivers/gpu/drm/radeon/radeon_i2c.c |   10 +++++-----
 include/drm/drm_crtc.h              |    1 +
 3 files changed, 24 insertions(+), 10 deletions(-)

--- linux-3.0-rc4.orig/drivers/gpu/drm/drm_edid.c	2011-06-21 10:30:19.000000000 +0200
+++ linux-3.0-rc4/drivers/gpu/drm/drm_edid.c	2011-06-22 13:49:10.000000000 +0200
@@ -128,6 +128,23 @@ static const u8 edid_header[] = {
 };
 
 /*
+ * Sanity check the header of the base EDID block.  Return 8 if the header
+ * is perfect, down to 0 if it's totally wrong.
+ */
+int drm_edid_header_valid(const u8 *raw_edid)
+{
+	int i, score = 0;
+
+	for (i = 0; i < sizeof(edid_header); i++)
+		if (raw_edid[i] == edid_header[i])
+			score++;
+
+	return score;
+}
+EXPORT_SYMBOL(drm_edid_header_valid);
+
+
+/*
  * Sanity check the EDID block (base or extension).  Return 0 if the block
  * doesn't check out, or 1 if it's valid.
  */
@@ -139,11 +156,7 @@ drm_edid_block_valid(u8 *raw_edid)
 	struct edid *edid = (struct edid *)raw_edid;
 
 	if (raw_edid[0] == 0x00) {
-		int score = 0;
-
-		for (i = 0; i < sizeof(edid_header); i++)
-			if (raw_edid[i] == edid_header[i])
-				score++;
+		int score = drm_edid_header_valid(raw_edid);
 
 		if (score == 8) ;
 		else if (score >= 6) {
--- linux-3.0-rc4.orig/drivers/gpu/drm/radeon/radeon_i2c.c	2011-05-30 20:45:08.000000000 +0200
+++ linux-3.0-rc4/drivers/gpu/drm/radeon/radeon_i2c.c	2011-06-22 12:00:35.000000000 +0200
@@ -34,20 +34,20 @@
  */
 bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 {
-	u8 out_buf[] = { 0x0, 0x0};
-	u8 buf[2];
+	u8 out = 0x0;
+	u8 buf[8];
 	int ret;
 	struct i2c_msg msgs[] = {
 		{
 			.addr = 0x50,
 			.flags = 0,
 			.len = 1,
-			.buf = out_buf,
+			.buf = &out,
 		},
 		{
 			.addr = 0x50,
 			.flags = I2C_M_RD,
-			.len = 1,
+			.len = 8,
 			.buf = buf,
 		}
 	};
@@ -57,7 +57,7 @@ bool radeon_ddc_probe(struct radeon_conn
 		radeon_router_select_ddc_port(radeon_connector);
 
 	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
-	if (ret == 2)
+	if (ret == 2 && drm_edid_header_valid(buf) >= 6)
 		return true;
 
 	return false;
--- linux-3.0-rc4.orig/include/drm/drm_crtc.h	2011-06-21 10:30:19.000000000 +0200
+++ linux-3.0-rc4/include/drm/drm_crtc.h	2011-06-22 12:02:24.000000000 +0200
@@ -802,6 +802,7 @@ extern struct drm_display_mode *drm_gtf_
 extern int drm_add_modes_noedid(struct drm_connector *connector,
 				int hdisplay, int vdisplay);
 
+extern int drm_edid_header_valid(const u8 *raw_edid);
 extern bool drm_edid_is_valid(struct edid *edid);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
 					   int hsize, int vsize, int fresh);


But if Alex believes that the case is rare enough that a board-specific
workaround is better, that's totally fine with me too. He is the master!

> Point 4:
> I've checked your comments and updated the patch. Hopefully, it fits now
> better to the linux kernel coding style. Thank you for the hints.
> 
> 
> A subsequent mail will contain the updated patch proposal. 

[1] I wonder why radeon_router_select_ddc_port() isn't part of
pre_xfer().

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
@ 2011-06-22 13:53       ` Jean Delvare
  0 siblings, 0 replies; 50+ messages in thread
From: Jean Delvare @ 2011-06-22 13:53 UTC (permalink / raw)
  To: Thomas Reim
  Cc: Thomas Reim, Dave Airlie, Alex Deucher, Mario Kleiner,
	Tyson Whitehead, Jason Wessel, dri-devel, linux-kernel,
	Thomas Reim

Hallo Thomas,

On Wed, 22 Jun 2011 03:11:24 +0200, Thomas Reim wrote:
> Salut Jean, 
> 
> thank you for the detailed reply. If I got you right you rose the
> following main points:
> 1. Root cause leading to flooding problem (you assume i2c bus not 
>    working correctly, i. e. "stuck bus") not adequately addressed by 
>    the fix 
> 2. Alternative proposal: Fix the verbose logging issue
> 3. i2c EDID probing inefficiently implemented
> 4. Strange coding and commenting style

Yes, this is a good summary.

> 
> Point 1:
> The Asus M2A-VM HDMI EDID error flooding problem was already addressed
> in this mailing list in April this year
> (https://lkml.org/lkml/2011/4/15/36). But it was not further discussed,

This is more of a workaround than a bug fix.

> maybe due to missing bug information. I wanted to provide this
> information to that thread, but your mail was faster :-). In the
> following, you can see the i2c dump of the DVI connector of the AMD 690G
> chip, where the monitor is connected to:
>      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
> 00: 00 ff ff ff ff ff ff 00 4c 2d ed 00 39 31 49 44    ........L-?.91ID
> 10: 2d 0e 01 03 80 26 1e 78 2a ee 95 a3 54 4c 99 26    -????&?x*???TL?&
> 20: 0f 50 54 bf ef 80 81 80 71 4f 01 01 01 01 01 01    ?PT?????qO??????
> 30: 01 01 01 01 01 01 30 2a 00 98 51 00 2a 40 30 70    ??????0*.?Q.*@0p
> 40: 13 00 78 2d 11 00 00 1e 00 00 00 fd 00 38 4c 1e    ?.x-?..?...?.8L?
> 50: 51 0e 00 0a 20 20 20 20 20 20 00 00 00 fc 00 53    Q?.?      ...?.S
> 60: 79 6e 63 4d 61 73 74 65 72 0a 20 20 00 00 00 ff    yncMaster?  ....
> 70: 00 48 34 4a 58 42 30 31 35 30 33 0a 20 20 00 e4    .H4JXB01503?  .?
> 80: 00 ff ff ff ff ff ff 00 4c 2d ed 00 39 31 49 44    ........L-?.91ID
> 90: 2d 0e 01 03 80 26 1e 78 2a ee 95 a3 54 4c 99 26    -????&?x*???TL?&
> a0: 0f 50 54 bf ef 80 81 80 71 4f 01 01 01 01 01 01    ?PT?????qO??????
> b0: 01 01 01 01 01 01 30 2a 00 98 51 00 2a 40 30 70    ??????0*.?Q.*@0p
> c0: 13 00 78 2d 11 00 00 1e 00 00 00 fd 00 38 4c 1e    ?.x-?..?...?.8L?
> d0: 51 0e 00 0a 20 20 20 20 20 20 00 00 00 fc 00 53    Q?.?      ...?.S
> e0: 79 6e 63 4d 61 73 74 65 72 0a 20 20 00 00 00 ff    yncMaster?  ....
> f0: 00 48 34 4a 58 42 30 31 35 30 33 0a 20 20 00 e4    .H4JXB01503?  .?

Looks very good.

> 
> Then we have the i2c dump of the HDMI connector with no monitor
> connected: 
>      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
> 00: 00 00 00 00 00 00 00 00 00 00 1f 00 00 00 00 00    ..........?.....
> 10: 00 00 00 00 00 XX 00 01 00 00 00 00 1f 00 00 00    .....X.?....?...
> 20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
> 30: 00 00 00 00 00 XX 00 00 00 00 00 7f 00 00 00 00    .....X.....?....
> 40: 00 00 1f 00 00 00 00 00 00 00 00 00 00 00 00 00    ..?.............
> 50: 00 00 00 00 00 07 00 01 00 00 00 00 00 00 00 00    .....?.?........
> 60: 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00    .....?..........
> 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
> 80: 00 00 ff 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
> 90: 00 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00    .....?..........
> a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
> b0: 00 00 00 00 00 ff 00 00 3f 00 00 00 00 00 00 00    ........?.......
> c0: 00 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00    .........?......
> d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
> e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
> f0: 00 00 00 00 XX 00 00 7f 00 00 00 00 00 00 00 00    ....X..?........

Obviously bogus. Is the result similar with a second dump, or is this
"moving noise"?

Can you post the output of i2cdetect for this i2c adapter?

I guess that the I2C adapter doesn't get created at all if you pass
bit_test=1 to module i2c-algo-bit?

I admit that the above is a little different from what I expected (all
zeroes). My initial proposal of only reading the first 2 bytes of the
EEPROM is too weak given the output above, but reading 3 or 4 bytes
should be sufficient.

Did you try connecting a monitor to the HDMI port? I am curious if
reading the EDID will work reliably or not. This is a very important
point to figure out what exactly is going on at the hardware level.
Even better would be if you could try with several monitors, and/or
compare the same EDID read from your system over HDMI and read from
another, known good system (or yours over DVI for example.)

Could the problem come from the fact that the HDMI connector is on a
separate riser card on your board, which maybe you don't use at all? If
so, could you please plug it in and see if it helps?

> 
> For this connector radeon_ddc_probe() reports a working DDC, which leads
> to the catastrophic situation that drm_get_edid() and
> drm_edid_block_valid() flood the logs with EDID error messages and
> dumps.

I understand that.

> 
> Finally, we have the i2c dump of the VGA connector, where also no
> monitor is connected to:
>      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
> 00: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 20: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 30: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 40: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 50: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 60: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 70: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 80: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 90: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> a0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> b0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> c0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> d0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> e0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> f0: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX    XXXXXXXXXXXXXXXX
> 
> radeon_ddc_probe() reports no DDC.

Yes, this is what the HDMI port should report as well: no ack from the
EEPROM chip, as there is no EEPROM at all.

> 
> Do you really believe that this is caused by a stuck i2c bus?

Almost. A SDA line stuck low would report zeroes all around the place,
which isn't the case here. Normally the neutral state of an I2C bus is
SCL and SDA high, so you should have pull-up resistors on each wire.
Only if a master or slave actively pulls the lines down, should they go
low. This is obviously not the case on your HDMI connector, as we see
noise in the dump.

If there no alternative way to know if an HDMI connector is populated
or not?

> Following
> the i2c dumps it really makes sense to add a limited check of some major
> EDID parts from i2c register for DDC probing. Current radeon_ddc_probe()
> just checks that we CAN get data from i2c register 0x50 and leaves the
> rest to the log flooding drm_edid functions.

Correct.

> Point 2:
> Your proposal has been intensively discussed after release of kernel
> 2.35. Many users suffered from this log flooding. Many people proposed
> fixes, e. g. log EDID errors only once. None of the proposals was taken
> over by the kernel developers. The linux distributions' bug lists are
> full of these unsolved bug reports. Also in kernel 3.0 no solution was
> released. For me that means, kernel people have stringent reasons to NOT
> touch the log flooding functions in DRM. Therefore, I spent my time to
> fix the problem in the hardware related domain. And the few changes in
> radeon code have solved the problem from 2.35 up to the latest 3.0 git
> version.

Probably preaching in the desert if this was discussed before, but...

IHMO, this error message reporting should be disabled when EDID polling
is enabled. Not just for your specific case, but in general. If the
EDID is invalid for any reason (including damaged EEPROM or
non-conforming display) it won't get fixed magically, so an error once
means an error forever, and it's pointless to repeat the same error
message forever.

Alternatively, we could remember that the error message was printed,
and stop printing it until at least one validation passes (different
screen connected, or transient error gone.)

> Point 3:
> > I don't like this. radeon_ddc_edid_probe() is partly redundant with
> > radeon_ddc_probe() and also partly redundant with drm_get_edid() and
> > drm_edid_is_valid(). It will add yet another round of I2C transactions,
> > and these transactions are slow, so the fewer we have at driver load
> > time, the happier we are. This is even more true these days when every
> > graphics card gets 8 I2C buses created.
> > 
> > If nothing else, you should call radeon_ddc_edid_probe() instead of,
> > not after, radeon_ddc_probe(), to save a transaction.
> 
> This is correct, I was not sure about possible side effects. Therefore,
> I used both functions in my first proposal but limited the new one to
> the DRM_MODE_CONNECTOR_HDMIA types of the eight i2c busses. 

I understand that you wanted to be as little intrusive as possible.
However, your current approach will still slow down probing on many
unrelated systems (many cards have an HDMI connector... most recent
cards, I'd say), while still not addressing the general case: what if
another system has similar problems on a different connector type?

So you are half-way to a generic fix. I'd rather got for a board
specific fix (as Alex Deucher proposed) or a truly generic fix (not
limited to a specific connector type.)

> > +bool radeon_ddc_edid_probe(struct radeon_connector *radeon_connector)
> > > +{
> > > +	u8 out_buf[] = { 0x0, 0x0};
> > 
> > You only use the first byte (same in radeon_ddc_probe, could be
> > optimized.)
> > 
> > > +	u8 block[20];
> > > +	int ret;
> > > +	struct i2c_msg msgs[] = {
> > > +		{
> > > +			.addr	= 0x50,
> > > +			.flags	= 0,
> > > +			.len	= 1,
> > > +			.buf	= out_buf,
> > > +		}, {
> > > +			.addr	= 0x50,
> > > +			.flags	= I2C_M_RD,
> > > +			.len	= 20,
> > > +			.buf	= block,
> > > +		}
> > > +	};
> > > +
> > > +	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
> > 
> > You are reading 20 bytes when you really only need 10. It would be more
> > efficient to read 8 bytes first, and only if needed, the two remaining
> > ones..
> 
> What shall we do? On the one hand you complain about the intensive use
> of the slow i2c bus. On the other hand you ask to add a second check for
> the good case, when we get a valid EDID via i2c.

My point was simply that it is faster to read 8 bytes and then 2 bytes
than 20 bytes. As a side bonus, you don't even have to read the last 2
bytes, if the 8 first aren't OK. But again this was really a
theoretical point, as I don't think there is any point in reading that
much from the EDID, when the problem is already visible within the
first few bytes.

> I'm not experienced at
> all in i2c bus driver handling. How would we have to change both
> radeon_ddc probing functions to request only the first byte?

radeon_ddc_probe() is already doing exactly that. My proposal (if and
only if we want to go for a generic fix) is to simply extend
radeon_ddc_probe() to read a few more bytes. That being said, we have
to be cautious: looking at drm_edid_block_valid(), I can see that it
has some tolerance and accepts EDID where only 6 of the first 8 bytes
match the standard signature. Your own proposal is stricter than this.

This really makes me believe that the layering between the drm helpers
and the radeon driver is not optimal. drm_edid_block_valid() is being
called too late in the chain, when apparently this is what you'd need
(at least the first part) to detect the broken I2C bus on your HDMI
connector early.

The sole fact that function radeon_ddc_probe() exists in driver radeon
while it has very little radeon-specific logic in it [1], seems wrong.
Ignoring this thought for a moment, an easy, general workaround for
your problem would be:

---
 drivers/gpu/drm/drm_edid.c          |   23 ++++++++++++++++++-----
 drivers/gpu/drm/radeon/radeon_i2c.c |   10 +++++-----
 include/drm/drm_crtc.h              |    1 +
 3 files changed, 24 insertions(+), 10 deletions(-)

--- linux-3.0-rc4.orig/drivers/gpu/drm/drm_edid.c	2011-06-21 10:30:19.000000000 +0200
+++ linux-3.0-rc4/drivers/gpu/drm/drm_edid.c	2011-06-22 13:49:10.000000000 +0200
@@ -128,6 +128,23 @@ static const u8 edid_header[] = {
 };
 
 /*
+ * Sanity check the header of the base EDID block.  Return 8 if the header
+ * is perfect, down to 0 if it's totally wrong.
+ */
+int drm_edid_header_valid(const u8 *raw_edid)
+{
+	int i, score = 0;
+
+	for (i = 0; i < sizeof(edid_header); i++)
+		if (raw_edid[i] == edid_header[i])
+			score++;
+
+	return score;
+}
+EXPORT_SYMBOL(drm_edid_header_valid);
+
+
+/*
  * Sanity check the EDID block (base or extension).  Return 0 if the block
  * doesn't check out, or 1 if it's valid.
  */
@@ -139,11 +156,7 @@ drm_edid_block_valid(u8 *raw_edid)
 	struct edid *edid = (struct edid *)raw_edid;
 
 	if (raw_edid[0] == 0x00) {
-		int score = 0;
-
-		for (i = 0; i < sizeof(edid_header); i++)
-			if (raw_edid[i] == edid_header[i])
-				score++;
+		int score = drm_edid_header_valid(raw_edid);
 
 		if (score == 8) ;
 		else if (score >= 6) {
--- linux-3.0-rc4.orig/drivers/gpu/drm/radeon/radeon_i2c.c	2011-05-30 20:45:08.000000000 +0200
+++ linux-3.0-rc4/drivers/gpu/drm/radeon/radeon_i2c.c	2011-06-22 12:00:35.000000000 +0200
@@ -34,20 +34,20 @@
  */
 bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 {
-	u8 out_buf[] = { 0x0, 0x0};
-	u8 buf[2];
+	u8 out = 0x0;
+	u8 buf[8];
 	int ret;
 	struct i2c_msg msgs[] = {
 		{
 			.addr = 0x50,
 			.flags = 0,
 			.len = 1,
-			.buf = out_buf,
+			.buf = &out,
 		},
 		{
 			.addr = 0x50,
 			.flags = I2C_M_RD,
-			.len = 1,
+			.len = 8,
 			.buf = buf,
 		}
 	};
@@ -57,7 +57,7 @@ bool radeon_ddc_probe(struct radeon_conn
 		radeon_router_select_ddc_port(radeon_connector);
 
 	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
-	if (ret == 2)
+	if (ret == 2 && drm_edid_header_valid(buf) >= 6)
 		return true;
 
 	return false;
--- linux-3.0-rc4.orig/include/drm/drm_crtc.h	2011-06-21 10:30:19.000000000 +0200
+++ linux-3.0-rc4/include/drm/drm_crtc.h	2011-06-22 12:02:24.000000000 +0200
@@ -802,6 +802,7 @@ extern struct drm_display_mode *drm_gtf_
 extern int drm_add_modes_noedid(struct drm_connector *connector,
 				int hdisplay, int vdisplay);
 
+extern int drm_edid_header_valid(const u8 *raw_edid);
 extern bool drm_edid_is_valid(struct edid *edid);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
 					   int hsize, int vsize, int fresh);


But if Alex believes that the case is rare enough that a board-specific
workaround is better, that's totally fine with me too. He is the master!

> Point 4:
> I've checked your comments and updated the patch. Hopefully, it fits now
> better to the linux kernel coding style. Thank you for the hints.
> 
> 
> A subsequent mail will contain the updated patch proposal. 

[1] I wonder why radeon_router_select_ddc_port() isn't part of
pre_xfer().

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-22  1:28   ` Alex Deucher
@ 2011-06-22 15:17     ` Thomas Reim
  2011-06-22 15:41       ` Alex Deucher
  2011-06-22 15:45       ` Alex Deucher
  0 siblings, 2 replies; 50+ messages in thread
From: Thomas Reim @ 2011-06-22 15:17 UTC (permalink / raw)
  To: Alex Deucher
  Cc: reimth, Dave Airlie, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel, dri-devel, linux-kernel,
	Thomas Reim

Dear Alex, 

> This is going to enable your quirk on every board with an HDMI port.
> If we need to add a quirk for your board, let's make it board
> specific.  It might be better to just disable edid polling for certain
> connectors on certain boards if they cause problems when no monitor is
> detected.
> 
> Alex

Initially, I made the quirk only for the Asus board, because I only have
this one to test. But the quirk applies of course to all boards that use
the RS690 type chipset.

I went through a couple of the many and various bugs that reported the
EDID error/dump flooding problem. Beside of RS690, also at least RS630,
RV770 and R350 are affected by this problem. In addition, I also found a
bug report on Intel 945 GM that seems to have the same root cause.

The majority of the bugs (ca. 80%) report a problem with the HDMI-A
connector. 15% have a problem with the DVI-I connector and 5% have a
problem with the LVDS connector. 

The proposed patch currently concentrates on the HDMI-A connector, only.

Based on Jean's proposal I updated the patch, so that
radeon_ddc_edid_probe() now replaces radeon_ddc_probe() for all HDMI-A
connectors. 

According to the VESA standards we could also do this for all connector
types in general. DDC is i2c plus EDID. Without the patch
radeon_ddc_probe() probes DDC by checking, if data at all can be
retrieved from i2c port 0x50 (where the EDID is provided). New
radeon_ddc_edid_probe() just checks in addition, if the EDID header and
version/revision information is available and according to the VESA
standards. 

Then and only then (for the HDMI-A connectors) we let drm_get_edid() and
drm_edid_block_valid() check the EDID checksum and probe the validity of
the EDID.

According to VESA's implementation guide this is the right approach:
Checking the exact match of the EDID header and that the revision number
is in valid range is mandatory. 

Based on Jean's comments, I believe that it makes sense to have EDID
polling enabled as there might be temporary communication problems
between graphics card and monitor. These should be logged. This also
applies for the buggy HDMI-A connectors, as soon as a monitor is
connected to them.

Hope this helps you.

Best regards

Thomas




^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-22 15:17     ` Thomas Reim
@ 2011-06-22 15:41       ` Alex Deucher
  2011-06-22 15:45       ` Alex Deucher
  1 sibling, 0 replies; 50+ messages in thread
From: Alex Deucher @ 2011-06-22 15:41 UTC (permalink / raw)
  To: Thomas Reim
  Cc: reimth, Dave Airlie, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel, dri-devel, linux-kernel,
	Thomas Reim

On Wed, Jun 22, 2011 at 11:17 AM, Thomas Reim <thomas.reim@nepomuc.de> wrote:
> Dear Alex,
>
>> This is going to enable your quirk on every board with an HDMI port.
>> If we need to add a quirk for your board, let's make it board
>> specific.  It might be better to just disable edid polling for certain
>> connectors on certain boards if they cause problems when no monitor is
>> detected.
>>
>> Alex
>
> Initially, I made the quirk only for the Asus board, because I only have
> this one to test. But the quirk applies of course to all boards that use
> the RS690 type chipset.
>
> I went through a couple of the many and various bugs that reported the
> EDID error/dump flooding problem. Beside of RS690, also at least RS630,
> RV770 and R350 are affected by this problem. In addition, I also found a
> bug report on Intel 945 GM that seems to have the same root cause.
>
> The majority of the bugs (ca. 80%) report a problem with the HDMI-A
> connector. 15% have a problem with the DVI-I connector and 5% have a
> problem with the LVDS connector.

Got links?  I'm not sure this is the same root cause.  A lot of hdmi
monitors have broken edid checksums and other edid problems due to
hdmi switches and receivers messing with the edid or just plain broken
edids (tv's are particularly bad).  These problems are reported the
same way via log spam, but are not the same issue.

In the particular case of your board (and probably a few other similar
rs690/rs740 boards), the oem provides an optional hdmi add-in card
that uses pcie lanes for display.  The oem usually has the same
connector table regardless of whether the add-in card is installed or
not so we have no way of knowing whether there is actually a connector
there or not.  Even when there is a add-in board present it sounds
like perhaps the i2c lines are not terminated properly when no monitor
is attached.

>
> The proposed patch currently concentrates on the HDMI-A connector, only.
>
> Based on Jean's proposal I updated the patch, so that
> radeon_ddc_edid_probe() now replaces radeon_ddc_probe() for all HDMI-A
> connectors.
>
> According to the VESA standards we could also do this for all connector
> types in general. DDC is i2c plus EDID. Without the patch
> radeon_ddc_probe() probes DDC by checking, if data at all can be
> retrieved from i2c port 0x50 (where the EDID is provided). New
> radeon_ddc_edid_probe() just checks in addition, if the EDID header and
> version/revision information is available and according to the VESA
> standards.
>
> Then and only then (for the HDMI-A connectors) we let drm_get_edid() and
> drm_edid_block_valid() check the EDID checksum and probe the validity of
> the EDID.
>
> According to VESA's implementation guide this is the right approach:
> Checking the exact match of the EDID header and that the revision number
> is in valid range is mandatory.
>

radeon_ddc_probe() is supposed to be lightweight.  It's used in the
detect() functions just to probe if something is attached or not.
There is a separate function to fetch the full edid and check if it's
valid.  For connectors without HPD (hot plug detect), the polling code
probes the edid every 10 seconds.

> Based on Jean's comments, I believe that it makes sense to have EDID
> polling enabled as there might be temporary communication problems
> between graphics card and monitor. These should be logged. This also
> applies for the buggy HDMI-A connectors, as soon as a monitor is
> connected to them.
>

edid polling was only added to deal with analog connectors that do not
support hotplug interrupts and digital connectors that don't have HPD.
 You can still manually probe the monitor, you just won't get an event
like you would with HPD or edid polling.

Alex

> Hope this helps you.
>
> Best regards
>
> Thomas
>
>
>
>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-22 15:17     ` Thomas Reim
  2011-06-22 15:41       ` Alex Deucher
@ 2011-06-22 15:45       ` Alex Deucher
  2011-06-23 21:57         ` Thomas Reim
  1 sibling, 1 reply; 50+ messages in thread
From: Alex Deucher @ 2011-06-22 15:45 UTC (permalink / raw)
  To: Thomas Reim
  Cc: reimth, Dave Airlie, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel, dri-devel, linux-kernel,
	Thomas Reim

On Wed, Jun 22, 2011 at 11:17 AM, Thomas Reim <thomas.reim@nepomuc.de> wrote:
> Dear Alex,
>
>> This is going to enable your quirk on every board with an HDMI port.
>> If we need to add a quirk for your board, let's make it board
>> specific.  It might be better to just disable edid polling for certain
>> connectors on certain boards if they cause problems when no monitor is
>> detected.
>>
>> Alex
>
> Initially, I made the quirk only for the Asus board, because I only have
> this one to test. But the quirk applies of course to all boards that use
> the RS690 type chipset.
>
> I went through a couple of the many and various bugs that reported the
> EDID error/dump flooding problem. Beside of RS690, also at least RS630,
> RV770 and R350 are affected by this problem. In addition, I also found a
> bug report on Intel 945 GM that seems to have the same root cause.
>
> The majority of the bugs (ca. 80%) report a problem with the HDMI-A
> connector. 15% have a problem with the DVI-I connector and 5% have a
> problem with the LVDS connector.
>
> The proposed patch currently concentrates on the HDMI-A connector, only.
>

I think it would be better to add a quirk flag and only do the
extended probe on specific boards where it is required.  E.g.,

if (radeon_connector->requires_extended_probe)
    radeon_ddc_probe_extended();
else
    radeon_ddc_probe();

Alex

> Based on Jean's proposal I updated the patch, so that
> radeon_ddc_edid_probe() now replaces radeon_ddc_probe() for all HDMI-A
> connectors.
>
> According to the VESA standards we could also do this for all connector
> types in general. DDC is i2c plus EDID. Without the patch
> radeon_ddc_probe() probes DDC by checking, if data at all can be
> retrieved from i2c port 0x50 (where the EDID is provided). New
> radeon_ddc_edid_probe() just checks in addition, if the EDID header and
> version/revision information is available and according to the VESA
> standards.
>
> Then and only then (for the HDMI-A connectors) we let drm_get_edid() and
> drm_edid_block_valid() check the EDID checksum and probe the validity of
> the EDID.
>
> According to VESA's implementation guide this is the right approach:
> Checking the exact match of the EDID header and that the revision number
> is in valid range is mandatory.
>
> Based on Jean's comments, I believe that it makes sense to have EDID
> polling enabled as there might be temporary communication problems
> between graphics card and monitor. These should be logged. This also
> applies for the buggy HDMI-A connectors, as soon as a monitor is
> connected to them.
>
> Hope this helps you.
>
> Best regards
>
> Thomas
>
>
>
>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-22 15:45       ` Alex Deucher
@ 2011-06-23 21:57         ` Thomas Reim
  0 siblings, 0 replies; 50+ messages in thread
From: Thomas Reim @ 2011-06-23 21:57 UTC (permalink / raw)
  To: Alex Deucher
  Cc: reimth, Dave Airlie, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel, dri-devel, linux-kernel,
	Thomas Reim

Dear Alex,

> I think it would be better to add a quirk flag and only do the
> extended probe on specific boards where it is required.  E.g.,
> 
> if (radeon_connector->requires_extended_probe)
>     radeon_ddc_probe_extended();
> else
>     radeon_ddc_probe();
> 
> Alex

Today, I updated the patch according to your proposal and the proposals
of Jean. I'll send it with my next mail.

Best regards

Thomas


^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-22  1:20   ` reimth
@ 2011-06-23 22:05     ` reimth
  -1 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-06-23 22:05 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel
  Cc: dri-devel, linux-kernel, Thomas Reim

From: Thomas Reim <rdratlos@yahoo.co.uk>

Some integrated ATI Radeon chipset implementations
(e. g. Asus M2A-VM HDMI, RS690) indicate the availability
of a DDC even when there's no monitor connected.
In this case, drm_get_edid() and drm_edid_block_valid()
periodically dump data and kernel errors into system
log files and onto terminals, which lead to an unacceptable
system behaviour. For this purpose function drm_edid_header_is_valid()
has been added to drm and function drm_edid_block_valid()
has been adapted to also use drm_edid_header_is_valid().

Tested since kernel 2.35 on Asus M2A-VM HDMI board

Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
---
 drivers/gpu/drm/drm_edid.c                 |   23 +++++++++++---
 drivers/gpu/drm/radeon/radeon_connectors.c |   29 ++++++++++++++++-
 drivers/gpu/drm/radeon/radeon_display.c    |   12 +++++++
 drivers/gpu/drm/radeon/radeon_i2c.c        |   45 ++++++++++++++++++++++++++-
 drivers/gpu/drm/radeon/radeon_mode.h       |    4 ++
 include/drm/drm_crtc.h                     |    1 +
 6 files changed, 105 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 0929219..1daaf81 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -128,6 +128,23 @@ static const u8 edid_header[] = {
 };
 
 /*
+ * Sanity check the header of the base EDID block.  Return 8 if the header
+ * is perfect, down to 0 if it's totally wrong.
+ */
+int drm_edid_header_is_valid(const u8 *raw_edid)
+{
+	int i, score = 0;
+
+	for (i = 0; i < sizeof(edid_header); i++)
+		if (raw_edid[i] == edid_header[i])
+			score++;
+
+	return score;
+}
+EXPORT_SYMBOL(drm_edid_header_is_valid);
+
+
+/*
  * Sanity check the EDID block (base or extension).  Return 0 if the block
  * doesn't check out, or 1 if it's valid.
  */
@@ -139,11 +156,7 @@ drm_edid_block_valid(u8 *raw_edid)
 	struct edid *edid = (struct edid *)raw_edid;
 
 	if (raw_edid[0] == 0x00) {
-		int score = 0;
-
-		for (i = 0; i < sizeof(edid_header); i++)
-			if (raw_edid[i] == edid_header[i])
-				score++;
+		int score = drm_edid_header_is_valid(raw_edid);
 
 		if (score == 8) ;
 		else if (score >= 6) {
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index cbfca3a..bcd2380 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -826,8 +826,12 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 	enum drm_connector_status ret = connector_status_disconnected;
 	bool dret = false;
 
-	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector);
+	if (radeon_connector->ddc_bus) {
+		if (radeon_connector->requires_extended_probe)
+			dret = radeon_ddc_probe_extended(radeon_connector);
+		else
+			dret = radeon_ddc_probe(radeon_connector);
+	}
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
@@ -1342,6 +1346,7 @@ radeon_add_atom_connector(struct drm_device *dev,
 	struct radeon_encoder *radeon_encoder;
 	uint32_t subpixel_order = SubPixelNone;
 	bool shared_ddc = false;
+	bool requires_extended_probe = false;
 	bool is_dp_bridge = false;
 
 	if (connector_type == DRM_MODE_CONNECTOR_Unknown)
@@ -1400,6 +1405,7 @@ radeon_add_atom_connector(struct drm_device *dev,
 	radeon_connector->shared_ddc = shared_ddc;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
+	radeon_connector->requires_extended_probe = requires_extended_probe;
 	radeon_connector->router = *router;
 	if (router->ddc_valid || router->cd_valid) {
 		radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
@@ -1688,6 +1694,23 @@ radeon_add_atom_connector(struct drm_device *dev,
 		}
 	}
 
+	/* RS690 HDMI DDC quirk:
+	 * Some integrated ATI Radeon chipset implementations (e. g.
+	 * Asus M2A-VM HDMI) indicate the availability of a DDC even
+	 * when there's no monitor connected to HDMI. For HDMI
+	 * connectors we check for the availability of EDID with
+	 * at least a correct EDID header and EDID version/revision
+	 * information. Only then, DDC is assumed to be available.
+	 * This prevents drm_get_edid() and drm_edid_block_valid() of
+	 * periodically dumping data and kernel errors into the logs
+	 * and onto the terminal, which would lead to an unacceptable
+	 * system behaviour */
+	if (connector_type == DRM_MODE_CONNECTOR_HDMIA &&
+		(rdev->family == CHIP_RS690 ||
+		 rdev->family == CHIP_RS740 ||
+		 rdev->family == CHIP_RV630))
+		requires_extended_probe = true;
+	radeon_connector->requires_extended_probe = requires_extended_probe;
 	if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
 		if (i2c_bus->valid)
 			connector->polled = DRM_CONNECTOR_POLL_CONNECT;
@@ -1716,6 +1739,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
 	struct drm_connector *connector;
 	struct radeon_connector *radeon_connector;
 	uint32_t subpixel_order = SubPixelNone;
+	bool requires_extended_probe = false;
 
 	if (connector_type == DRM_MODE_CONNECTOR_Unknown)
 		return;
@@ -1746,6 +1770,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
 	radeon_connector->devices = supported_device;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
+	radeon_connector->requires_extended_probe = requires_extended_probe;
 	switch (connector_type) {
 	case DRM_MODE_CONNECTOR_VGA:
 		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 292f73f..27e6840 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -715,6 +715,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
 	if (ret) {
 		radeon_setup_encoder_clones(dev);
 		radeon_print_display_setup(dev);
+		/* Is this really required here?
+		   Seems to just force drm to dump EDID errors
+		   to kernel logs */
 		list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
 			radeon_ddc_dump(drm_connector);
 	}
@@ -777,8 +780,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
 	if (!radeon_connector->ddc_bus)
 		return -1;
 	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
+	/* Log EDID retrieval status here. In particular with regard to
+	 * connectors with requires_extended_probe flag set, that will prevent
+	 * function radeon_dvi_detect() to fetch EDID on this connector,
+	 * as long as there is no valid EDID header found */
 	if (edid) {
+		DRM_INFO("Radeon display connector %s: Found valid EDID",
+				drm_get_connector_name(connector));
 		kfree(edid);
+	} else {
+		DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
+				drm_get_connector_name(connector));
 	}
 	return ret;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 781196d..7e93cf9 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -34,7 +34,7 @@
  */
 bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 {
-	u8 out_buf[] = { 0x0, 0x0};
+	u8 out = 0x0;
 	u8 buf[2];
 	int ret;
 	struct i2c_msg msgs[] = {
@@ -42,7 +42,7 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 			.addr = 0x50,
 			.flags = 0,
 			.len = 1,
-			.buf = out_buf,
+			.buf = &out,
 		},
 		{
 			.addr = 0x50,
@@ -63,6 +63,47 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 	return false;
 }
 
+/*
+ * Probe EDID header information via I2C:
+ * Try to fetch EDID information by calling i2c_transfer driver function and
+ * probe for a valid EDID header
+ */
+bool radeon_ddc_probe_extended(struct radeon_connector *radeon_connector)
+{
+	u8 out = 0x0;
+	u8 block[8];
+	int ret;
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= 0x50,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= &out,
+		}, {
+			.addr	= 0x50,
+			.flags	= I2C_M_RD,
+			.len	= 8,
+			.buf	= block,
+		}
+	};
+
+	/* on hw with routers, select right port */
+	if (radeon_connector->router.ddc_valid)
+		radeon_router_select_ddc_port(radeon_connector);
+
+	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
+	if (ret == 2)
+		if (drm_edid_header_is_valid(block) >= 6)
+			/* EDID header starts with:
+			 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00
+			 * Only the first 6 bytes must be valid as
+			 * drm_edid_block_valid() can fix the last 2 bytes
+			 */
+			return true;
+	/* Couldn't find an accessible EDID on this connector */
+	return false;
+}
+
 /* bit banging i2c */
 
 static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 6df4e3c..b834f27 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -438,6 +438,9 @@ struct radeon_connector {
 	struct radeon_i2c_chan *ddc_bus;
 	/* some systems have an hdmi and vga port with a shared ddc line */
 	bool shared_ddc;
+	/* for some Radeon chip families we apply an additional EDID header
+	   check as part of the DDC probe */
+	bool requires_extended_probe;
 	bool use_digital;
 	/* we need to mind the EDID between detect
 	   and get modes due to analog/digital/tvencoder */
@@ -515,6 +518,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
 extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
+extern bool radeon_ddc_probe_extended(struct radeon_connector *radeon_connector);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 33d12f8..0ec3687 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -802,6 +802,7 @@ extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev,
 extern int drm_add_modes_noedid(struct drm_connector *connector,
 				int hdisplay, int vdisplay);
 
+extern int drm_edid_header_is_valid(const u8 *raw_edid);
 extern bool drm_edid_is_valid(struct edid *edid);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
 					   int hsize, int vsize, int fresh);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
@ 2011-06-23 22:05     ` reimth
  0 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-06-23 22:05 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare, Tyson Whitehead
  Cc: dri-devel, linux-kernel, Thomas Reim

From: Thomas Reim <rdratlos@yahoo.co.uk>

Some integrated ATI Radeon chipset implementations
(e. g. Asus M2A-VM HDMI, RS690) indicate the availability
of a DDC even when there's no monitor connected.
In this case, drm_get_edid() and drm_edid_block_valid()
periodically dump data and kernel errors into system
log files and onto terminals, which lead to an unacceptable
system behaviour. For this purpose function drm_edid_header_is_valid()
has been added to drm and function drm_edid_block_valid()
has been adapted to also use drm_edid_header_is_valid().

Tested since kernel 2.35 on Asus M2A-VM HDMI board

Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
---
 drivers/gpu/drm/drm_edid.c                 |   23 +++++++++++---
 drivers/gpu/drm/radeon/radeon_connectors.c |   29 ++++++++++++++++-
 drivers/gpu/drm/radeon/radeon_display.c    |   12 +++++++
 drivers/gpu/drm/radeon/radeon_i2c.c        |   45 ++++++++++++++++++++++++++-
 drivers/gpu/drm/radeon/radeon_mode.h       |    4 ++
 include/drm/drm_crtc.h                     |    1 +
 6 files changed, 105 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 0929219..1daaf81 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -128,6 +128,23 @@ static const u8 edid_header[] = {
 };
 
 /*
+ * Sanity check the header of the base EDID block.  Return 8 if the header
+ * is perfect, down to 0 if it's totally wrong.
+ */
+int drm_edid_header_is_valid(const u8 *raw_edid)
+{
+	int i, score = 0;
+
+	for (i = 0; i < sizeof(edid_header); i++)
+		if (raw_edid[i] == edid_header[i])
+			score++;
+
+	return score;
+}
+EXPORT_SYMBOL(drm_edid_header_is_valid);
+
+
+/*
  * Sanity check the EDID block (base or extension).  Return 0 if the block
  * doesn't check out, or 1 if it's valid.
  */
@@ -139,11 +156,7 @@ drm_edid_block_valid(u8 *raw_edid)
 	struct edid *edid = (struct edid *)raw_edid;
 
 	if (raw_edid[0] == 0x00) {
-		int score = 0;
-
-		for (i = 0; i < sizeof(edid_header); i++)
-			if (raw_edid[i] == edid_header[i])
-				score++;
+		int score = drm_edid_header_is_valid(raw_edid);
 
 		if (score == 8) ;
 		else if (score >= 6) {
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index cbfca3a..bcd2380 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -826,8 +826,12 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 	enum drm_connector_status ret = connector_status_disconnected;
 	bool dret = false;
 
-	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector);
+	if (radeon_connector->ddc_bus) {
+		if (radeon_connector->requires_extended_probe)
+			dret = radeon_ddc_probe_extended(radeon_connector);
+		else
+			dret = radeon_ddc_probe(radeon_connector);
+	}
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
@@ -1342,6 +1346,7 @@ radeon_add_atom_connector(struct drm_device *dev,
 	struct radeon_encoder *radeon_encoder;
 	uint32_t subpixel_order = SubPixelNone;
 	bool shared_ddc = false;
+	bool requires_extended_probe = false;
 	bool is_dp_bridge = false;
 
 	if (connector_type == DRM_MODE_CONNECTOR_Unknown)
@@ -1400,6 +1405,7 @@ radeon_add_atom_connector(struct drm_device *dev,
 	radeon_connector->shared_ddc = shared_ddc;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
+	radeon_connector->requires_extended_probe = requires_extended_probe;
 	radeon_connector->router = *router;
 	if (router->ddc_valid || router->cd_valid) {
 		radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
@@ -1688,6 +1694,23 @@ radeon_add_atom_connector(struct drm_device *dev,
 		}
 	}
 
+	/* RS690 HDMI DDC quirk:
+	 * Some integrated ATI Radeon chipset implementations (e. g.
+	 * Asus M2A-VM HDMI) indicate the availability of a DDC even
+	 * when there's no monitor connected to HDMI. For HDMI
+	 * connectors we check for the availability of EDID with
+	 * at least a correct EDID header and EDID version/revision
+	 * information. Only then, DDC is assumed to be available.
+	 * This prevents drm_get_edid() and drm_edid_block_valid() of
+	 * periodically dumping data and kernel errors into the logs
+	 * and onto the terminal, which would lead to an unacceptable
+	 * system behaviour */
+	if (connector_type == DRM_MODE_CONNECTOR_HDMIA &&
+		(rdev->family == CHIP_RS690 ||
+		 rdev->family == CHIP_RS740 ||
+		 rdev->family == CHIP_RV630))
+		requires_extended_probe = true;
+	radeon_connector->requires_extended_probe = requires_extended_probe;
 	if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
 		if (i2c_bus->valid)
 			connector->polled = DRM_CONNECTOR_POLL_CONNECT;
@@ -1716,6 +1739,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
 	struct drm_connector *connector;
 	struct radeon_connector *radeon_connector;
 	uint32_t subpixel_order = SubPixelNone;
+	bool requires_extended_probe = false;
 
 	if (connector_type == DRM_MODE_CONNECTOR_Unknown)
 		return;
@@ -1746,6 +1770,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
 	radeon_connector->devices = supported_device;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
+	radeon_connector->requires_extended_probe = requires_extended_probe;
 	switch (connector_type) {
 	case DRM_MODE_CONNECTOR_VGA:
 		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 292f73f..27e6840 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -715,6 +715,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
 	if (ret) {
 		radeon_setup_encoder_clones(dev);
 		radeon_print_display_setup(dev);
+		/* Is this really required here?
+		   Seems to just force drm to dump EDID errors
+		   to kernel logs */
 		list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
 			radeon_ddc_dump(drm_connector);
 	}
@@ -777,8 +780,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
 	if (!radeon_connector->ddc_bus)
 		return -1;
 	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
+	/* Log EDID retrieval status here. In particular with regard to
+	 * connectors with requires_extended_probe flag set, that will prevent
+	 * function radeon_dvi_detect() to fetch EDID on this connector,
+	 * as long as there is no valid EDID header found */
 	if (edid) {
+		DRM_INFO("Radeon display connector %s: Found valid EDID",
+				drm_get_connector_name(connector));
 		kfree(edid);
+	} else {
+		DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
+				drm_get_connector_name(connector));
 	}
 	return ret;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 781196d..7e93cf9 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -34,7 +34,7 @@
  */
 bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 {
-	u8 out_buf[] = { 0x0, 0x0};
+	u8 out = 0x0;
 	u8 buf[2];
 	int ret;
 	struct i2c_msg msgs[] = {
@@ -42,7 +42,7 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 			.addr = 0x50,
 			.flags = 0,
 			.len = 1,
-			.buf = out_buf,
+			.buf = &out,
 		},
 		{
 			.addr = 0x50,
@@ -63,6 +63,47 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 	return false;
 }
 
+/*
+ * Probe EDID header information via I2C:
+ * Try to fetch EDID information by calling i2c_transfer driver function and
+ * probe for a valid EDID header
+ */
+bool radeon_ddc_probe_extended(struct radeon_connector *radeon_connector)
+{
+	u8 out = 0x0;
+	u8 block[8];
+	int ret;
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= 0x50,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= &out,
+		}, {
+			.addr	= 0x50,
+			.flags	= I2C_M_RD,
+			.len	= 8,
+			.buf	= block,
+		}
+	};
+
+	/* on hw with routers, select right port */
+	if (radeon_connector->router.ddc_valid)
+		radeon_router_select_ddc_port(radeon_connector);
+
+	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
+	if (ret == 2)
+		if (drm_edid_header_is_valid(block) >= 6)
+			/* EDID header starts with:
+			 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00
+			 * Only the first 6 bytes must be valid as
+			 * drm_edid_block_valid() can fix the last 2 bytes
+			 */
+			return true;
+	/* Couldn't find an accessible EDID on this connector */
+	return false;
+}
+
 /* bit banging i2c */
 
 static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 6df4e3c..b834f27 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -438,6 +438,9 @@ struct radeon_connector {
 	struct radeon_i2c_chan *ddc_bus;
 	/* some systems have an hdmi and vga port with a shared ddc line */
 	bool shared_ddc;
+	/* for some Radeon chip families we apply an additional EDID header
+	   check as part of the DDC probe */
+	bool requires_extended_probe;
 	bool use_digital;
 	/* we need to mind the EDID between detect
 	   and get modes due to analog/digital/tvencoder */
@@ -515,6 +518,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
 extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
+extern bool radeon_ddc_probe_extended(struct radeon_connector *radeon_connector);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 33d12f8..0ec3687 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -802,6 +802,7 @@ extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev,
 extern int drm_add_modes_noedid(struct drm_connector *connector,
 				int hdisplay, int vdisplay);
 
+extern int drm_edid_header_is_valid(const u8 *raw_edid);
 extern bool drm_edid_is_valid(struct edid *edid);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
 					   int hsize, int vsize, int fresh);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-23 22:05     ` reimth
  (?)
@ 2011-06-23 22:55     ` Alex Deucher
  2011-06-24  4:02       ` Thomas Reim
  -1 siblings, 1 reply; 50+ messages in thread
From: Alex Deucher @ 2011-06-23 22:55 UTC (permalink / raw)
  To: reimth
  Cc: Dave Airlie, Mario Kleiner, Jean Delvare, Tyson Whitehead,
	Jason Wessel, dri-devel, linux-kernel, Thomas Reim

On Thu, Jun 23, 2011 at 6:05 PM,  <reimth@googlemail.com> wrote:
> From: Thomas Reim <rdratlos@yahoo.co.uk>
>
> Some integrated ATI Radeon chipset implementations
> (e. g. Asus M2A-VM HDMI, RS690) indicate the availability
> of a DDC even when there's no monitor connected.
> In this case, drm_get_edid() and drm_edid_block_valid()
> periodically dump data and kernel errors into system
> log files and onto terminals, which lead to an unacceptable
> system behaviour. For this purpose function drm_edid_header_is_valid()
> has been added to drm and function drm_edid_block_valid()
> has been adapted to also use drm_edid_header_is_valid().
>
> Tested since kernel 2.35 on Asus M2A-VM HDMI board

See comments below.

Alex

>
> Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
> ---
>  drivers/gpu/drm/drm_edid.c                 |   23 +++++++++++---
>  drivers/gpu/drm/radeon/radeon_connectors.c |   29 ++++++++++++++++-
>  drivers/gpu/drm/radeon/radeon_display.c    |   12 +++++++
>  drivers/gpu/drm/radeon/radeon_i2c.c        |   45 ++++++++++++++++++++++++++-
>  drivers/gpu/drm/radeon/radeon_mode.h       |    4 ++
>  include/drm/drm_crtc.h                     |    1 +
>  6 files changed, 105 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 0929219..1daaf81 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -128,6 +128,23 @@ static const u8 edid_header[] = {
>  };
>
>  /*
> + * Sanity check the header of the base EDID block.  Return 8 if the header
> + * is perfect, down to 0 if it's totally wrong.
> + */
> +int drm_edid_header_is_valid(const u8 *raw_edid)
> +{
> +       int i, score = 0;
> +
> +       for (i = 0; i < sizeof(edid_header); i++)
> +               if (raw_edid[i] == edid_header[i])
> +                       score++;
> +
> +       return score;
> +}
> +EXPORT_SYMBOL(drm_edid_header_is_valid);
> +
> +
> +/*
>  * Sanity check the EDID block (base or extension).  Return 0 if the block
>  * doesn't check out, or 1 if it's valid.
>  */
> @@ -139,11 +156,7 @@ drm_edid_block_valid(u8 *raw_edid)
>        struct edid *edid = (struct edid *)raw_edid;
>
>        if (raw_edid[0] == 0x00) {
> -               int score = 0;
> -
> -               for (i = 0; i < sizeof(edid_header); i++)
> -                       if (raw_edid[i] == edid_header[i])
> -                               score++;
> +               int score = drm_edid_header_is_valid(raw_edid);
>
>                if (score == 8) ;
>                else if (score >= 6) {
> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> index cbfca3a..bcd2380 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -826,8 +826,12 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
>        enum drm_connector_status ret = connector_status_disconnected;
>        bool dret = false;
>
> -       if (radeon_connector->ddc_bus)
> -               dret = radeon_ddc_probe(radeon_connector);
> +       if (radeon_connector->ddc_bus) {
> +               if (radeon_connector->requires_extended_probe)
> +                       dret = radeon_ddc_probe_extended(radeon_connector);
> +               else
> +                       dret = radeon_ddc_probe(radeon_connector);
> +       }

Thinking about it more, it might be cleaner to just make the extended
mode a flag, e.g.,
dret = radeon_ddc_probe_extended(radeon_connector,
radeon_connector->requires_extended_probe);
and handle the extended fetch in the same probe function.


>        if (dret) {
>                if (radeon_connector->edid) {
>                        kfree(radeon_connector->edid);
> @@ -1342,6 +1346,7 @@ radeon_add_atom_connector(struct drm_device *dev,
>        struct radeon_encoder *radeon_encoder;
>        uint32_t subpixel_order = SubPixelNone;
>        bool shared_ddc = false;
> +       bool requires_extended_probe = false;
>        bool is_dp_bridge = false;
>
>        if (connector_type == DRM_MODE_CONNECTOR_Unknown)
> @@ -1400,6 +1405,7 @@ radeon_add_atom_connector(struct drm_device *dev,
>        radeon_connector->shared_ddc = shared_ddc;
>        radeon_connector->connector_object_id = connector_object_id;
>        radeon_connector->hpd = *hpd;
> +       radeon_connector->requires_extended_probe = requires_extended_probe;
>        radeon_connector->router = *router;
>        if (router->ddc_valid || router->cd_valid) {
>                radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
> @@ -1688,6 +1694,23 @@ radeon_add_atom_connector(struct drm_device *dev,
>                }
>        }
>
> +       /* RS690 HDMI DDC quirk:
> +        * Some integrated ATI Radeon chipset implementations (e. g.
> +        * Asus M2A-VM HDMI) indicate the availability of a DDC even
> +        * when there's no monitor connected to HDMI. For HDMI
> +        * connectors we check for the availability of EDID with
> +        * at least a correct EDID header and EDID version/revision
> +        * information. Only then, DDC is assumed to be available.
> +        * This prevents drm_get_edid() and drm_edid_block_valid() of
> +        * periodically dumping data and kernel errors into the logs
> +        * and onto the terminal, which would lead to an unacceptable
> +        * system behaviour */
> +       if (connector_type == DRM_MODE_CONNECTOR_HDMIA &&
> +               (rdev->family == CHIP_RS690 ||
> +                rdev->family == CHIP_RS740 ||
> +                rdev->family == CHIP_RV630))

This seems like an arbitrary selection of chips.  I haven't heard of
any problems related to ddc on rv630.  Also I think we should limit it
to the specific connector that is problematic rather than all hdmi
ports.  In the case of your board, it seems the hdmi port on the
add-in card is the only problematic one.  Lots of rs690 motherboards
have hdmi ports on the motherboard itself that work fine.  I'd prefer
to match based on the pci device and subsytem ids and the
supported_device and connector type.  See radeon_atom_apply_quirks()
in radeon_atombios.c for an example.  Something like:

radeon_connector->requires_extended_probe =
        radeon_connector_needs_extended_probe(rdev, supported_dev,
connector_type);

> +               requires_extended_probe = true;
> +       radeon_connector->requires_extended_probe = requires_extended_probe;
>        if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
>                if (i2c_bus->valid)
>                        connector->polled = DRM_CONNECTOR_POLL_CONNECT;
> @@ -1716,6 +1739,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
>        struct drm_connector *connector;
>        struct radeon_connector *radeon_connector;
>        uint32_t subpixel_order = SubPixelNone;
> +       bool requires_extended_probe = false;
>
>        if (connector_type == DRM_MODE_CONNECTOR_Unknown)
>                return;
> @@ -1746,6 +1770,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
>        radeon_connector->devices = supported_device;
>        radeon_connector->connector_object_id = connector_object_id;
>        radeon_connector->hpd = *hpd;
> +       radeon_connector->requires_extended_probe = requires_extended_probe;
>        switch (connector_type) {
>        case DRM_MODE_CONNECTOR_VGA:
>                drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index 292f73f..27e6840 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -715,6 +715,9 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
>        if (ret) {
>                radeon_setup_encoder_clones(dev);
>                radeon_print_display_setup(dev);
> +               /* Is this really required here?
> +                  Seems to just force drm to dump EDID errors
> +                  to kernel logs */
>                list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
>                        radeon_ddc_dump(drm_connector);

Both the code and the comment can probably be removed, but let's make
that a separate patch.

>        }
> @@ -777,8 +780,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
>        if (!radeon_connector->ddc_bus)
>                return -1;
>        edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
> +       /* Log EDID retrieval status here. In particular with regard to
> +        * connectors with requires_extended_probe flag set, that will prevent
> +        * function radeon_dvi_detect() to fetch EDID on this connector,
> +        * as long as there is no valid EDID header found */
>        if (edid) {
> +               DRM_INFO("Radeon display connector %s: Found valid EDID",
> +                               drm_get_connector_name(connector));
>                kfree(edid);
> +       } else {
> +               DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
> +                               drm_get_connector_name(connector));

These will just spam the log as well.

>        }
>        return ret;
>  }
> diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
> index 781196d..7e93cf9 100644
> --- a/drivers/gpu/drm/radeon/radeon_i2c.c
> +++ b/drivers/gpu/drm/radeon/radeon_i2c.c
> @@ -34,7 +34,7 @@
>  */
>  bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
>  {
> -       u8 out_buf[] = { 0x0, 0x0};
> +       u8 out = 0x0;
>        u8 buf[2];
>        int ret;
>        struct i2c_msg msgs[] = {
> @@ -42,7 +42,7 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
>                        .addr = 0x50,
>                        .flags = 0,
>                        .len = 1,
> -                       .buf = out_buf,
> +                       .buf = &out,
>                },
>                {
>                        .addr = 0x50,


The change above doesn't seem to be related.

> @@ -63,6 +63,47 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
>        return false;
>  }
>
> +/*
> + * Probe EDID header information via I2C:
> + * Try to fetch EDID information by calling i2c_transfer driver function and
> + * probe for a valid EDID header
> + */
> +bool radeon_ddc_probe_extended(struct radeon_connector *radeon_connector)
> +{
> +       u8 out = 0x0;
> +       u8 block[8];
> +       int ret;
> +       struct i2c_msg msgs[] = {
> +               {
> +                       .addr   = 0x50,
> +                       .flags  = 0,
> +                       .len    = 1,
> +                       .buf    = &out,
> +               }, {
> +                       .addr   = 0x50,
> +                       .flags  = I2C_M_RD,
> +                       .len    = 8,
> +                       .buf    = block,
> +               }
> +       };
> +
> +       /* on hw with routers, select right port */
> +       if (radeon_connector->router.ddc_valid)
> +               radeon_router_select_ddc_port(radeon_connector);
> +
> +       ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
> +       if (ret == 2)
> +               if (drm_edid_header_is_valid(block) >= 6)
> +                       /* EDID header starts with:
> +                        * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00
> +                        * Only the first 6 bytes must be valid as
> +                        * drm_edid_block_valid() can fix the last 2 bytes
> +                        */
> +                       return true;
> +       /* Couldn't find an accessible EDID on this connector */
> +       return false;
> +}
> +
>  /* bit banging i2c */
>
>  static void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index 6df4e3c..b834f27 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -438,6 +438,9 @@ struct radeon_connector {
>        struct radeon_i2c_chan *ddc_bus;
>        /* some systems have an hdmi and vga port with a shared ddc line */
>        bool shared_ddc;
> +       /* for some Radeon chip families we apply an additional EDID header
> +          check as part of the DDC probe */
> +       bool requires_extended_probe;
>        bool use_digital;
>        /* we need to mind the EDID between detect
>           and get modes due to analog/digital/tvencoder */
> @@ -515,6 +518,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
>  extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
>  extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
>  extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
> +extern bool radeon_ddc_probe_extended(struct radeon_connector *radeon_connector);
>  extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
>
>  extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 33d12f8..0ec3687 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -802,6 +802,7 @@ extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev,
>  extern int drm_add_modes_noedid(struct drm_connector *connector,
>                                int hdisplay, int vdisplay);
>
> +extern int drm_edid_header_is_valid(const u8 *raw_edid);
>  extern bool drm_edid_is_valid(struct edid *edid);
>  struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
>                                           int hsize, int vsize, int fresh);
> --
> 1.7.1
>
>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-23 22:55     ` Alex Deucher
@ 2011-06-24  4:02       ` Thomas Reim
  2011-06-24 13:36         ` Alex Deucher
  0 siblings, 1 reply; 50+ messages in thread
From: Thomas Reim @ 2011-06-24  4:02 UTC (permalink / raw)
  To: Alex Deucher
  Cc: reimth, Dave Airlie, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel, dri-devel, linux-kernel,
	Thomas Reim

Hi Alex,

thank you for your feedback.

> Thinking about it more, it might be cleaner to just make the extended
> mode a flag, e.g.,
> dret = radeon_ddc_probe_extended(radeon_connector,
> radeon_connector->requires_extended_probe);
> and handle the extended fetch in the same probe function.
> 

OK. That makes also sense. I will adapt again the patch. 

> > +       /* RS690 HDMI DDC quirk:
> > +        * Some integrated ATI Radeon chipset implementations (e. g.
> > +        * Asus M2A-VM HDMI) indicate the availability of a DDC even
> > +        * when there's no monitor connected to HDMI. For HDMI
> > +        * connectors we check for the availability of EDID with
> > +        * at least a correct EDID header and EDID version/revision
> > +        * information. Only then, DDC is assumed to be available.
> > +        * This prevents drm_get_edid() and drm_edid_block_valid() of
> > +        * periodically dumping data and kernel errors into the logs
> > +        * and onto the terminal, which would lead to an unacceptable
> > +        * system behaviour */
> > +       if (connector_type == DRM_MODE_CONNECTOR_HDMIA &&
> > +               (rdev->family == CHIP_RS690 ||
> > +                rdev->family == CHIP_RS740 ||
> > +                rdev->family == CHIP_RV630))
> This seems like an arbitrary selection of chips.  I haven't heard of
> any problems related to ddc on rv630.  Also I think we should limit it
> to the specific connector that is problematic rather than all hdmi
> ports.  In the case of your board, it seems the hdmi port on the
> add-in card is the only problematic one.  Lots of rs690 motherboards
> have hdmi ports on the motherboard itself that work fine.  I'd prefer
> to match based on the pci device and subsytem ids and the
> supported_device and connector type.  See radeon_atom_apply_quirks()
> in radeon_atombios.c for an example.  Something like:
> 
> radeon_connector->requires_extended_probe =
>         radeon_connector_needs_extended_probe(rdev, supported_dev,
> connector_type);

I've added RS740 because linux uses the same firmware and this chip was
also part of the other patch you mentioned in your first e-mail. RV630
was added because I checked freedesktop bug 31943. The problem described
there is different from the one here, but I saw logs, when no monitor
was connected, and for this situation the patch would help. 

With regard to moving away from connector type and chip family to pci
devices I'm not really sure. I remember complaints from people a year
ago, that used the RS690 on a laptop and had the same problem. I just
can't find the related messages. Don't you believe that this could be to
focused? Especially, if we compare patch
http://git.kernel.org/?p=linux/kernel/git/airlied/drm-2.6.git;a=commitdiff;h=4a9a8b71e12d41abb71c4e741bff524f016cfef4?

I felt rather safe with the above approach, as nothing will go wrong, if
we check the HDMIA type connectors also RS690 of another manufacturers.
We just check for a valid first six bytes set of the EDID header now.

> > @@ -777,8 +780,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
> >        if (!radeon_connector->ddc_bus)
> >                return -1;
> >        edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
> > +       /* Log EDID retrieval status here. In particular with regard to
> > +        * connectors with requires_extended_probe flag set, that will prevent
> > +        * function radeon_dvi_detect() to fetch EDID on this connector,
> > +        * as long as there is no valid EDID header found */
> >        if (edid) {
> > +               DRM_INFO("Radeon display connector %s: Found valid EDID",
> > +                               drm_get_connector_name(connector));
> >                kfree(edid);
> > +       } else {
> > +               DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
> > +                               drm_get_connector_name(connector));
> 
> These will just spam the log as well.

Here's the log:
kernel: [   14.912386] [drm] Radeon Display Connectors
kernel: [   14.912389] [drm] Connector 0:
kernel: [   14.912391] [drm]   VGA
kernel: [   14.912394] [drm]   DDC: 0x7e50 0x7e40 0x7e54 0x7e44 0x7e58
0x7e48 0x7e5c 0x7e4c
kernel: [   14.912397] [drm]   Encoders:
kernel: [   14.912398] [drm]     CRT1: INTERNAL_KLDSCP_DAC1
kernel: [   14.912401] [drm] Connector 1:
kernel: [   14.912402] [drm]   S-video
kernel: [   14.912404] [drm]   Encoders:
kernel: [   14.912405] [drm]     TV1: INTERNAL_KLDSCP_DAC1
kernel: [   14.912407] [drm] Connector 2:
kernel: [   14.912409] [drm]   HDMI-A
kernel: [   14.912410] [drm]   HPD2
kernel: [   14.912413] [drm]   DDC: 0x7e40 0x7e60 0x7e44 0x7e64 0x7e48
0x7e68 0x7e4c 0x7e6c
kernel: [   14.912415] [drm]   Encoders:
kernel: [   14.912417] [drm]     DFP2: INTERNAL_DDI
kernel: [   14.912419] [drm] Connector 3:
kernel: [   14.912421] [drm]   DVI-D
kernel: [   14.912423] [drm]   DDC: 0x7e40 0x7e50 0x7e44 0x7e54 0x7e48
0x7e58 0x7e4c 0x7e5c
kernel: [   14.912425] [drm]   Encoders:
kernel: [   14.912427] [drm]     DFP3: INTERNAL_LVTM1
kernel: [   15.071566] HDA Intel 0000:00:14.2: PCI INT A -> GSI 16
(level, low) -> IRQ 16
kernel: [   15.071645] HDA Intel 0000:00:14.2: irq 42 for MSI/MSI-X
kernel: [   15.072678] [drm] Radeon display connector VGA-1: No display
connected or invalid EDID
kernel: [   15.470734] Raw EDID:
kernel: [   15.470745] <3>00 00 00 00 00 00 00 00 00 00 00 07 00 00 00
00  ................
kernel: [   15.470748] <3>00 00 00 00 00 00 00 00 00 00 07 00 00 00 00
00  ................
kernel: [   15.470751] <3>00 00 00 00 00 00 00 00 00 00 7f 00 00 00 00
00  ................
kernel: [   15.470754] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
kernel: [   15.470757] <3>00 00 00 00 1f 00 00 00 00 00 00 00 00 00 00
00  ................
kernel: [   15.470760] <3>00 00 00 00 00 07 00 00 00 00 00 7f 00 00 00
00  ................
kernel: [   15.470762] <3>00 00 00 00 00 00 07 00 00 00 00 00 00 00 00
00  ................
kernel: [   15.470765] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01  ................
kernel: [   15.470767] 
kernel: [   15.779568] Raw EDID:
kernel: [   15.779578] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
kernel: [   15.779581] <3>00 00 00 00 00 7f 00 00 00 00 03 00 00 00 00
00  ................
kernel: [   15.779584] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
kernel: [   15.779587] <3>00 00 00 00 ff 00 00 00 00 00 00 00 00 00 00
00  ................
kernel: [   15.779590] <3>00 00 00 00 00 00 00 00 ff 00 00 00 00 00 00
00  ................
kernel: [   15.779593] <3>00 00 00 00 00 00 00 00 00 01 00 00 00 00 00
00  ................
kernel: [   15.779596] <3>00 00 00 7f 00 00 00 00 00 03 07 00 00 00 00
00  ................
kernel: [   15.779598] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
kernel: [   15.779600] 
kernel: [   16.151817] Raw EDID:
kernel: [   16.151827] <3>00 00 00 00 00 00 1f 00 00 00 00 00 00 00 00
00  ................
kernel: [   16.151830] <3>00 00 00 00 00 00 00 00 00 01 00 00 00 00 00
00  ................
kernel: [   16.151833] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
kernel: [   16.151836] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
kernel: [   16.151839] <3>00 00 1f 00 00 00 00 00 00 00 00 00 00 00 0f
00  ................
kernel: [   16.151842] <3>01 00 00 00 00 00 00 00 01 00 00 00 00 07 00
ff  ................
kernel: [   16.151844] <3>00 00 00 00 00 00 ff 00 00 00 00 00 00 00 7f
00  ................
kernel: [   16.151847] <3>00 0f 00 00 00 00 00 00 00 3f 00 00 00 00 00
00  .........?......
kernel: [   16.151849] 
kernel: [   16.444209] Raw EDID:
kernel: [   16.444220] <3>00 07 00 00 00 00 00 00 ff 00 00 00 00 ff 00
00  ................
kernel: [   16.444223] <3>00 00 3f 00 00 00 00 00 00 00 00 00 00 ff 00
00  ..?.............
kernel: [   16.444226] <3>00 00 00 00 00 00 00 00 00 07 00 00 00 01 0f
00  ................
kernel: [   16.444229] <3>00 07 00 00 00 00 00 00 00 00 01 07 00 00 00
00  ................
kernel: [   16.444231] <3>00 00 00 00 00 00 00 00 7f 00 00 00 00 1f 00
00  ................
kernel: [   16.444234] <3>00 00 03 00 00 00 00 3f 00 03 00 00 00 00 00
00  .......?........
kernel: [   16.444237] <3>7f 00 00 1f 00 00 00 00 00 00 00 00 0f 07 00
00  ................
kernel: [   16.444240] <3>00 00 00 00 00 00 00 00 00 00 03 00 00 00 00
00  ................
kernel: [   16.444242] 
kernel: [   16.444248] radeon 0000:01:05.0: HDMI-A-1: EDID block 0
invalid.
kernel: [   16.444252] [drm] Radeon display connector HDMI-A-1: No
display connected or invalid EDID
kernel: [   16.762734] [drm] Radeon display connector DVI-D-1: Found
valid EDID

Just one info entry per connector will be added during connector setup.
The EDID dump was already there and comes from the DDC probing during
connector setup. After that, there are no more entries in the log with
regard to the buggy HDMI connector. From a user point of view I would
prefer to have the two log entries:
radeon 0000:01:05.0: HDMI-A-1: EDID block 0 invalid.
[drm] Radeon display connector HDMI-A-1: No display connected or invalid
EDID.
One from the probing, which is a little bit cryptic, and the explaining
one which prelude the silence for this connector.

> > diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
> > index 781196d..7e93cf9 100644
> > --- a/drivers/gpu/drm/radeon/radeon_i2c.c
> > +++ b/drivers/gpu/drm/radeon/radeon_i2c.c
> > @@ -34,7 +34,7 @@
> >  */
> >  bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
> >  {
> > -       u8 out_buf[] = { 0x0, 0x0};
> > +       u8 out = 0x0;
> >        u8 buf[2];
> >        int ret;
> >        struct i2c_msg msgs[] = {
> > @@ -42,7 +42,7 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
> >                        .addr = 0x50,
> >                        .flags = 0,
> >                        .len = 1,
> > -                       .buf = out_buf,
> > +                       .buf = &out,
> >                },
> >                {
> >                        .addr = 0x50,
> 
> 
> The change above doesn't seem to be related.

This was a comment from Jean who complained about the ineffective usage
of the i2c bus. But I can also restore the old code. What's your
preference?

Best regards

Thomas


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-24  4:02       ` Thomas Reim
@ 2011-06-24 13:36         ` Alex Deucher
  2011-06-27 12:14             ` Jean Delvare
  2011-07-06  9:35           ` Thomas Reim
  0 siblings, 2 replies; 50+ messages in thread
From: Alex Deucher @ 2011-06-24 13:36 UTC (permalink / raw)
  To: Thomas Reim
  Cc: reimth, Dave Airlie, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel, dri-devel, linux-kernel,
	Thomas Reim

On Fri, Jun 24, 2011 at 12:02 AM, Thomas Reim <thomas.reim@nepomuc.de> wrote:
> Hi Alex,
>
> thank you for your feedback.
>
>> Thinking about it more, it might be cleaner to just make the extended
>> mode a flag, e.g.,
>> dret = radeon_ddc_probe_extended(radeon_connector,
>> radeon_connector->requires_extended_probe);
>> and handle the extended fetch in the same probe function.
>>
>
> OK. That makes also sense. I will adapt again the patch.
>
>> > +       /* RS690 HDMI DDC quirk:
>> > +        * Some integrated ATI Radeon chipset implementations (e. g.
>> > +        * Asus M2A-VM HDMI) indicate the availability of a DDC even
>> > +        * when there's no monitor connected to HDMI. For HDMI
>> > +        * connectors we check for the availability of EDID with
>> > +        * at least a correct EDID header and EDID version/revision
>> > +        * information. Only then, DDC is assumed to be available.
>> > +        * This prevents drm_get_edid() and drm_edid_block_valid() of
>> > +        * periodically dumping data and kernel errors into the logs
>> > +        * and onto the terminal, which would lead to an unacceptable
>> > +        * system behaviour */
>> > +       if (connector_type == DRM_MODE_CONNECTOR_HDMIA &&
>> > +               (rdev->family == CHIP_RS690 ||
>> > +                rdev->family == CHIP_RS740 ||
>> > +                rdev->family == CHIP_RV630))
>> This seems like an arbitrary selection of chips.  I haven't heard of
>> any problems related to ddc on rv630.  Also I think we should limit it
>> to the specific connector that is problematic rather than all hdmi
>> ports.  In the case of your board, it seems the hdmi port on the
>> add-in card is the only problematic one.  Lots of rs690 motherboards
>> have hdmi ports on the motherboard itself that work fine.  I'd prefer
>> to match based on the pci device and subsytem ids and the
>> supported_device and connector type.  See radeon_atom_apply_quirks()
>> in radeon_atombios.c for an example.  Something like:
>>
>> radeon_connector->requires_extended_probe =
>>         radeon_connector_needs_extended_probe(rdev, supported_dev,
>> connector_type);
>
> I've added RS740 because linux uses the same firmware and this chip was
> also part of the other patch you mentioned in your first e-mail. RV630
> was added because I checked freedesktop bug 31943. The problem described
> there is different from the one here, but I saw logs, when no monitor
> was connected, and for this situation the patch would help.

I'd rather add quirks on a case by case bases rather than speculating
on mailing list reports.

>
> With regard to moving away from connector type and chip family to pci
> devices I'm not really sure. I remember complaints from people a year
> ago, that used the RS690 on a laptop and had the same problem. I just
> can't find the related messages. Don't you believe that this could be to
> focused? Especially, if we compare patch
> http://git.kernel.org/?p=linux/kernel/git/airlied/drm-2.6.git;a=commitdiff;h=4a9a8b71e12d41abb71c4e741bff524f016cfef4?
>

We should probably revert or rework that patch when we apply yours
otherwise we may end up removing i2c buses unnecessarily in some
cases.  I think this is a better approach.

> I felt rather safe with the above approach, as nothing will go wrong, if
> we check the HDMIA type connectors also RS690 of another manufacturers.
> We just check for a valid first six bytes set of the EDID header now.

As I said above, lets just apply this to the specific board and
connector that is problematic.  I seems to only affect the hdmi port
on the add-in cards, so there's no need to penalize all hdmi ports.
If we get enough quirks down the road, we can make it a general rule.

>
>> > @@ -777,8 +780,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
>> >        if (!radeon_connector->ddc_bus)
>> >                return -1;
>> >        edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
>> > +       /* Log EDID retrieval status here. In particular with regard to
>> > +        * connectors with requires_extended_probe flag set, that will prevent
>> > +        * function radeon_dvi_detect() to fetch EDID on this connector,
>> > +        * as long as there is no valid EDID header found */
>> >        if (edid) {
>> > +               DRM_INFO("Radeon display connector %s: Found valid EDID",
>> > +                               drm_get_connector_name(connector));
>> >                kfree(edid);
>> > +       } else {
>> > +               DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
>> > +                               drm_get_connector_name(connector));
>>
>> These will just spam the log as well.
>
> Here's the log:
> kernel: [   14.912386] [drm] Radeon Display Connectors
> kernel: [   14.912389] [drm] Connector 0:
> kernel: [   14.912391] [drm]   VGA
> kernel: [   14.912394] [drm]   DDC: 0x7e50 0x7e40 0x7e54 0x7e44 0x7e58
> 0x7e48 0x7e5c 0x7e4c
> kernel: [   14.912397] [drm]   Encoders:
> kernel: [   14.912398] [drm]     CRT1: INTERNAL_KLDSCP_DAC1
> kernel: [   14.912401] [drm] Connector 1:
> kernel: [   14.912402] [drm]   S-video
> kernel: [   14.912404] [drm]   Encoders:
> kernel: [   14.912405] [drm]     TV1: INTERNAL_KLDSCP_DAC1
> kernel: [   14.912407] [drm] Connector 2:
> kernel: [   14.912409] [drm]   HDMI-A
> kernel: [   14.912410] [drm]   HPD2
> kernel: [   14.912413] [drm]   DDC: 0x7e40 0x7e60 0x7e44 0x7e64 0x7e48
> 0x7e68 0x7e4c 0x7e6c
> kernel: [   14.912415] [drm]   Encoders:
> kernel: [   14.912417] [drm]     DFP2: INTERNAL_DDI
> kernel: [   14.912419] [drm] Connector 3:
> kernel: [   14.912421] [drm]   DVI-D
> kernel: [   14.912423] [drm]   DDC: 0x7e40 0x7e50 0x7e44 0x7e54 0x7e48
> 0x7e58 0x7e4c 0x7e5c
> kernel: [   14.912425] [drm]   Encoders:
> kernel: [   14.912427] [drm]     DFP3: INTERNAL_LVTM1
> kernel: [   15.071566] HDA Intel 0000:00:14.2: PCI INT A -> GSI 16
> (level, low) -> IRQ 16
> kernel: [   15.071645] HDA Intel 0000:00:14.2: irq 42 for MSI/MSI-X
> kernel: [   15.072678] [drm] Radeon display connector VGA-1: No display
> connected or invalid EDID
> kernel: [   15.470734] Raw EDID:
> kernel: [   15.470745] <3>00 00 00 00 00 00 00 00 00 00 00 07 00 00 00
> 00  ................
> kernel: [   15.470748] <3>00 00 00 00 00 00 00 00 00 00 07 00 00 00 00
> 00  ................
> kernel: [   15.470751] <3>00 00 00 00 00 00 00 00 00 00 7f 00 00 00 00
> 00  ................
> kernel: [   15.470754] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00  ................
> kernel: [   15.470757] <3>00 00 00 00 1f 00 00 00 00 00 00 00 00 00 00
> 00  ................
> kernel: [   15.470760] <3>00 00 00 00 00 07 00 00 00 00 00 7f 00 00 00
> 00  ................
> kernel: [   15.470762] <3>00 00 00 00 00 00 07 00 00 00 00 00 00 00 00
> 00  ................
> kernel: [   15.470765] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 01  ................
> kernel: [   15.470767]
> kernel: [   15.779568] Raw EDID:
> kernel: [   15.779578] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00  ................
> kernel: [   15.779581] <3>00 00 00 00 00 7f 00 00 00 00 03 00 00 00 00
> 00  ................
> kernel: [   15.779584] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00  ................
> kernel: [   15.779587] <3>00 00 00 00 ff 00 00 00 00 00 00 00 00 00 00
> 00  ................
> kernel: [   15.779590] <3>00 00 00 00 00 00 00 00 ff 00 00 00 00 00 00
> 00  ................
> kernel: [   15.779593] <3>00 00 00 00 00 00 00 00 00 01 00 00 00 00 00
> 00  ................
> kernel: [   15.779596] <3>00 00 00 7f 00 00 00 00 00 03 07 00 00 00 00
> 00  ................
> kernel: [   15.779598] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00  ................
> kernel: [   15.779600]
> kernel: [   16.151817] Raw EDID:
> kernel: [   16.151827] <3>00 00 00 00 00 00 1f 00 00 00 00 00 00 00 00
> 00  ................
> kernel: [   16.151830] <3>00 00 00 00 00 00 00 00 00 01 00 00 00 00 00
> 00  ................
> kernel: [   16.151833] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00  ................
> kernel: [   16.151836] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> 00  ................
> kernel: [   16.151839] <3>00 00 1f 00 00 00 00 00 00 00 00 00 00 00 0f
> 00  ................
> kernel: [   16.151842] <3>01 00 00 00 00 00 00 00 01 00 00 00 00 07 00
> ff  ................
> kernel: [   16.151844] <3>00 00 00 00 00 00 ff 00 00 00 00 00 00 00 7f
> 00  ................
> kernel: [   16.151847] <3>00 0f 00 00 00 00 00 00 00 3f 00 00 00 00 00
> 00  .........?......
> kernel: [   16.151849]
> kernel: [   16.444209] Raw EDID:
> kernel: [   16.444220] <3>00 07 00 00 00 00 00 00 ff 00 00 00 00 ff 00
> 00  ................
> kernel: [   16.444223] <3>00 00 3f 00 00 00 00 00 00 00 00 00 00 ff 00
> 00  ..?.............
> kernel: [   16.444226] <3>00 00 00 00 00 00 00 00 00 07 00 00 00 01 0f
> 00  ................
> kernel: [   16.444229] <3>00 07 00 00 00 00 00 00 00 00 01 07 00 00 00
> 00  ................
> kernel: [   16.444231] <3>00 00 00 00 00 00 00 00 7f 00 00 00 00 1f 00
> 00  ................
> kernel: [   16.444234] <3>00 00 03 00 00 00 00 3f 00 03 00 00 00 00 00
> 00  .......?........
> kernel: [   16.444237] <3>7f 00 00 1f 00 00 00 00 00 00 00 00 0f 07 00
> 00  ................
> kernel: [   16.444240] <3>00 00 00 00 00 00 00 00 00 00 03 00 00 00 00
> 00  ................
> kernel: [   16.444242]
> kernel: [   16.444248] radeon 0000:01:05.0: HDMI-A-1: EDID block 0
> invalid.
> kernel: [   16.444252] [drm] Radeon display connector HDMI-A-1: No
> display connected or invalid EDID
> kernel: [   16.762734] [drm] Radeon display connector DVI-D-1: Found
> valid EDID
>
> Just one info entry per connector will be added during connector setup.
> The EDID dump was already there and comes from the DDC probing during
> connector setup. After that, there are no more entries in the log with
> regard to the buggy HDMI connector. From a user point of view I would
> prefer to have the two log entries:
> radeon 0000:01:05.0: HDMI-A-1: EDID block 0 invalid.
> [drm] Radeon display connector HDMI-A-1: No display connected or invalid
> EDID.
> One from the probing, which is a little bit cryptic, and the explaining
> one which prelude the silence for this connector.

ok, that makes sense.

>
>> > diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
>> > index 781196d..7e93cf9 100644
>> > --- a/drivers/gpu/drm/radeon/radeon_i2c.c
>> > +++ b/drivers/gpu/drm/radeon/radeon_i2c.c
>> > @@ -34,7 +34,7 @@
>> >  */
>> >  bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
>> >  {
>> > -       u8 out_buf[] = { 0x0, 0x0};
>> > +       u8 out = 0x0;
>> >        u8 buf[2];
>> >        int ret;
>> >        struct i2c_msg msgs[] = {
>> > @@ -42,7 +42,7 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
>> >                        .addr = 0x50,
>> >                        .flags = 0,
>> >                        .len = 1,
>> > -                       .buf = out_buf,
>> > +                       .buf = &out,
>> >                },
>> >                {
>> >                        .addr = 0x50,
>>
>>
>> The change above doesn't seem to be related.
>
> This was a comment from Jean who complained about the ineffective usage
> of the i2c bus. But I can also restore the old code. What's your
> preference?

Ah, I missed that.  Let's make that a separate patch, or fix it when
you add support for the extended edid check.

Thanks for fixing this up.

Alex

>
> Best regards
>
> Thomas
>
>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-24 13:36         ` Alex Deucher
@ 2011-06-27 12:14             ` Jean Delvare
  2011-07-06  9:35           ` Thomas Reim
  1 sibling, 0 replies; 50+ messages in thread
From: Jean Delvare @ 2011-06-27 12:14 UTC (permalink / raw)
  To: Alex Deucher
  Cc: Thomas Reim, reimth, Dave Airlie, Mario Kleiner, Tyson Whitehead,
	Jason Wessel, dri-devel, linux-kernel, Thomas Reim

On Fri, 24 Jun 2011 09:36:56 -0400, Alex Deucher wrote:
> On Fri, Jun 24, 2011 at 12:02 AM, Thomas Reim <thomas.reim@nepomuc.de> wrote:
> >> > diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
> >> > index 781196d..7e93cf9 100644
> >> > --- a/drivers/gpu/drm/radeon/radeon_i2c.c
> >> > +++ b/drivers/gpu/drm/radeon/radeon_i2c.c
> >> > @@ -34,7 +34,7 @@
> >> >  */
> >> >  bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
> >> >  {
> >> > -       u8 out_buf[] = { 0x0, 0x0};
> >> > +       u8 out = 0x0;
> >> >        u8 buf[2];
> >> >        int ret;
> >> >        struct i2c_msg msgs[] = {
> >> > @@ -42,7 +42,7 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
> >> >                        .addr = 0x50,
> >> >                        .flags = 0,
> >> >                        .len = 1,
> >> > -                       .buf = out_buf,
> >> > +                       .buf = &out,
> >> >                },
> >> >                {
> >> >                        .addr = 0x50,
> >>
> >>
> >> The change above doesn't seem to be related.
> >
> > This was a comment from Jean who complained about the ineffective usage
> > of the i2c bus. But I can also restore the old code. What's your
> > preference?
> 
> Ah, I missed that.  Let's make that a separate patch, or fix it when
> you add support for the extended edid check.
> 
> Thanks for fixing this up.

I'll send a patch for that one, as I found it. It is indeed unrelated
to the problem, I mentioned it only to avoid the same mistake in a
newly added function.

It's a very minor cleanup / optimization, BTW.

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
@ 2011-06-27 12:14             ` Jean Delvare
  0 siblings, 0 replies; 50+ messages in thread
From: Jean Delvare @ 2011-06-27 12:14 UTC (permalink / raw)
  To: Alex Deucher
  Cc: Whitehead, Thomas Reim, linux-kernel, dri-devel, reimth,
	Thomas Reim, Mario Kleiner, Jason Wessel, Dave Airlie, Tyson

On Fri, 24 Jun 2011 09:36:56 -0400, Alex Deucher wrote:
> On Fri, Jun 24, 2011 at 12:02 AM, Thomas Reim <thomas.reim@nepomuc.de> wrote:
> >> > diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
> >> > index 781196d..7e93cf9 100644
> >> > --- a/drivers/gpu/drm/radeon/radeon_i2c.c
> >> > +++ b/drivers/gpu/drm/radeon/radeon_i2c.c
> >> > @@ -34,7 +34,7 @@
> >> >  */
> >> >  bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
> >> >  {
> >> > -       u8 out_buf[] = { 0x0, 0x0};
> >> > +       u8 out = 0x0;
> >> >        u8 buf[2];
> >> >        int ret;
> >> >        struct i2c_msg msgs[] = {
> >> > @@ -42,7 +42,7 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
> >> >                        .addr = 0x50,
> >> >                        .flags = 0,
> >> >                        .len = 1,
> >> > -                       .buf = out_buf,
> >> > +                       .buf = &out,
> >> >                },
> >> >                {
> >> >                        .addr = 0x50,
> >>
> >>
> >> The change above doesn't seem to be related.
> >
> > This was a comment from Jean who complained about the ineffective usage
> > of the i2c bus. But I can also restore the old code. What's your
> > preference?
> 
> Ah, I missed that.  Let's make that a separate patch, or fix it when
> you add support for the extended edid check.
> 
> Thanks for fixing this up.

I'll send a patch for that one, as I found it. It is indeed unrelated
to the problem, I mentioned it only to avoid the same mistake in a
newly added function.

It's a very minor cleanup / optimization, BTW.

-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-24 13:36         ` Alex Deucher
  2011-06-27 12:14             ` Jean Delvare
@ 2011-07-06  9:35           ` Thomas Reim
  1 sibling, 0 replies; 50+ messages in thread
From: Thomas Reim @ 2011-07-06  9:35 UTC (permalink / raw)
  To: Alex Deucher
  Cc: Dave Airlie, Mario Kleiner, Jean Delvare, Tyson Whitehead,
	Jason Wessel, dri-devel, linux-kernel, reimth

Dear Alex,

sorry for the long delay. I have updated the patch according to the
comments in your last e-mail (see below).

I've added function radeon_connector_needs_extended_probe() and flag
radeon_connector->requires_extended_probe that provide the means to
force on a board,connector basis to check for a valid EDID header during
DDC probe.

I've adapted function radeon_ddc_probe() to perform an additional EDID
header check if required by the connector.

Finally, I've adapted function radeon_device_init() to also log
subsystem vendor and device information, if available. This allows to
add further quirks based on the dmesg output of drm/radeon.

> > I've added RS740 because linux uses the same firmware and this chip was
> > also part of the other patch you mentioned in your first e-mail. RV630
> > was added because I checked freedesktop bug 31943. The problem described
> > there is different from the one here, but I saw logs, when no monitor
> > was connected, and for this situation the patch would help.
> 
> I'd rather add quirks on a case by case bases rather than speculating
> on mailing list reports.

Done. See function radeon_connector_needs_extended_probe()

> 
> >
> > With regard to moving away from connector type and chip family to pci
> > devices I'm not really sure. I remember complaints from people a year
> > ago, that used the RS690 on a laptop and had the same problem. I just
> > can't find the related messages. Don't you believe that this could be to
> > focused? Especially, if we compare patch
> > http://git.kernel.org/?p=linux/kernel/git/airlied/drm-2.6.git;a=commitdiff;h=4a9a8b71e12d41abb71c4e741bff524f016cfef4?
> >
> 
> We should probably revert or rework that patch when we apply yours
> otherwise we may end up removing i2c buses unnecessarily in some
> cases.  I think this is a better approach.

Understood.

> 
> > I felt rather safe with the above approach, as nothing will go wrong, if
> > we check the HDMIA type connectors also RS690 of another manufacturers.
> > We just check for a valid first six bytes set of the EDID header now.
> 
> As I said above, lets just apply this to the specific board and
> connector that is problematic.  I seems to only affect the hdmi port
> on the add-in cards, so there's no need to penalize all hdmi ports.
> If we get enough quirks down the road, we can make it a general rule.
> 

You're right. The patch currently fixes only the ASUS M2A-VM device:
+       if ((dev->pdev->device == 0x791e) &&
+           (dev->pdev->subsystem_vendor == 0x1043) &&
+           (dev->pdev->subsystem_device == 0x826d)) {
+               if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
+                   (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
This will solve bug
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/722806.


> >
> > Just one info entry per connector will be added during connector setup.
> > The EDID dump was already there and comes from the DDC probing during
> > connector setup. After that, there are no more entries in the log with
> > regard to the buggy HDMI connector. From a user point of view I would
> > prefer to have the two log entries:
> > radeon 0000:01:05.0: HDMI-A-1: EDID block 0 invalid.
> > [drm] Radeon display connector HDMI-A-1: No display connected or invalid
> > EDID.
> > One from the probing, which is a little bit cryptic, and the explaining
> > one which prelude the silence for this connector.
> 
> ok, that makes sense.
> 
> >
> >> > diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
> >> > index 781196d..7e93cf9 100644
> >> > --- a/drivers/gpu/drm/radeon/radeon_i2c.c
> >> > +++ b/drivers/gpu/drm/radeon/radeon_i2c.c
> >> > @@ -34,7 +34,7 @@
> >> >  */
> >> >  bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
> >> >  {
> >> > -       u8 out_buf[] = { 0x0, 0x0};
> >> > +       u8 out = 0x0;
> >> >        u8 buf[2];
> >> >        int ret;
> >> >        struct i2c_msg msgs[] = {
> >> > @@ -42,7 +42,7 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
> >> >                        .addr = 0x50,
> >> >                        .flags = 0,
> >> >                        .len = 1,
> >> > -                       .buf = out_buf,
> >> > +                       .buf = &out,
> >> >                },
> >> >                {
> >> >                        .addr = 0x50,
> >>
> >>
> >> The change above doesn't seem to be related.
> >
> > This was a comment from Jean who complained about the ineffective usage
> > of the i2c bus. But I can also restore the old code. What's your
> > preference?
> 
> Ah, I missed that.  Let's make that a separate patch, or fix it when
> you add support for the extended edid check.
> 
Done.

The patch is for the latest git version of the linux kernel. Do you
think it would be possible to provide this patch already starting from
the most recent 2.35 kernel update? Ubuntu uses this kernel version for
the long-term stable Maverick release.

I will send the patch in my next e-mail. Hope this helps you. 

Best regards

Thomas



^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-06-23 22:05     ` reimth
@ 2011-07-06 10:09       ` reimth
  -1 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-07-06 10:09 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel
  Cc: dri-devel, linux-kernel, Thomas Reim

From: Thomas Reim <rdratlos@yahoo.co.uk>

    Some integrated ATI Radeon chipset implementations
    with add-on HDMI card (e. g. Asus M2A-VM HDMI) indicate the availability
    of a DDC even when the add-on card is not plugged in or HDMI is disabled
    in BIOS setup. In this case, drm_get_edid() and drm_edid_block_valid()
    periodically dump data and kernel errors into system log files and onto
    terminals. For these chipsets DDC probing is extended by a check for a
    correct EDID header. Only in case a valid EDID header is also found, the
    (HDMI) connector will be used by the Radeon driver. This prevents the
    kernel driver from useless flooding of logs and terminal sessions with
    EDID dumps and error messages.
    This patch adds a flag 'requires_extended_probe' to the radeon_connector
    structure. In function radeon_connector_needs_extended_probe() this flag
    can be set on a chipset family/vendor/connector type specific basis.
    In addition, function drm_edid_header_is_valid() has been added for EDID
    header check and function radeon_ddc_probe() has been adapted to perform
    extended DDC probing if required by the connector's flag.

    Tested for kernel 2.35, 2.38 and 3.0 on Asus M2A-VM HDMI board

Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
---
 drivers/gpu/drm/drm_edid.c                 |   24 +++++++++++----
 drivers/gpu/drm/radeon/radeon_connectors.c |   45 ++++++++++++++++++++++++++--
 drivers/gpu/drm/radeon/radeon_device.c     |    7 ++++-
 drivers/gpu/drm/radeon/radeon_display.c    |    9 +++++
 drivers/gpu/drm/radeon/radeon_i2c.c        |   32 +++++++++++++++-----
 drivers/gpu/drm/radeon/radeon_mode.h       |    6 +++-
 include/drm/drm_crtc.h                     |    1 +
 7 files changed, 105 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 0929219..1bbb85b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -127,6 +127,23 @@ static const u8 edid_header[] = {
 	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
 };
 
+ /*
+ * Sanity check the header of the base EDID block.  Return 8 if the header
+ * is perfect, down to 0 if it's totally wrong.
+ */
+int drm_edid_header_is_valid(const u8 *raw_edid)
+{
+	int i, score = 0;
+
+	for (i = 0; i < sizeof(edid_header); i++)
+		if (raw_edid[i] == edid_header[i])
+			score++;
+
+	return score;
+}
+EXPORT_SYMBOL(drm_edid_header_is_valid);
+
+
 /*
  * Sanity check the EDID block (base or extension).  Return 0 if the block
  * doesn't check out, or 1 if it's valid.
@@ -139,12 +156,7 @@ drm_edid_block_valid(u8 *raw_edid)
 	struct edid *edid = (struct edid *)raw_edid;
 
 	if (raw_edid[0] == 0x00) {
-		int score = 0;
-
-		for (i = 0; i < sizeof(edid_header); i++)
-			if (raw_edid[i] == edid_header[i])
-				score++;
-
+		int score = drm_edid_header_is_valid(raw_edid);
 		if (score == 8) ;
 		else if (score >= 6) {
 			DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index cbfca3a..2e70be2 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -424,6 +424,36 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr
 	return 0;
 }
 
+/*
+ * Some integrated ATI Radeon chipset implementations (e. g.
+ * Asus M2A-VM HDMI) may indicate the availability of a DDC,
+ * even when there's no monitor connected. For these connectors
+ * following DDC probe extension will be applied: check also for the
+ * availability of EDID with at least a correct EDID header. Only then,
+ * DDC is assumed to be available. This prevents drm_get_edid() and
+ * drm_edid_block_valid() from periodically dumping data and kernel
+ * errors into the logs and onto the terminal.
+ */
+static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
+				     uint32_t supported_device,
+				     int connector_type)
+{
+	/* Asus M2A-VM HDMI board sends data to i2c bus even,
+	 * if HDMI add-on card is not plugged in or HDMI is disabled in
+	 * BIOS. Valid DDC can only be assumed, if also a valid EDID header
+	 * can be retrieved via i2c bus during DDC probe */
+	if ((dev->pdev->device == 0x791e) &&
+	    (dev->pdev->subsystem_vendor == 0x1043) &&
+	    (dev->pdev->subsystem_device == 0x826d)) {
+		if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
+		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
+			return true;
+	}
+
+	/* Default: no EDID header probe required for DDC probing */
+	return false;
+}
+
 static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
 					  struct drm_connector *connector)
 {
@@ -655,7 +685,8 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
 		ret = connector_status_disconnected;
 
 	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector);
+		dret = radeon_ddc_probe(radeon_connector,
+					radeon_connector->requires_extended_probe);
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
@@ -827,7 +858,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 	bool dret = false;
 
 	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector);
+		dret = radeon_ddc_probe(radeon_connector,
+					radeon_connector->requires_extended_probe);
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
@@ -1245,7 +1277,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
 				if (radeon_dp_getdpcd(radeon_connector))
 					ret = connector_status_connected;
 			} else {
-				if (radeon_ddc_probe(radeon_connector))
+				if (radeon_ddc_probe(radeon_connector,
+						     radeon_connector->requires_extended_probe))
 					ret = connector_status_connected;
 			}
 		}
@@ -1400,6 +1433,9 @@ radeon_add_atom_connector(struct drm_device *dev,
 	radeon_connector->shared_ddc = shared_ddc;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
+	radeon_connector->requires_extended_probe =
+		radeon_connector_needs_extended_probe(rdev, supported_device,
+							connector_type);
 	radeon_connector->router = *router;
 	if (router->ddc_valid || router->cd_valid) {
 		radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
@@ -1746,6 +1782,9 @@ radeon_add_legacy_connector(struct drm_device *dev,
 	radeon_connector->devices = supported_device;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
+	radeon_connector->requires_extended_probe =
+		radeon_connector_needs_extended_probe(rdev, supported_device,
+							connector_type);
 	switch (connector_type) {
 	case DRM_MODE_CONNECTOR_VGA:
 		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 7cfaa7e..cbdac3d 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -704,8 +704,13 @@ int radeon_device_init(struct radeon_device *rdev,
 	rdev->gpu_lockup = false;
 	rdev->accel_working = false;
 
-	DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
+	if (pdev->subsystem_vendor == 0)
+		DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
 		radeon_family_name[rdev->family], pdev->vendor, pdev->device);
+	else
+		DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n",
+		radeon_family_name[rdev->family], pdev->vendor, pdev->device,
+		pdev->subsystem_vendor, pdev->subsystem_device);
 
 	/* mutex initialization are all done here so we
 	 * can recall function without having locking issues */
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 292f73f..ed085ce 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -777,8 +777,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
 	if (!radeon_connector->ddc_bus)
 		return -1;
 	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
+	/* Log EDID retrieval status here. In particular with regard to
+	 * connectors with requires_extended_probe flag set, that will prevent
+	 * function radeon_dvi_detect() to fetch EDID on this connector,
+	 * as long as there is no valid EDID header found */
 	if (edid) {
+		DRM_INFO("Radeon display connector %s: Found valid EDID",
+				drm_get_connector_name(connector));
 		kfree(edid);
+	} else {
+		DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
+				drm_get_connector_name(connector));
 	}
 	return ret;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 781196d..6c111c1 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -32,17 +32,17 @@
  * radeon_ddc_probe
  *
  */
-bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
+bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
 {
-	u8 out_buf[] = { 0x0, 0x0};
-	u8 buf[2];
+	u8 out = 0x0;
+	u8 buf[8];
 	int ret;
 	struct i2c_msg msgs[] = {
 		{
 			.addr = 0x50,
 			.flags = 0,
 			.len = 1,
-			.buf = out_buf,
+			.buf = &out,
 		},
 		{
 			.addr = 0x50,
@@ -52,15 +52,31 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 		}
 	};
 
+	/* Read 8 bytes from i2c for extended probe of EDID header */
+	if (requires_extended_probe)
+		msgs[1].len = 8;
+
 	/* on hw with routers, select right port */
 	if (radeon_connector->router.ddc_valid)
 		radeon_router_select_ddc_port(radeon_connector);
 
 	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
-	if (ret == 2)
-		return true;
-
-	return false;
+	if (ret != 2)
+		/* Couldn't find an accessible DDC on this connector */
+		return false;
+	if (requires_extended_probe) {
+		/* Probe also for valid EDID header
+		 * EDID header starts with:
+		 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
+		 * Only the first 6 bytes must be valid as
+		 * drm_edid_block_valid() can fix the last 2 bytes */
+		if (drm_edid_header_is_valid(buf) < 6) {
+			/* Couldn't find an accessible EDID on this
+			 * connector */
+			return false;
+		}
+	}
+	return true;
 }
 
 /* bit banging i2c */
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 6df4e3c..d09031c 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -438,6 +438,9 @@ struct radeon_connector {
 	struct radeon_i2c_chan *ddc_bus;
 	/* some systems have an hdmi and vga port with a shared ddc line */
 	bool shared_ddc;
+	/* for some Radeon chip families we apply an additional EDID header
+	   check as part of the DDC probe */
+	bool requires_extended_probe;
 	bool use_digital;
 	/* we need to mind the EDID between detect
 	   and get modes due to analog/digital/tvencoder */
@@ -514,7 +517,8 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
 				u8 val);
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
-extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
+extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector,
+			bool requires_extended_probe);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 33d12f8..0ec3687 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -802,6 +802,7 @@ extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev,
 extern int drm_add_modes_noedid(struct drm_connector *connector,
 				int hdisplay, int vdisplay);
 
+extern int drm_edid_header_is_valid(const u8 *raw_edid);
 extern bool drm_edid_is_valid(struct edid *edid);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
 					   int hsize, int vsize, int fresh);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
@ 2011-07-06 10:09       ` reimth
  0 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-07-06 10:09 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare, Tyson Whitehead
  Cc: dri-devel, linux-kernel, Thomas Reim

From: Thomas Reim <rdratlos@yahoo.co.uk>

    Some integrated ATI Radeon chipset implementations
    with add-on HDMI card (e. g. Asus M2A-VM HDMI) indicate the availability
    of a DDC even when the add-on card is not plugged in or HDMI is disabled
    in BIOS setup. In this case, drm_get_edid() and drm_edid_block_valid()
    periodically dump data and kernel errors into system log files and onto
    terminals. For these chipsets DDC probing is extended by a check for a
    correct EDID header. Only in case a valid EDID header is also found, the
    (HDMI) connector will be used by the Radeon driver. This prevents the
    kernel driver from useless flooding of logs and terminal sessions with
    EDID dumps and error messages.
    This patch adds a flag 'requires_extended_probe' to the radeon_connector
    structure. In function radeon_connector_needs_extended_probe() this flag
    can be set on a chipset family/vendor/connector type specific basis.
    In addition, function drm_edid_header_is_valid() has been added for EDID
    header check and function radeon_ddc_probe() has been adapted to perform
    extended DDC probing if required by the connector's flag.

    Tested for kernel 2.35, 2.38 and 3.0 on Asus M2A-VM HDMI board

Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
---
 drivers/gpu/drm/drm_edid.c                 |   24 +++++++++++----
 drivers/gpu/drm/radeon/radeon_connectors.c |   45 ++++++++++++++++++++++++++--
 drivers/gpu/drm/radeon/radeon_device.c     |    7 ++++-
 drivers/gpu/drm/radeon/radeon_display.c    |    9 +++++
 drivers/gpu/drm/radeon/radeon_i2c.c        |   32 +++++++++++++++-----
 drivers/gpu/drm/radeon/radeon_mode.h       |    6 +++-
 include/drm/drm_crtc.h                     |    1 +
 7 files changed, 105 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 0929219..1bbb85b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -127,6 +127,23 @@ static const u8 edid_header[] = {
 	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
 };
 
+ /*
+ * Sanity check the header of the base EDID block.  Return 8 if the header
+ * is perfect, down to 0 if it's totally wrong.
+ */
+int drm_edid_header_is_valid(const u8 *raw_edid)
+{
+	int i, score = 0;
+
+	for (i = 0; i < sizeof(edid_header); i++)
+		if (raw_edid[i] == edid_header[i])
+			score++;
+
+	return score;
+}
+EXPORT_SYMBOL(drm_edid_header_is_valid);
+
+
 /*
  * Sanity check the EDID block (base or extension).  Return 0 if the block
  * doesn't check out, or 1 if it's valid.
@@ -139,12 +156,7 @@ drm_edid_block_valid(u8 *raw_edid)
 	struct edid *edid = (struct edid *)raw_edid;
 
 	if (raw_edid[0] == 0x00) {
-		int score = 0;
-
-		for (i = 0; i < sizeof(edid_header); i++)
-			if (raw_edid[i] == edid_header[i])
-				score++;
-
+		int score = drm_edid_header_is_valid(raw_edid);
 		if (score == 8) ;
 		else if (score >= 6) {
 			DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index cbfca3a..2e70be2 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -424,6 +424,36 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr
 	return 0;
 }
 
+/*
+ * Some integrated ATI Radeon chipset implementations (e. g.
+ * Asus M2A-VM HDMI) may indicate the availability of a DDC,
+ * even when there's no monitor connected. For these connectors
+ * following DDC probe extension will be applied: check also for the
+ * availability of EDID with at least a correct EDID header. Only then,
+ * DDC is assumed to be available. This prevents drm_get_edid() and
+ * drm_edid_block_valid() from periodically dumping data and kernel
+ * errors into the logs and onto the terminal.
+ */
+static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
+				     uint32_t supported_device,
+				     int connector_type)
+{
+	/* Asus M2A-VM HDMI board sends data to i2c bus even,
+	 * if HDMI add-on card is not plugged in or HDMI is disabled in
+	 * BIOS. Valid DDC can only be assumed, if also a valid EDID header
+	 * can be retrieved via i2c bus during DDC probe */
+	if ((dev->pdev->device == 0x791e) &&
+	    (dev->pdev->subsystem_vendor == 0x1043) &&
+	    (dev->pdev->subsystem_device == 0x826d)) {
+		if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
+		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
+			return true;
+	}
+
+	/* Default: no EDID header probe required for DDC probing */
+	return false;
+}
+
 static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
 					  struct drm_connector *connector)
 {
@@ -655,7 +685,8 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
 		ret = connector_status_disconnected;
 
 	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector);
+		dret = radeon_ddc_probe(radeon_connector,
+					radeon_connector->requires_extended_probe);
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
@@ -827,7 +858,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 	bool dret = false;
 
 	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector);
+		dret = radeon_ddc_probe(radeon_connector,
+					radeon_connector->requires_extended_probe);
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
@@ -1245,7 +1277,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
 				if (radeon_dp_getdpcd(radeon_connector))
 					ret = connector_status_connected;
 			} else {
-				if (radeon_ddc_probe(radeon_connector))
+				if (radeon_ddc_probe(radeon_connector,
+						     radeon_connector->requires_extended_probe))
 					ret = connector_status_connected;
 			}
 		}
@@ -1400,6 +1433,9 @@ radeon_add_atom_connector(struct drm_device *dev,
 	radeon_connector->shared_ddc = shared_ddc;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
+	radeon_connector->requires_extended_probe =
+		radeon_connector_needs_extended_probe(rdev, supported_device,
+							connector_type);
 	radeon_connector->router = *router;
 	if (router->ddc_valid || router->cd_valid) {
 		radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
@@ -1746,6 +1782,9 @@ radeon_add_legacy_connector(struct drm_device *dev,
 	radeon_connector->devices = supported_device;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
+	radeon_connector->requires_extended_probe =
+		radeon_connector_needs_extended_probe(rdev, supported_device,
+							connector_type);
 	switch (connector_type) {
 	case DRM_MODE_CONNECTOR_VGA:
 		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 7cfaa7e..cbdac3d 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -704,8 +704,13 @@ int radeon_device_init(struct radeon_device *rdev,
 	rdev->gpu_lockup = false;
 	rdev->accel_working = false;
 
-	DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
+	if (pdev->subsystem_vendor == 0)
+		DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
 		radeon_family_name[rdev->family], pdev->vendor, pdev->device);
+	else
+		DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n",
+		radeon_family_name[rdev->family], pdev->vendor, pdev->device,
+		pdev->subsystem_vendor, pdev->subsystem_device);
 
 	/* mutex initialization are all done here so we
 	 * can recall function without having locking issues */
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 292f73f..ed085ce 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -777,8 +777,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
 	if (!radeon_connector->ddc_bus)
 		return -1;
 	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
+	/* Log EDID retrieval status here. In particular with regard to
+	 * connectors with requires_extended_probe flag set, that will prevent
+	 * function radeon_dvi_detect() to fetch EDID on this connector,
+	 * as long as there is no valid EDID header found */
 	if (edid) {
+		DRM_INFO("Radeon display connector %s: Found valid EDID",
+				drm_get_connector_name(connector));
 		kfree(edid);
+	} else {
+		DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
+				drm_get_connector_name(connector));
 	}
 	return ret;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 781196d..6c111c1 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -32,17 +32,17 @@
  * radeon_ddc_probe
  *
  */
-bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
+bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
 {
-	u8 out_buf[] = { 0x0, 0x0};
-	u8 buf[2];
+	u8 out = 0x0;
+	u8 buf[8];
 	int ret;
 	struct i2c_msg msgs[] = {
 		{
 			.addr = 0x50,
 			.flags = 0,
 			.len = 1,
-			.buf = out_buf,
+			.buf = &out,
 		},
 		{
 			.addr = 0x50,
@@ -52,15 +52,31 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 		}
 	};
 
+	/* Read 8 bytes from i2c for extended probe of EDID header */
+	if (requires_extended_probe)
+		msgs[1].len = 8;
+
 	/* on hw with routers, select right port */
 	if (radeon_connector->router.ddc_valid)
 		radeon_router_select_ddc_port(radeon_connector);
 
 	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
-	if (ret == 2)
-		return true;
-
-	return false;
+	if (ret != 2)
+		/* Couldn't find an accessible DDC on this connector */
+		return false;
+	if (requires_extended_probe) {
+		/* Probe also for valid EDID header
+		 * EDID header starts with:
+		 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
+		 * Only the first 6 bytes must be valid as
+		 * drm_edid_block_valid() can fix the last 2 bytes */
+		if (drm_edid_header_is_valid(buf) < 6) {
+			/* Couldn't find an accessible EDID on this
+			 * connector */
+			return false;
+		}
+	}
+	return true;
 }
 
 /* bit banging i2c */
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 6df4e3c..d09031c 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -438,6 +438,9 @@ struct radeon_connector {
 	struct radeon_i2c_chan *ddc_bus;
 	/* some systems have an hdmi and vga port with a shared ddc line */
 	bool shared_ddc;
+	/* for some Radeon chip families we apply an additional EDID header
+	   check as part of the DDC probe */
+	bool requires_extended_probe;
 	bool use_digital;
 	/* we need to mind the EDID between detect
 	   and get modes due to analog/digital/tvencoder */
@@ -514,7 +517,8 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
 				u8 val);
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
-extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
+extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector,
+			bool requires_extended_probe);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 33d12f8..0ec3687 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -802,6 +802,7 @@ extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev,
 extern int drm_add_modes_noedid(struct drm_connector *connector,
 				int hdisplay, int vdisplay);
 
+extern int drm_edid_header_is_valid(const u8 *raw_edid);
 extern bool drm_edid_is_valid(struct edid *edid);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
 					   int hsize, int vsize, int fresh);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-07-06 10:09       ` reimth
  (?)
@ 2011-07-06 12:26       ` Thomas Reim
  -1 siblings, 0 replies; 50+ messages in thread
From: Thomas Reim @ 2011-07-06 12:26 UTC (permalink / raw)
  To: dri-devel, linux-kernel

Here are the kernel logs with and without the patch for better
visualisation of the changes:

1. dmesg after applying the patch:

[    0.000000] Initializing cgroup subsys cpuset
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Linux version 3.0-3-generic (root@Mark-Aurel) (gcc
version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4) ) #5 SMP Wed Jul 6 01:54:25
CEST 2011 (Ubuntu 3.0-3.5-generic 3.0.0-rc5)
...
[    6.980082] [drm] Initialized drm 1.1.0 20060810
[    8.353140] [drm] radeon defaulting to kernel modesetting.
[    8.353147] [drm] radeon kernel modesetting enabled.
[    8.423983] radeon 0000:01:05.0: PCI INT A -> GSI 18 (level, low) ->
IRQ 18
[    8.424296] [drm] initializing kernel modesetting (RS690
0x1002:0x791E 0x1043:0x826D).
[    8.424323] [drm] register mmio base: 0xFDCF0000
[    8.424326] [drm] register mmio size: 65536
[    8.424667] ATOM BIOS: ATI
[    8.424697] radeon 0000:01:05.0: VRAM: 128M 0x0000000038000000 -
0x000000003FFFFFFF (128M used)
[    8.424702] radeon 0000:01:05.0: GTT: 512M 0x0000000040000000 -
0x000000005FFFFFFF
[    8.424722] [drm] Supports vblank timestamp caching Rev 1
(10.10.2010).
[    8.424724] [drm] Driver supports precise vblank timestamp query.
[    8.424738] [drm] radeon: irq initialized.
[    8.424833] [drm] Detected VRAM RAM=128M, BAR=128M
[    8.424839] [drm] RAM width 128bits DDR
[    8.429082] [TTM] Zone  kernel: Available graphics memory: 412360
kiB.
[    8.429087] [TTM] Initializing pool allocator.
[    8.429119] [drm] radeon: 128M of VRAM memory ready
[    8.429121] [drm] radeon: 512M of GTT memory ready.
[    8.429149] [drm] GART: num cpu pages 131072, num gpu pages 131072
[    8.433650] [drm] radeon: 1 quad pipes, 1 z pipes initialized.
[    8.450393] radeon 0000:01:05.0: WB enabled
[    8.452791] [drm] Loading RS690/RS740 Microcode
[    9.139696] [drm] radeon: ring at 0x0000000040001000
[    9.139718] [drm] ring test succeeded in 1 usecs
[    9.139884] [drm] radeon: ib pool ready.
[    9.139978] [drm] ib test succeeded in 0 usecs
[    9.140324] [drm] Radeon Display Connectors
[    9.140327] [drm] Connector 0:
[    9.140329] [drm]   VGA
[    9.140332] [drm]   DDC: 0x7e50 0x7e40 0x7e54 0x7e44 0x7e58 0x7e48
0x7e5c 0x7e4c
[    9.140334] [drm]   Encoders:
[    9.140336] [drm]     CRT1: INTERNAL_KLDSCP_DAC1
[    9.140338] [drm] Connector 1:
[    9.140340] [drm]   S-video
[    9.140341] [drm]   Encoders:
[    9.140343] [drm]     TV1: INTERNAL_KLDSCP_DAC1
[    9.140344] [drm] Connector 2:
[    9.140346] [drm]   HDMI-A
[    9.140347] [drm]   HPD2
[    9.140350] [drm]   DDC: 0x7e40 0x7e60 0x7e44 0x7e64 0x7e48 0x7e68
0x7e4c 0x7e6c
[    9.140352] [drm]   Encoders:
[    9.140354] [drm]     DFP2: INTERNAL_DDI
[    9.140356] [drm] Connector 3:
[    9.140357] [drm]   DVI-D
[    9.140360] [drm]   DDC: 0x7e40 0x7e50 0x7e44 0x7e54 0x7e48 0x7e58
0x7e4c 0x7e5c
[    9.140362] [drm]   Encoders:
[    9.140364] [drm]     DFP3: INTERNAL_LVTM1
[    9.200505] [drm] Radeon display connector VGA-1: No monitor
connected or invalid EDID
[    9.536899] Raw EDID:
[    9.536907] <3>00 00 00 00 00 01 00 00 00 00 00 00 00 00 00
00  ................
[    9.536911] <3>00 00 00 00 3f 00 00 00 00 00 00 00 00 00 00
00  ....?...........
[    9.536914] <3>00 00 03 00 00 00 00 00 00 00 00 00 00 7f 00
00  ................
[    9.536917] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[    9.536920] <3>00 00 00 00 00 00 00 3f 00 00 00 00 00 00 00
00  .......?........
[    9.536922] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[    9.536925] <3>ff 00 00 00 00 00 00 00 00 00 00 00 00 0f 1f
00  ................
[    9.536928] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[    9.536930] 
[    9.865805] Raw EDID:
[    9.865813] <3>00 00 00 00 01 00 00 00 00 00 00 00 00 00 ff
00  ................
[    9.865816] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 1f 00
00  ................
[    9.865819] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[    9.865822] <3>00 00 00 00 00 00 00 07 00 00 00 00 00 00 00
00  ................
[    9.865825] <3>00 00 03 00 00 00 00 00 00 00 ff 00 00 00 00
00  ................
[    9.865828] <3>00 03 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[    9.865831] <3>00 00 1f 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[    9.865833] <3>00 00 00 00 00 00 00 00 00 00 07 00 00 00 00
00  ................
[    9.865836] 
[   10.211426] Raw EDID:
[   10.211436] <3>00 00 00 00 00 00 00 03 00 00 00 ff 00 00 00
00  ................
[   10.211439] <3>00 00 00 00 00 00 00 03 00 00 00 00 00 00 00
00  ................
[   10.211442] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   10.211445] <3>7f 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   10.211448] <3>00 00 00 00 00 00 3f 00 00 00 00 ff 00 00 00
00  ......?.........
[   10.211451] <3>00 00 00 00 00 00 00 00 00 00 00 00 3f 00 00
00  ............?...
[   10.211454] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   10.211457] <3>00 3f 00 00 00 00 00 00 00 00 00 00 00 00 ff
00  .?..............
[   10.211459] 
[   10.407265] Raw EDID:
[   10.407274] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   10.407277] <3>00 00 00 ff 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   10.407280] <3>00 00 00 ff 00 7f 00 00 00 00 00 00 00 00 00
00  ................
[   10.407283] <3>00 00 00 00 00 00 ff 00 00 00 00 00 00 00 00
00  ................
[   10.407286] <3>00 00 00 00 00 00 00 00 00 00 00 7f 00 00 00
00  ................
[   10.407289] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   10.407309] <3>00 0f 00 00 00 00 00 00 00 00 01 00 00 00 00
00  ................
[   10.407312] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 3f 00
00  .............?..
[   10.407314] 
[   10.407320] radeon 0000:01:05.0: HDMI-A-1: EDID block 0 invalid.
[   10.407324] [drm] Radeon display connector HDMI-A-1: No monitor
connected or invalid EDID
[   10.601868] [drm] Radeon display connector DVI-D-1: Found valid EDID
[   11.200051] [drm] fb mappable at 0xF0040000
[   11.200056] [drm] vram apper at 0xF0000000
[   11.200059] [drm] size 5242880
[   11.200061] [drm] fb depth is 24
[   11.200062] [drm]    pitch is 5120
[   11.201974] drm: registered panic notifier
[   11.202110] [drm] Initialized radeon 2.10.0 20080528 for 0000:01:05.0
on minor 0

> From: Thomas Reim <rdratlos@yahoo.co.uk>
> 
>     Some integrated ATI Radeon chipset implementations
>     with add-on HDMI card (e. g. Asus M2A-VM HDMI) indicate the availability
>     of a DDC even when the add-on card is not plugged in or HDMI is disabled
>     in BIOS setup. In this case, drm_get_edid() and drm_edid_block_valid()
>     periodically dump data and kernel errors into system log files and onto
>     terminals. For these chipsets DDC probing is extended by a check for a
>     correct EDID header. Only in case a valid EDID header is also found, the
>     (HDMI) connector will be used by the Radeon driver. This prevents the
>     kernel driver from useless flooding of logs and terminal sessions with
>     EDID dumps and error messages.
>     This patch adds a flag 'requires_extended_probe' to the radeon_connector
>     structure. In function radeon_connector_needs_extended_probe() this flag
>     can be set on a chipset family/vendor/connector type specific basis.
>     In addition, function drm_edid_header_is_valid() has been added for EDID
>     header check and function radeon_ddc_probe() has been adapted to perform
>     extended DDC probing if required by the connector's flag.
> 
>     Tested for kernel 2.35, 2.38 and 3.0 on Asus M2A-VM HDMI board
> 
> Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>


2. dmesg without patch:

[    0.000000] Initializing cgroup subsys cpuset
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Linux version 3.0.0-rc3-radeonfix (root@Mark-Aurel) (gcc
version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5) ) #1 SMP Tue Jun 21
10:29:44 CEST 2011
[    0.000000] Command line:
BOOT_IMAGE=/boot/vmlinuz-3.0.0-rc3-radeonfix
root=UUID=0cc18590-dcbb-43ba-867a-0a3b3b6a9b56 ro quiet splash
vt.handoff=7
.
.
.
[   13.590728] [drm] Initialized drm 1.1.0 20060810
[   14.923157] [drm] radeon defaulting to kernel modesetting.
[   14.923163] [drm] radeon kernel modesetting enabled.
[   14.931891] radeon 0000:01:05.0: PCI INT A -> GSI 18 (level, low) ->
IRQ 18
[   14.932445] [drm] initializing kernel modesetting (RS690
0x1002:0x791E).
[   14.932475] [drm] register mmio base: 0xFDCF0000
[   14.932478] [drm] register mmio size: 65536
[   14.932817] ATOM BIOS: ATI
[   14.932845] radeon 0000:01:05.0: VRAM: 128M 0x0000000038000000 -
0x000000003FFFFFFF (128M used)
[   14.932849] radeon 0000:01:05.0: GTT: 512M 0x0000000040000000 -
0x000000005FFFFFFF
[   14.932884] [drm] Supports vblank timestamp caching Rev 1
(10.10.2010).
[   14.932887] [drm] Driver supports precise vblank timestamp query.
[   14.932902] [drm] radeon: irq initialized.
[   14.932994] [drm] Detected VRAM RAM=128M, BAR=128M
[   14.932998] [drm] RAM width 128bits DDR
[   14.933165] [TTM] Zone  kernel: Available graphics memory: 445354
kiB.
[   14.933168] [TTM] Initializing pool allocator.
[   14.933200] [drm] radeon: 128M of VRAM memory ready
[   14.933203] [drm] radeon: 512M of GTT memory ready.
[   14.933284] [drm] GART: num cpu pages 131072, num gpu pages 131072
[   14.938106] [drm] radeon: 1 quad pipes, 1 z pipes initialized.
[   14.981418] radeon 0000:01:05.0: WB enabled
[   14.982168] [drm] Loading RS690/RS740 Microcode
[   15.030767] [drm] radeon: ring at 0x0000000040001000
[   15.030789] [drm] ring test succeeded in 1 usecs
[   15.030950] [drm] radeon: ib pool ready.
[   15.031038] [drm] ib test succeeded in 0 usecs
[   15.031047] failed to evaluate ATIF got AE_BAD_PARAMETER
[   15.031332] [drm] Radeon Display Connectors
[   15.031335] [drm] Connector 0:
[   15.031337] [drm]   VGA
[   15.031340] [drm]   DDC: 0x7e50 0x7e40 0x7e54 0x7e44 0x7e58 0x7e48
0x7e5c 0x7e4c
[   15.031342] [drm]   Encoders:
[   15.031344] [drm]     CRT1: INTERNAL_KLDSCP_DAC1
[   15.031346] [drm] Connector 1:
[   15.031348] [drm]   S-video
[   15.031349] [drm]   Encoders:
[   15.031351] [drm]     TV1: INTERNAL_KLDSCP_DAC1
[   15.031353] [drm] Connector 2:
[   15.031355] [drm]   HDMI-A
[   15.031356] [drm]   HPD2
[   15.031359] [drm]   DDC: 0x7e40 0x7e60 0x7e44 0x7e64 0x7e48 0x7e68
0x7e4c 0x7e6c
[   15.031361] [drm]   Encoders:
[   15.031363] [drm]     DFP2: INTERNAL_DDI
[   15.031365] [drm] Connector 3:
[   15.031367] [drm]   DVI-D
[   15.031369] [drm]   DDC: 0x7e40 0x7e50 0x7e44 0x7e54 0x7e48 0x7e58
0x7e4c 0x7e5c
[   15.031371] [drm]   Encoders:
[   15.031373] [drm]     DFP3: INTERNAL_LVTM1
[   15.461821] Raw EDID:
[   15.461865] <3>00 00 00 00 00 00 00 00 00 00 00 00 07 00 00
00  ................
[   15.461869] <3>00 00 00 00 00 00 00 00 00 00 00 00 01 00 00
00  ................
[   15.461872] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
3f  ...............?
[   15.461875] <3>0f 1f 3f 1f 3f 7f 00 00 00 00 00 00 00 00 00
00  ..?.?...........
[   15.461877] <3>00 00 00 00 00 00 00 ff 00 00 00 00 00 00 00
00  ................
[   15.461880] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
3f  ...............?
[   15.461883] <3>03 1f 00 00 00 00 00 00 00 00 3f 00 00 00 0f
00  ..........?.....
[   15.461886] <3>00 00 00 00 00 00 00 00 00 00 0f 07 00 3f 00
00  .............?..
[   15.461888] 
[   15.822495] Raw EDID:
[   15.822539] <3>00 03 00 00 00 00 00 00 00 3f 00 00 00 00 00
00  .........?......
[   15.822542] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   15.822545] <3>00 0f 00 00 00 00 00 00 00 00 00 00 00 3f 00
00  .............?..
[   15.822548] <3>0f 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   15.822551] <3>00 00 00 00 00 00 00 00 00 00 01 00 00 00 00
00  ................
[   15.822553] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 07
00  ................
[   15.822556] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   15.822559] <3>00 00 00 00 00 00 00 00 7f 00 ff 00 00 00 00
00  ................
[   15.822561] 
[   15.861945] EXT4-fs (sda3): re-mounted. Opts: errors=remount-ro
[   16.193649] Raw EDID:
[   16.193692] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   16.193696] <3>00 00 00 00 1f 00 00 00 00 00 03 00 00 00 00
00  ................
[   16.193699] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   16.193702] <3>00 00 00 00 00 ff 00 00 00 00 00 00 00 00 00
00  ................
[   16.193705] <3>00 00 00 00 00 00 00 00 00 00 00 7f 00 00 00
00  ................
[   16.193707] <3>00 00 00 7f 00 00 00 3f 00 00 00 00 00 07 3f
00  .......?......?.
[   16.193710] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   16.193713] <3>00 03 00 00 07 1f 00 00 00 00 00 00 00 00 00
00  ................
[   16.193715] 
[   16.499673] Raw EDID:
[   16.499717] <3>00 07 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   16.499720] <3>00 00 00 00 00 00 00 00 01 00 00 00 00 00 00
00  ................
[   16.499723] <3>00 00 00 00 00 00 00 00 00 00 00 00 03 00 00
00  ................
[   16.499726] <3>00 00 00 00 03 00 00 07 00 00 00 00 00 00 00
00  ................
[   16.499729] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   16.499732] <3>00 ff 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   16.499734] <3>00 00 00 00 00 00 00 00 00 00 00 3f 00 00 01
00  ...........?....
[   16.499737] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   16.499739] 
[   16.499778] radeon 0000:01:05.0: HDMI-A-1: EDID block 0 invalid.
[   17.585964] Raw EDID:
[   17.586008] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 7f
00  ................
[   17.586012] <3>00 00 00 00 00 00 00 00 00 00 00 ff 00 00 00
00  ................
[   17.586015] <3>00 ff 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   17.586017] <3>00 00 00 00 00 00 00 00 00 00 00 3f 00 00 00
00  ...........?....
[   17.586020] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 01
00  ................
[   17.586023] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   17.586026] <3>00 00 00 00 00 00 00 00 00 7f 00 00 00 00 00
00  ................
[   17.586028] <3>00 00 00 00 00 3f 00 00 00 00 00 00 00 00 00
00  .....?..........
[   17.586030] 
[   17.886217] Raw EDID:
[   17.886260] <3>00 00 00 00 00 00 00 7f 00 00 00 00 00 00 00
00  ................
[   17.886263] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   17.886266] <3>00 0f 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   17.886269] <3>00 00 00 00 00 00 00 00 00 00 00 01 00 00 00
00  ................
[   17.886271] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   17.886274] <3>00 00 00 00 00 0f 00 00 00 00 00 00 00 00 00
00  ................
[   17.886277] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01  ................
[   17.886279] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   17.886282] 
[   18.203072] Raw EDID:
[   18.203117] <3>00 00 00 00 00 00 0f 00 00 00 00 00 00 00 00
00  ................
[   18.203120] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   18.203123] <3>01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   18.203126] <3>00 00 00 00 00 00 00 00 00 00 00 7f 00 00 00
00  ................
[   18.203129] <3>00 00 00 0f 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   18.203131] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 01 00
00  ................
[   18.203134] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   18.203137] <3>00 00 00 00 00 00 00 00 7f 00 00 00 00 00 00
00  ................
[   18.203139] 
[   18.493769] Raw EDID:
[   18.493812] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 01
00  ................
[   18.493815] <3>00 00 00 00 00 00 00 00 00 00 00 00 1f 00 00
00  ................
[   18.493818] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   18.493821] <3>00 00 00 00 00 00 03 00 00 00 00 00 00 00 00
00  ................
[   18.493823] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   18.493826] <3>00 ff 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   18.493829] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   18.493832] <3>00 00 00 00 00 00 3f 00 00 00 00 00 00 00 00
00  ......?.........
[   18.493834] 
[   18.493872] radeon 0000:01:05.0: HDMI-A-1: EDID block 0 invalid.
[   18.493877] [drm:radeon_dvi_detect] *ERROR* HDMI-A-1: probed a
monitor but no|invalid EDID
[   18.900024] [drm] fb mappable at 0xF0040000
[   18.900029] [drm] vram apper at 0xF0000000
[   18.900031] [drm] size 5242880
[   18.900033] [drm] fb depth is 24
[   18.900034] [drm]    pitch is 5120
[   18.982054] drm: registered panic notifier
[   19.040041] [drm] Initialized radeon 2.10.0 20080528 for 0000:01:05.0
on minor 0
.
.
.
[   20.064119] Raw EDID:
[   20.064168] <3>00 00 00 00 00 00 00 00 00 00 07 00 00 00 00
00  ................
[   20.064171] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1f  ................
[   20.064174] <3>00 00 00 00 00 00 00 1f 00 00 00 00 00 00 00
00  ................
[   20.064177] <3>00 00 00 00 00 00 3f 00 00 00 00 00 00 00 00
00  ......?.........
[   20.064180] <3>00 00 00 00 03 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.064182] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 1f 00
00  ................
[   20.064185] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.064188] <3>00 00 00 00 00 07 00 00 00 00 00 00 00 00 00
00  ................
[   20.064190] 
[   20.257421] Raw EDID:
[   20.257471] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.257474] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.257477] <3>00 00 7f 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.257479] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.257482] <3>07 00 00 00 00 00 00 00 00 00 00 07 00 00 00
00  ................
[   20.257485] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.257487] <3>00 00 00 00 00 01 00 00 00 00 00 00 03 00 00
00  ................
[   20.257490] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.257492] 
[   20.465811] Raw EDID:
[   20.465860] <3>00 00 00 3f 00 00 00 00 00 00 00 07 00 00 00
00  ...?............
[   20.465863] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.465866] <3>00 00 7f 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.465869] <3>00 00 00 00 00 00 00 00 00 00 00 00 1f 00 00
00  ................
[   20.465872] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.465874] <3>00 00 00 00 00 00 07 00 00 00 00 00 00 00 00
00  ................
[   20.465877] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.465880] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.465882] 
[   20.665976] Raw EDID:
[   20.666026] <3>00 00 00 00 00 00 00 0f 00 00 00 00 00 00 00
00  ................
[   20.666029] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.666032] <3>00 07 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.666034] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.666037] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.666040] <3>00 00 00 00 00 00 3f 00 00 00 00 00 00 00 00
00  ......?.........
[   20.666043] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.666045] <3>0f 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.666047] 
[   20.666076] radeon 0000:01:05.0: HDMI-A-1: EDID block 0 invalid.
[   20.666081] [drm:radeon_dvi_detect] *ERROR* HDMI-A-1: probed a
monitor but no|invalid EDID
[   20.900353] Raw EDID:
[   20.900399] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.900402] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.900405] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.900408] <3>07 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.900411] <3>00 00 00 00 00 00 00 00 00 00 01 00 00 00 00
00  ................
[   20.900413] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   20.900416] <3>00 00 00 00 00 7f 00 00 00 00 00 00 00 00 00
00  ................
[   20.900419] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1f  ................
[   20.900421] 
[   21.102164] Raw EDID:
[   21.102209] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   21.102212] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 0f
00  ................
[   21.102215] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   21.102217] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   21.102220] <3>00 00 00 00 00 00 7f 00 00 00 00 00 00 00 00
00  ................
[   21.102223] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   21.102226] <3>1f 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   21.102228] <3>00 00 00 00 00 00 00 00 00 00 07 00 00 00 00
00  ................
[   21.102230] 
[   21.303189] Raw EDID:
[   21.303234] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   21.303237] <3>00 7f 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   21.303240] <3>00 00 00 00 00 00 00 00 00 00 00 1f 00 00 00
00  ................
[   21.303243] <3>00 00 00 00 00 0f 00 00 00 00 00 00 00 00 00
00  ................
[   21.303245] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
03  ................
[   21.303248] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   21.303251] <3>00 00 00 00 00 00 00 00 00 00 ff 00 00 00 00
00  ................
[   21.303254] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   21.303256] 
[   21.488194] Raw EDID:
[   21.488248] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 0f
00  ................
[   21.488251] <3>00 00 00 07 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   21.488254] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   21.488256] <3>00 00 00 00 00 00 3f 00 00 00 00 00 00 00 00
00  ......?.........
[   21.488259] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   21.488262] <3>0f 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   21.488265] <3>00 00 00 00 00 00 00 00 00 00 03 00 00 00 00
00  ................
[   21.488267] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   21.488269] 
[   21.488300] radeon 0000:01:05.0: HDMI-A-1: EDID block 0 invalid.
[   21.488305] [drm:radeon_dvi_detect] *ERROR* HDMI-A-1: probed a
monitor but no|invalid EDID
[   21.625439] r8169 0000:03:05.0: eth1: link up
[   23.012406] Raw EDID:
[   23.012414] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 01 00
00  ................
[   23.012417] <3>00 00 00 00 00 00 00 00 00 00 01 00 00 00 00
00  ................
[   23.012420] <3>00 00 00 00 00 00 00 00 00 01 00 00 00 00 00
00  ................
[   23.012423] <3>00 00 00 00 00 00 00 01 00 00 00 00 00 00 00
00  ................
[   23.012426] <3>00 00 00 00 00 1f 00 00 00 00 00 00 00 00 00
00  ................
[   23.012428] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
03  ................
[   23.012431] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.012434] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.012436] 
[   23.165127] Raw EDID:
[   23.165135] <3>00 00 00 00 7f 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.165138] <3>00 00 0f 00 00 00 00 00 00 00 00 00 00 00 1f
00  ................
[   23.165141] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.165144] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.165147] <3>00 00 00 00 00 00 00 7f 00 00 00 00 00 00 00
00  ................
[   23.165149] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.165152] <3>00 1f 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.165155] <3>00 00 03 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.165157] 
[   23.315132] Raw EDID:
[   23.315139] <3>00 00 00 00 00 00 00 00 00 0f 00 00 00 00 00
00  ................
[   23.315142] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.315145] <3>00 00 7f 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.315148] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.315151] <3>07 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.315153] <3>00 00 00 00 00 00 00 00 00 00 01 00 00 00 00
00  ................
[   23.315156] <3>00 00 00 00 00 00 00 00 01 00 00 00 00 00 00
00  ................
[   23.315159] <3>00 00 03 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.315161] 
[   23.477121] Raw EDID:
[   23.477129] <3>00 00 00 00 00 00 00 00 00 0f 00 00 00 00 00
00  ................
[   23.477132] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.477135] <3>00 00 00 00 00 ff 00 00 00 00 00 00 00 00 00
00  ................
[   23.477138] <3>00 00 00 00 00 00 00 00 00 3f 00 00 00 00 00
00  .........?......
[   23.477140] <3>00 00 00 0f 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.477143] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 01 00
00  ................
[   23.477146] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 7f
00  ................
[   23.477149] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.477151] 
[   23.477156] radeon 0000:01:05.0: HDMI-A-1: EDID block 0 invalid.
[   23.477161] [drm:radeon_dvi_detect] *ERROR* HDMI-A-1: probed a
monitor but no|invalid EDID
[   23.650366] Raw EDID:
[   23.650374] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.650377] <3>00 00 3f 00 00 00 00 00 00 00 00 00 0f 00 00
00  ..?.............
[   23.650380] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.650383] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01  ................
[   23.650385] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.650388] <3>00 00 00 00 00 ff 00 00 00 00 00 00 00 00 00
00  ................
[   23.650391] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.650394] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
3f  ...............?
[   23.650396] 
[   23.792015] Raw EDID:
[   23.792022] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.792025] <3>00 00 00 00 00 00 ff 00 00 00 00 00 00 00 00
00  ................
[   23.792028] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.792031] <3>00 00 00 00 00 00 00 00 00 3f 00 00 00 00 00
00  .........?......
[   23.792034] <3>00 00 00 00 00 00 1f 00 00 00 00 00 00 00 00
00  ................
[   23.792036] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.792039] <3>00 1f 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.792042] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.792044] 
[   23.930039] Raw EDID:
[   23.930047] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.930050] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.930053] <3>00 00 3f 00 03 00 00 00 00 00 00 00 00 00 00
00  ..?.............
[   23.930056] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.930058] <3>00 00 00 1f 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.930061] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.930064] <3>00 00 00 00 00 01 00 00 00 00 00 00 00 00 00
00  ................
[   23.930066] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   23.930069] 
[   24.108740] Raw EDID:
[   24.108748] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   24.108752] <3>00 00 00 00 00 00 00 ff 00 00 00 00 00 00 00
00  ................
[   24.108754] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   24.108757] <3>00 1f 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   24.108760] <3>00 00 00 00 00 00 00 00 00 00 00 03 00 00 00
00  ................
[   24.108763] <3>00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00  ................
[   24.108765] <3>00 00 00 00 00 00 1f 00 00 00 00 00 00 00 ff
00  ................
[   24.108768] <3>00 00 00 00 00 00 00 00 00 00 00 00 01 00 00
00  ................
[   24.108770] 
[   24.108775] radeon 0000:01:05.0: HDMI-A-1: EDID block 0 invalid.
[   24.108780] [drm:radeon_dvi_detect] *ERROR* HDMI-A-1: probed a
monitor but no|invalid EDID
...

Best regards

Thomas



^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-07-06 10:09       ` reimth
  (?)
  (?)
@ 2011-07-06 15:39       ` Alex Deucher
  2011-07-06 15:42         ` Alex Deucher
                           ` (4 more replies)
  -1 siblings, 5 replies; 50+ messages in thread
From: Alex Deucher @ 2011-07-06 15:39 UTC (permalink / raw)
  To: reimth
  Cc: Dave Airlie, Mario Kleiner, Jean Delvare, Tyson Whitehead,
	Jason Wessel, dri-devel, linux-kernel, Thomas Reim

On Wed, Jul 6, 2011 at 6:09 AM,  <reimth@googlemail.com> wrote:
> From: Thomas Reim <rdratlos@yahoo.co.uk>
>
>    Some integrated ATI Radeon chipset implementations
>    with add-on HDMI card (e. g. Asus M2A-VM HDMI) indicate the availability
>    of a DDC even when the add-on card is not plugged in or HDMI is disabled
>    in BIOS setup. In this case, drm_get_edid() and drm_edid_block_valid()
>    periodically dump data and kernel errors into system log files and onto
>    terminals. For these chipsets DDC probing is extended by a check for a
>    correct EDID header. Only in case a valid EDID header is also found, the
>    (HDMI) connector will be used by the Radeon driver. This prevents the
>    kernel driver from useless flooding of logs and terminal sessions with
>    EDID dumps and error messages.
>    This patch adds a flag 'requires_extended_probe' to the radeon_connector
>    structure. In function radeon_connector_needs_extended_probe() this flag
>    can be set on a chipset family/vendor/connector type specific basis.
>    In addition, function drm_edid_header_is_valid() has been added for EDID
>    header check and function radeon_ddc_probe() has been adapted to perform
>    extended DDC probing if required by the connector's flag.
>
>    Tested for kernel 2.35, 2.38 and 3.0 on Asus M2A-VM HDMI board
>

Once it's ready, just add:
Cc: stable@kernel.org
to the commit message and it will go into the stable kernels as well.
Might want to mention the bug report in your commit message as well.
Just a couple comments below.  With those fixed:

Reviewed-by: Alex Deucher <alexdeucher@gmail.com>

> Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
> ---
>  drivers/gpu/drm/drm_edid.c                 |   24 +++++++++++----
>  drivers/gpu/drm/radeon/radeon_connectors.c |   45 ++++++++++++++++++++++++++--
>  drivers/gpu/drm/radeon/radeon_device.c     |    7 ++++-
>  drivers/gpu/drm/radeon/radeon_display.c    |    9 +++++
>  drivers/gpu/drm/radeon/radeon_i2c.c        |   32 +++++++++++++++-----
>  drivers/gpu/drm/radeon/radeon_mode.h       |    6 +++-
>  include/drm/drm_crtc.h                     |    1 +
>  7 files changed, 105 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 0929219..1bbb85b 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -127,6 +127,23 @@ static const u8 edid_header[] = {
>        0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
>  };
>
> + /*
> + * Sanity check the header of the base EDID block.  Return 8 if the header
> + * is perfect, down to 0 if it's totally wrong.
> + */
> +int drm_edid_header_is_valid(const u8 *raw_edid)
> +{
> +       int i, score = 0;
> +
> +       for (i = 0; i < sizeof(edid_header); i++)
> +               if (raw_edid[i] == edid_header[i])
> +                       score++;
> +
> +       return score;
> +}
> +EXPORT_SYMBOL(drm_edid_header_is_valid);
> +
> +
>  /*
>  * Sanity check the EDID block (base or extension).  Return 0 if the block
>  * doesn't check out, or 1 if it's valid.
> @@ -139,12 +156,7 @@ drm_edid_block_valid(u8 *raw_edid)
>        struct edid *edid = (struct edid *)raw_edid;
>
>        if (raw_edid[0] == 0x00) {
> -               int score = 0;
> -
> -               for (i = 0; i < sizeof(edid_header); i++)
> -                       if (raw_edid[i] == edid_header[i])
> -                               score++;
> -
> +               int score = drm_edid_header_is_valid(raw_edid);
>                if (score == 8) ;
>                else if (score >= 6) {
>                        DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");

Might want to break this hunk out as a separate patch.

> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> index cbfca3a..2e70be2 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -424,6 +424,36 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr
>        return 0;
>  }
>
> +/*
> + * Some integrated ATI Radeon chipset implementations (e. g.
> + * Asus M2A-VM HDMI) may indicate the availability of a DDC,
> + * even when there's no monitor connected. For these connectors
> + * following DDC probe extension will be applied: check also for the
> + * availability of EDID with at least a correct EDID header. Only then,
> + * DDC is assumed to be available. This prevents drm_get_edid() and
> + * drm_edid_block_valid() from periodically dumping data and kernel
> + * errors into the logs and onto the terminal.
> + */
> +static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
> +                                    uint32_t supported_device,
> +                                    int connector_type)
> +{
> +       /* Asus M2A-VM HDMI board sends data to i2c bus even,
> +        * if HDMI add-on card is not plugged in or HDMI is disabled in
> +        * BIOS. Valid DDC can only be assumed, if also a valid EDID header
> +        * can be retrieved via i2c bus during DDC probe */
> +       if ((dev->pdev->device == 0x791e) &&
> +           (dev->pdev->subsystem_vendor == 0x1043) &&
> +           (dev->pdev->subsystem_device == 0x826d)) {
> +               if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
> +                   (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
> +                       return true;
> +       }
> +
> +       /* Default: no EDID header probe required for DDC probing */
> +       return false;
> +}
> +
>  static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
>                                          struct drm_connector *connector)
>  {
> @@ -655,7 +685,8 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
>                ret = connector_status_disconnected;
>
>        if (radeon_connector->ddc_bus)
> -               dret = radeon_ddc_probe(radeon_connector);
> +               dret = radeon_ddc_probe(radeon_connector,
> +                                       radeon_connector->requires_extended_probe);
>        if (dret) {
>                if (radeon_connector->edid) {
>                        kfree(radeon_connector->edid);
> @@ -827,7 +858,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
>        bool dret = false;
>
>        if (radeon_connector->ddc_bus)
> -               dret = radeon_ddc_probe(radeon_connector);
> +               dret = radeon_ddc_probe(radeon_connector,
> +                                       radeon_connector->requires_extended_probe);
>        if (dret) {
>                if (radeon_connector->edid) {
>                        kfree(radeon_connector->edid);
> @@ -1245,7 +1277,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
>                                if (radeon_dp_getdpcd(radeon_connector))
>                                        ret = connector_status_connected;
>                        } else {
> -                               if (radeon_ddc_probe(radeon_connector))
> +                               if (radeon_ddc_probe(radeon_connector,
> +                                                    radeon_connector->requires_extended_probe))
>                                        ret = connector_status_connected;
>                        }
>                }
> @@ -1400,6 +1433,9 @@ radeon_add_atom_connector(struct drm_device *dev,
>        radeon_connector->shared_ddc = shared_ddc;
>        radeon_connector->connector_object_id = connector_object_id;
>        radeon_connector->hpd = *hpd;
> +       radeon_connector->requires_extended_probe =
> +               radeon_connector_needs_extended_probe(rdev, supported_device,
> +                                                       connector_type);
>        radeon_connector->router = *router;
>        if (router->ddc_valid || router->cd_valid) {
>                radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
> @@ -1746,6 +1782,9 @@ radeon_add_legacy_connector(struct drm_device *dev,
>        radeon_connector->devices = supported_device;
>        radeon_connector->connector_object_id = connector_object_id;
>        radeon_connector->hpd = *hpd;
> +       radeon_connector->requires_extended_probe =
> +               radeon_connector_needs_extended_probe(rdev, supported_device,
> +                                                       connector_type);
>        switch (connector_type) {
>        case DRM_MODE_CONNECTOR_VGA:
>                drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
> diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
> index 7cfaa7e..cbdac3d 100644
> --- a/drivers/gpu/drm/radeon/radeon_device.c
> +++ b/drivers/gpu/drm/radeon/radeon_device.c
> @@ -704,8 +704,13 @@ int radeon_device_init(struct radeon_device *rdev,
>        rdev->gpu_lockup = false;
>        rdev->accel_working = false;
>
> -       DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
> +       if (pdev->subsystem_vendor == 0)
> +               DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
>                radeon_family_name[rdev->family], pdev->vendor, pdev->device);
> +       else
> +               DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n",
> +               radeon_family_name[rdev->family], pdev->vendor, pdev->device,
> +               pdev->subsystem_vendor, pdev->subsystem_device);
>

No need for the if block.  Just always print both the pci and
subsystem ids.  Also, I'd suggest making that a separate patch as it's
not related to the actual fix.


>        /* mutex initialization are all done here so we
>         * can recall function without having locking issues */
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index 292f73f..ed085ce 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -777,8 +777,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
>        if (!radeon_connector->ddc_bus)
>                return -1;
>        edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
> +       /* Log EDID retrieval status here. In particular with regard to
> +        * connectors with requires_extended_probe flag set, that will prevent
> +        * function radeon_dvi_detect() to fetch EDID on this connector,
> +        * as long as there is no valid EDID header found */
>        if (edid) {
> +               DRM_INFO("Radeon display connector %s: Found valid EDID",
> +                               drm_get_connector_name(connector));
>                kfree(edid);
> +       } else {
> +               DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
> +                               drm_get_connector_name(connector));
>        }
>        return ret;
>  }
> diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
> index 781196d..6c111c1 100644
> --- a/drivers/gpu/drm/radeon/radeon_i2c.c
> +++ b/drivers/gpu/drm/radeon/radeon_i2c.c
> @@ -32,17 +32,17 @@
>  * radeon_ddc_probe
>  *
>  */
> -bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
> +bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
>  {
> -       u8 out_buf[] = { 0x0, 0x0};
> -       u8 buf[2];
> +       u8 out = 0x0;
> +       u8 buf[8];
>        int ret;
>        struct i2c_msg msgs[] = {
>                {
>                        .addr = 0x50,
>                        .flags = 0,
>                        .len = 1,
> -                       .buf = out_buf,
> +                       .buf = &out,
>                },
>                {
>                        .addr = 0x50,
> @@ -52,15 +52,31 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
>                }
>        };
>
> +       /* Read 8 bytes from i2c for extended probe of EDID header */
> +       if (requires_extended_probe)
> +               msgs[1].len = 8;
> +
>        /* on hw with routers, select right port */
>        if (radeon_connector->router.ddc_valid)
>                radeon_router_select_ddc_port(radeon_connector);
>
>        ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
> -       if (ret == 2)
> -               return true;
> -
> -       return false;
> +       if (ret != 2)
> +               /* Couldn't find an accessible DDC on this connector */
> +               return false;
> +       if (requires_extended_probe) {
> +               /* Probe also for valid EDID header
> +                * EDID header starts with:
> +                * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
> +                * Only the first 6 bytes must be valid as
> +                * drm_edid_block_valid() can fix the last 2 bytes */
> +               if (drm_edid_header_is_valid(buf) < 6) {
> +                       /* Couldn't find an accessible EDID on this
> +                        * connector */
> +                       return false;
> +               }
> +       }
> +       return true;
>  }
>
>  /* bit banging i2c */
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index 6df4e3c..d09031c 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -438,6 +438,9 @@ struct radeon_connector {
>        struct radeon_i2c_chan *ddc_bus;
>        /* some systems have an hdmi and vga port with a shared ddc line */
>        bool shared_ddc;
> +       /* for some Radeon chip families we apply an additional EDID header
> +          check as part of the DDC probe */
> +       bool requires_extended_probe;
>        bool use_digital;
>        /* we need to mind the EDID between detect
>           and get modes due to analog/digital/tvencoder */
> @@ -514,7 +517,8 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
>                                u8 val);
>  extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
>  extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
> -extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
> +extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector,
> +                       bool requires_extended_probe);
>  extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
>
>  extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 33d12f8..0ec3687 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -802,6 +802,7 @@ extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev,
>  extern int drm_add_modes_noedid(struct drm_connector *connector,
>                                int hdisplay, int vdisplay);
>
> +extern int drm_edid_header_is_valid(const u8 *raw_edid);
>  extern bool drm_edid_is_valid(struct edid *edid);
>  struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
>                                           int hsize, int vsize, int fresh);
> --
> 1.7.1
>
>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-07-06 15:39       ` Alex Deucher
@ 2011-07-06 15:42         ` Alex Deucher
  2011-07-06 23:30           ` reimth
                           ` (3 subsequent siblings)
  4 siblings, 0 replies; 50+ messages in thread
From: Alex Deucher @ 2011-07-06 15:42 UTC (permalink / raw)
  To: reimth
  Cc: Dave Airlie, Mario Kleiner, Jean Delvare, Tyson Whitehead,
	Jason Wessel, dri-devel, linux-kernel, Thomas Reim

On Wed, Jul 6, 2011 at 11:39 AM, Alex Deucher <alexdeucher@gmail.com> wrote:
> On Wed, Jul 6, 2011 at 6:09 AM,  <reimth@googlemail.com> wrote:
>> From: Thomas Reim <rdratlos@yahoo.co.uk>
>>
>>    Some integrated ATI Radeon chipset implementations
>>    with add-on HDMI card (e. g. Asus M2A-VM HDMI) indicate the availability
>>    of a DDC even when the add-on card is not plugged in or HDMI is disabled
>>    in BIOS setup. In this case, drm_get_edid() and drm_edid_block_valid()
>>    periodically dump data and kernel errors into system log files and onto
>>    terminals. For these chipsets DDC probing is extended by a check for a
>>    correct EDID header. Only in case a valid EDID header is also found, the
>>    (HDMI) connector will be used by the Radeon driver. This prevents the
>>    kernel driver from useless flooding of logs and terminal sessions with
>>    EDID dumps and error messages.
>>    This patch adds a flag 'requires_extended_probe' to the radeon_connector
>>    structure. In function radeon_connector_needs_extended_probe() this flag
>>    can be set on a chipset family/vendor/connector type specific basis.
>>    In addition, function drm_edid_header_is_valid() has been added for EDID
>>    header check and function radeon_ddc_probe() has been adapted to perform
>>    extended DDC probing if required by the connector's flag.
>>
>>    Tested for kernel 2.35, 2.38 and 3.0 on Asus M2A-VM HDMI board
>>
>
> Once it's ready, just add:
> Cc: stable@kernel.org
> to the commit message and it will go into the stable kernels as well.
> Might want to mention the bug report in your commit message as well.
> Just a couple comments below.  With those fixed:
>
> Reviewed-by: Alex Deucher <alexdeucher@gmail.com>

We also may want to revert 4a9a8b71e12d41abb71c4e741bff524f016cfef4
once this patch goes in, otherwise we may remove the ddc bus
unnecessarily on some systems.

Alex

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH 0/3] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-07-06 15:39       ` Alex Deucher
@ 2011-07-06 23:30           ` reimth
  2011-07-06 23:30           ` reimth
                             ` (3 subsequent siblings)
  4 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-07-06 23:30 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel
  Cc: dri-devel, linux-kernel, stable, Thomas Reim

From: Thomas Reim <rdratlos@yahoo.co.uk>

Dear Alex,

> > From: Thomas Reim <rdratlos@yahoo.co.uk>
> >
> >    Some integrated ATI Radeon chipset implementations
> >    with add-on HDMI card (e. g. Asus M2A-VM HDMI) indicate the availability
> >    of a DDC even when the add-on card is not plugged in or HDMI is disabled
> >    in BIOS setup. In this case, drm_get_edid() and drm_edid_block_valid()
> >    periodically dump data and kernel errors into system log files and onto
> >    terminals. For these chipsets DDC probing is extended by a check for a
> >    correct EDID header. Only in case a valid EDID header is also found, the
> >    (HDMI) connector will be used by the Radeon driver. This prevents the
> >    kernel driver from useless flooding of logs and terminal sessions with
> >    EDID dumps and error messages.
> >    This patch adds a flag 'requires_extended_probe' to the radeon_connector
> >    structure. In function radeon_connector_needs_extended_probe() this flag
> >    can be set on a chipset family/vendor/connector type specific basis.
> >    In addition, function drm_edid_header_is_valid() has been added for EDID
> >    header check and function radeon_ddc_probe() has been adapted to perform
> >    extended DDC probing if required by the connector's flag.
> >
> >    Tested for kernel 2.35, 2.38 and 3.0 on Asus M2A-VM HDMI board
> >
> 
> Once it's ready, just add:
> Cc: stable@kernel.org
> to the commit message and it will go into the stable kernels as well.
> Might want to mention the bug report in your commit message as well.
> Just a couple comments below.  With those fixed:
> 
> Reviewed-by: Alex Deucher <alexdeucher@gmail.com>
> 
> > Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
> 
thank you for the review and your feedback. I've incorporated your comments as follows:

>  * Sanity check the EDID block (base or extension).  Return 0 if the block
> >  * doesn't check out, or 1 if it's valid.
> > @@ -139,12 +156,7 @@ drm_edid_block_valid(u8 *raw_edid)
> >        struct edid *edid = (struct edid *)raw_edid;
> >
> >        if (raw_edid[0] == 0x00) {
> > -               int score = 0;
> > -
> > -               for (i = 0; i < sizeof(edid_header); i++)
> > -                       if (raw_edid[i] == edid_header[i])
> > -                               score++;
> > -
> > +               int score = drm_edid_header_is_valid(raw_edid);
> >                if (score == 8) ;
> >                else if (score >= 6) {
> >                        DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
> 
> Might want to break this hunk out as a separate patch.

Done. Moved to [PATCH 1/3] drm: Separate EDID Header Check from EDID Block Check  

> --- a/drivers/gpu/drm/radeon/radeon_device.c
> > +++ b/drivers/gpu/drm/radeon/radeon_device.c
> > @@ -704,8 +704,13 @@ int radeon_device_init(struct radeon_device *rdev,
> >        rdev->gpu_lockup = false;
> >        rdev->accel_working = false;
> >
> > -       DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
> > +       if (pdev->subsystem_vendor == 0)
> > +               DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
> >                radeon_family_name[rdev->family], pdev->vendor, pdev->device);
> > +       else
> > +               DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n",
> > +               radeon_family_name[rdev->family], pdev->vendor, pdev->device,
> > +               pdev->subsystem_vendor, pdev->subsystem_device);
> >
> 
> No need for the if block.  Just always print both the pci and
> subsystem ids.  Also, I'd suggest making that a separate patch as it's
> not related to the actual fix.

Done. Moved to [PATCH 3/3] drm/radeon: Log Subsystem Vendor and Device Information.

The following mails will contain the three patches:
[PATCH 1/3] drm: Separate EDID Header Check from EDID Block Check
[PATCH 2/3] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
[PATCH 3/3] drm/radeon: Log Subsystem Vendor and Device Information

[PATCH 2/3] requires [PATCH 1/3] (new function drm_edid_header_is_valid). [PATCH 3/3] 
is an add-on that helps people to identify also the subsystem vendor and device PCI ID 
of a Radeon chipset within the kernel log. So all information that is needed to include 
Radeon implementations other than Asus M2A-VM HDMI for extended DDC probing should now 
be available in dmesg. 

The patches were generated against revision 'Linux 3.0-rc6' in Linux kernel git repository.

Best regards

Thomas Reim


Thomas Reim (3):
  drm: Separate EDID Header Check from EDID Block Check
  drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  drm/radeon: Log Subsystem Vendor and Device Information

 drivers/gpu/drm/drm_edid.c                 |   24 +++++++++++----
 drivers/gpu/drm/radeon/radeon_connectors.c |   45 ++++++++++++++++++++++++++--
 drivers/gpu/drm/radeon/radeon_device.c     |    5 ++-
 drivers/gpu/drm/radeon/radeon_display.c    |    9 +++++
 drivers/gpu/drm/radeon/radeon_i2c.c        |   32 +++++++++++++++-----
 drivers/gpu/drm/radeon/radeon_mode.h       |    6 +++-
 include/drm/drm_crtc.h                     |    1 +
 7 files changed, 102 insertions(+), 20 deletions(-)


^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH 0/3] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
@ 2011-07-06 23:30           ` reimth
  0 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-07-06 23:30 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare, Tyson Whitehead
  Cc: Thomas Reim, linux-kernel, dri-devel, stable

From: Thomas Reim <rdratlos@yahoo.co.uk>

Dear Alex,

> > From: Thomas Reim <rdratlos@yahoo.co.uk>
> >
> >    Some integrated ATI Radeon chipset implementations
> >    with add-on HDMI card (e. g. Asus M2A-VM HDMI) indicate the availability
> >    of a DDC even when the add-on card is not plugged in or HDMI is disabled
> >    in BIOS setup. In this case, drm_get_edid() and drm_edid_block_valid()
> >    periodically dump data and kernel errors into system log files and onto
> >    terminals. For these chipsets DDC probing is extended by a check for a
> >    correct EDID header. Only in case a valid EDID header is also found, the
> >    (HDMI) connector will be used by the Radeon driver. This prevents the
> >    kernel driver from useless flooding of logs and terminal sessions with
> >    EDID dumps and error messages.
> >    This patch adds a flag 'requires_extended_probe' to the radeon_connector
> >    structure. In function radeon_connector_needs_extended_probe() this flag
> >    can be set on a chipset family/vendor/connector type specific basis.
> >    In addition, function drm_edid_header_is_valid() has been added for EDID
> >    header check and function radeon_ddc_probe() has been adapted to perform
> >    extended DDC probing if required by the connector's flag.
> >
> >    Tested for kernel 2.35, 2.38 and 3.0 on Asus M2A-VM HDMI board
> >
> 
> Once it's ready, just add:
> Cc: stable@kernel.org
> to the commit message and it will go into the stable kernels as well.
> Might want to mention the bug report in your commit message as well.
> Just a couple comments below.  With those fixed:
> 
> Reviewed-by: Alex Deucher <alexdeucher@gmail.com>
> 
> > Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
> 
thank you for the review and your feedback. I've incorporated your comments as follows:

>  * Sanity check the EDID block (base or extension).  Return 0 if the block
> >  * doesn't check out, or 1 if it's valid.
> > @@ -139,12 +156,7 @@ drm_edid_block_valid(u8 *raw_edid)
> >        struct edid *edid = (struct edid *)raw_edid;
> >
> >        if (raw_edid[0] == 0x00) {
> > -               int score = 0;
> > -
> > -               for (i = 0; i < sizeof(edid_header); i++)
> > -                       if (raw_edid[i] == edid_header[i])
> > -                               score++;
> > -
> > +               int score = drm_edid_header_is_valid(raw_edid);
> >                if (score == 8) ;
> >                else if (score >= 6) {
> >                        DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
> 
> Might want to break this hunk out as a separate patch.

Done. Moved to [PATCH 1/3] drm: Separate EDID Header Check from EDID Block Check  

> --- a/drivers/gpu/drm/radeon/radeon_device.c
> > +++ b/drivers/gpu/drm/radeon/radeon_device.c
> > @@ -704,8 +704,13 @@ int radeon_device_init(struct radeon_device *rdev,
> >        rdev->gpu_lockup = false;
> >        rdev->accel_working = false;
> >
> > -       DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
> > +       if (pdev->subsystem_vendor == 0)
> > +               DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
> >                radeon_family_name[rdev->family], pdev->vendor, pdev->device);
> > +       else
> > +               DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n",
> > +               radeon_family_name[rdev->family], pdev->vendor, pdev->device,
> > +               pdev->subsystem_vendor, pdev->subsystem_device);
> >
> 
> No need for the if block.  Just always print both the pci and
> subsystem ids.  Also, I'd suggest making that a separate patch as it's
> not related to the actual fix.

Done. Moved to [PATCH 3/3] drm/radeon: Log Subsystem Vendor and Device Information.

The following mails will contain the three patches:
[PATCH 1/3] drm: Separate EDID Header Check from EDID Block Check
[PATCH 2/3] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
[PATCH 3/3] drm/radeon: Log Subsystem Vendor and Device Information

[PATCH 2/3] requires [PATCH 1/3] (new function drm_edid_header_is_valid). [PATCH 3/3] 
is an add-on that helps people to identify also the subsystem vendor and device PCI ID 
of a Radeon chipset within the kernel log. So all information that is needed to include 
Radeon implementations other than Asus M2A-VM HDMI for extended DDC probing should now 
be available in dmesg. 

The patches were generated against revision 'Linux 3.0-rc6' in Linux kernel git repository.

Best regards

Thomas Reim


Thomas Reim (3):
  drm: Separate EDID Header Check from EDID Block Check
  drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  drm/radeon: Log Subsystem Vendor and Device Information

 drivers/gpu/drm/drm_edid.c                 |   24 +++++++++++----
 drivers/gpu/drm/radeon/radeon_connectors.c |   45 ++++++++++++++++++++++++++--
 drivers/gpu/drm/radeon/radeon_device.c     |    5 ++-
 drivers/gpu/drm/radeon/radeon_display.c    |    9 +++++
 drivers/gpu/drm/radeon/radeon_i2c.c        |   32 +++++++++++++++-----
 drivers/gpu/drm/radeon/radeon_mode.h       |    6 +++-
 include/drm/drm_crtc.h                     |    1 +
 7 files changed, 102 insertions(+), 20 deletions(-)

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH 3/3] drm/radeon: Log Subsystem Vendor and Device Information
  2011-07-06 15:39       ` Alex Deucher
@ 2011-07-06 23:30           ` reimth
  2011-07-06 23:30           ` reimth
                             ` (3 subsequent siblings)
  4 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-07-06 23:30 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel
  Cc: dri-devel, linux-kernel, stable, Thomas Reim

From: Thomas Reim <rdratlos@yahoo.co.uk>

    Log PCI subsystem vendor and subsystem device ID in addition to
    PCI vendor and device ID during kernel mode initialisation. This helps
    to better identify radeon devices of third-party vendors, e. g. for
    bug analysis.

    Tested for kernel 2.35, 2.38 and 3.0 on Asus M2A-VM HDMI board

Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
---
 drivers/gpu/drm/radeon/radeon_device.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 7cfaa7e..440e6ec 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -704,8 +704,9 @@ int radeon_device_init(struct radeon_device *rdev,
 	rdev->gpu_lockup = false;
 	rdev->accel_working = false;
 
-	DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
-		radeon_family_name[rdev->family], pdev->vendor, pdev->device);
+	DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n",
+		radeon_family_name[rdev->family], pdev->vendor, pdev->device,
+		pdev->subsystem_vendor, pdev->subsystem_device);
 
 	/* mutex initialization are all done here so we
 	 * can recall function without having locking issues */
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 3/3] drm/radeon: Log Subsystem Vendor and Device Information
@ 2011-07-06 23:30           ` reimth
  0 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-07-06 23:30 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare, Tyson Whitehead
  Cc: dri-devel, linux-kernel, stable, Thomas Reim

From: Thomas Reim <rdratlos@yahoo.co.uk>

    Log PCI subsystem vendor and subsystem device ID in addition to
    PCI vendor and device ID during kernel mode initialisation. This helps
    to better identify radeon devices of third-party vendors, e. g. for
    bug analysis.

    Tested for kernel 2.35, 2.38 and 3.0 on Asus M2A-VM HDMI board

Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
---
 drivers/gpu/drm/radeon/radeon_device.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 7cfaa7e..440e6ec 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -704,8 +704,9 @@ int radeon_device_init(struct radeon_device *rdev,
 	rdev->gpu_lockup = false;
 	rdev->accel_working = false;
 
-	DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
-		radeon_family_name[rdev->family], pdev->vendor, pdev->device);
+	DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n",
+		radeon_family_name[rdev->family], pdev->vendor, pdev->device,
+		pdev->subsystem_vendor, pdev->subsystem_device);
 
 	/* mutex initialization are all done here so we
 	 * can recall function without having locking issues */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 2/3] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-07-06 15:39       ` Alex Deucher
@ 2011-07-06 23:30           ` reimth
  2011-07-06 23:30           ` reimth
                             ` (3 subsequent siblings)
  4 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-07-06 23:30 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel
  Cc: dri-devel, linux-kernel, stable, Thomas Reim

From: Thomas Reim <rdratlos@yahoo.co.uk>

    Fixes bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/722806:
    Some integrated ATI Radeon chipset implementations with add-on HDMI card
    (e. g. Asus M2A-VM HDMI) indicate the availability of a DDC even
    when the add-on card is not plugged in or HDMI is disabled in BIOS setup.
    In this case, drm_get_edid() and drm_edid_block_valid() periodically
    dump data and kernel errors into system log files and onto terminals.
    For these chipsets DDC probing is extended by a check for a correct
    EDID header. Only in case a valid EDID header is also found, the
    (HDMI) connector will be used by the Radeon driver. This prevents the
    kernel driver from useless flooding of logs and terminal sessions with
    EDID dumps and error messages.
    This patch adds a flag 'requires_extended_probe' to the radeon_connector
    structure. In function radeon_connector_needs_extended_probe() this flag
    can be set on a chipset family/vendor/connector type specific basis.
    In addition, function radeon_ddc_probe() has been adapted to perform
    extended DDC probing if required by the connector's flag.
    Requires function drm_edid_header_is_valid() in DRM module provided by
    [PATCH] drm: Separate EDID Header Check from EDID Block Check.

    Tested for kernel 2.35, 2.38 and 3.0 on Asus M2A-VM HDMI board

Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
---
 drivers/gpu/drm/radeon/radeon_connectors.c |   45 ++++++++++++++++++++++++++--
 drivers/gpu/drm/radeon/radeon_display.c    |    9 +++++
 drivers/gpu/drm/radeon/radeon_i2c.c        |   32 +++++++++++++++-----
 drivers/gpu/drm/radeon/radeon_mode.h       |    6 +++-
 4 files changed, 80 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index cbfca3a..2e70be2 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -424,6 +424,36 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr
 	return 0;
 }
 
+/*
+ * Some integrated ATI Radeon chipset implementations (e. g.
+ * Asus M2A-VM HDMI) may indicate the availability of a DDC,
+ * even when there's no monitor connected. For these connectors
+ * following DDC probe extension will be applied: check also for the
+ * availability of EDID with at least a correct EDID header. Only then,
+ * DDC is assumed to be available. This prevents drm_get_edid() and
+ * drm_edid_block_valid() from periodically dumping data and kernel
+ * errors into the logs and onto the terminal.
+ */
+static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
+				     uint32_t supported_device,
+				     int connector_type)
+{
+	/* Asus M2A-VM HDMI board sends data to i2c bus even,
+	 * if HDMI add-on card is not plugged in or HDMI is disabled in
+	 * BIOS. Valid DDC can only be assumed, if also a valid EDID header
+	 * can be retrieved via i2c bus during DDC probe */
+	if ((dev->pdev->device == 0x791e) &&
+	    (dev->pdev->subsystem_vendor == 0x1043) &&
+	    (dev->pdev->subsystem_device == 0x826d)) {
+		if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
+		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
+			return true;
+	}
+
+	/* Default: no EDID header probe required for DDC probing */
+	return false;
+}
+
 static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
 					  struct drm_connector *connector)
 {
@@ -655,7 +685,8 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
 		ret = connector_status_disconnected;
 
 	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector);
+		dret = radeon_ddc_probe(radeon_connector,
+					radeon_connector->requires_extended_probe);
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
@@ -827,7 +858,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 	bool dret = false;
 
 	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector);
+		dret = radeon_ddc_probe(radeon_connector,
+					radeon_connector->requires_extended_probe);
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
@@ -1245,7 +1277,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
 				if (radeon_dp_getdpcd(radeon_connector))
 					ret = connector_status_connected;
 			} else {
-				if (radeon_ddc_probe(radeon_connector))
+				if (radeon_ddc_probe(radeon_connector,
+						     radeon_connector->requires_extended_probe))
 					ret = connector_status_connected;
 			}
 		}
@@ -1400,6 +1433,9 @@ radeon_add_atom_connector(struct drm_device *dev,
 	radeon_connector->shared_ddc = shared_ddc;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
+	radeon_connector->requires_extended_probe =
+		radeon_connector_needs_extended_probe(rdev, supported_device,
+							connector_type);
 	radeon_connector->router = *router;
 	if (router->ddc_valid || router->cd_valid) {
 		radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
@@ -1746,6 +1782,9 @@ radeon_add_legacy_connector(struct drm_device *dev,
 	radeon_connector->devices = supported_device;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
+	radeon_connector->requires_extended_probe =
+		radeon_connector_needs_extended_probe(rdev, supported_device,
+							connector_type);
 	switch (connector_type) {
 	case DRM_MODE_CONNECTOR_VGA:
 		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 292f73f..ed085ce 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -777,8 +777,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
 	if (!radeon_connector->ddc_bus)
 		return -1;
 	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
+	/* Log EDID retrieval status here. In particular with regard to
+	 * connectors with requires_extended_probe flag set, that will prevent
+	 * function radeon_dvi_detect() to fetch EDID on this connector,
+	 * as long as there is no valid EDID header found */
 	if (edid) {
+		DRM_INFO("Radeon display connector %s: Found valid EDID",
+				drm_get_connector_name(connector));
 		kfree(edid);
+	} else {
+		DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
+				drm_get_connector_name(connector));
 	}
 	return ret;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 781196d..6c111c1 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -32,17 +32,17 @@
  * radeon_ddc_probe
  *
  */
-bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
+bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
 {
-	u8 out_buf[] = { 0x0, 0x0};
-	u8 buf[2];
+	u8 out = 0x0;
+	u8 buf[8];
 	int ret;
 	struct i2c_msg msgs[] = {
 		{
 			.addr = 0x50,
 			.flags = 0,
 			.len = 1,
-			.buf = out_buf,
+			.buf = &out,
 		},
 		{
 			.addr = 0x50,
@@ -52,15 +52,31 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 		}
 	};
 
+	/* Read 8 bytes from i2c for extended probe of EDID header */
+	if (requires_extended_probe)
+		msgs[1].len = 8;
+
 	/* on hw with routers, select right port */
 	if (radeon_connector->router.ddc_valid)
 		radeon_router_select_ddc_port(radeon_connector);
 
 	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
-	if (ret == 2)
-		return true;
-
-	return false;
+	if (ret != 2)
+		/* Couldn't find an accessible DDC on this connector */
+		return false;
+	if (requires_extended_probe) {
+		/* Probe also for valid EDID header
+		 * EDID header starts with:
+		 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
+		 * Only the first 6 bytes must be valid as
+		 * drm_edid_block_valid() can fix the last 2 bytes */
+		if (drm_edid_header_is_valid(buf) < 6) {
+			/* Couldn't find an accessible EDID on this
+			 * connector */
+			return false;
+		}
+	}
+	return true;
 }
 
 /* bit banging i2c */
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 6df4e3c..d09031c 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -438,6 +438,9 @@ struct radeon_connector {
 	struct radeon_i2c_chan *ddc_bus;
 	/* some systems have an hdmi and vga port with a shared ddc line */
 	bool shared_ddc;
+	/* for some Radeon chip families we apply an additional EDID header
+	   check as part of the DDC probe */
+	bool requires_extended_probe;
 	bool use_digital;
 	/* we need to mind the EDID between detect
 	   and get modes due to analog/digital/tvencoder */
@@ -514,7 +517,8 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
 				u8 val);
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
-extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
+extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector,
+			bool requires_extended_probe);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 2/3] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
@ 2011-07-06 23:30           ` reimth
  0 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-07-06 23:30 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare, Tyson Whitehead
  Cc: dri-devel, linux-kernel, stable, Thomas Reim

From: Thomas Reim <rdratlos@yahoo.co.uk>

    Fixes bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/722806:
    Some integrated ATI Radeon chipset implementations with add-on HDMI card
    (e. g. Asus M2A-VM HDMI) indicate the availability of a DDC even
    when the add-on card is not plugged in or HDMI is disabled in BIOS setup.
    In this case, drm_get_edid() and drm_edid_block_valid() periodically
    dump data and kernel errors into system log files and onto terminals.
    For these chipsets DDC probing is extended by a check for a correct
    EDID header. Only in case a valid EDID header is also found, the
    (HDMI) connector will be used by the Radeon driver. This prevents the
    kernel driver from useless flooding of logs and terminal sessions with
    EDID dumps and error messages.
    This patch adds a flag 'requires_extended_probe' to the radeon_connector
    structure. In function radeon_connector_needs_extended_probe() this flag
    can be set on a chipset family/vendor/connector type specific basis.
    In addition, function radeon_ddc_probe() has been adapted to perform
    extended DDC probing if required by the connector's flag.
    Requires function drm_edid_header_is_valid() in DRM module provided by
    [PATCH] drm: Separate EDID Header Check from EDID Block Check.

    Tested for kernel 2.35, 2.38 and 3.0 on Asus M2A-VM HDMI board

Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
---
 drivers/gpu/drm/radeon/radeon_connectors.c |   45 ++++++++++++++++++++++++++--
 drivers/gpu/drm/radeon/radeon_display.c    |    9 +++++
 drivers/gpu/drm/radeon/radeon_i2c.c        |   32 +++++++++++++++-----
 drivers/gpu/drm/radeon/radeon_mode.h       |    6 +++-
 4 files changed, 80 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index cbfca3a..2e70be2 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -424,6 +424,36 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr
 	return 0;
 }
 
+/*
+ * Some integrated ATI Radeon chipset implementations (e. g.
+ * Asus M2A-VM HDMI) may indicate the availability of a DDC,
+ * even when there's no monitor connected. For these connectors
+ * following DDC probe extension will be applied: check also for the
+ * availability of EDID with at least a correct EDID header. Only then,
+ * DDC is assumed to be available. This prevents drm_get_edid() and
+ * drm_edid_block_valid() from periodically dumping data and kernel
+ * errors into the logs and onto the terminal.
+ */
+static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
+				     uint32_t supported_device,
+				     int connector_type)
+{
+	/* Asus M2A-VM HDMI board sends data to i2c bus even,
+	 * if HDMI add-on card is not plugged in or HDMI is disabled in
+	 * BIOS. Valid DDC can only be assumed, if also a valid EDID header
+	 * can be retrieved via i2c bus during DDC probe */
+	if ((dev->pdev->device == 0x791e) &&
+	    (dev->pdev->subsystem_vendor == 0x1043) &&
+	    (dev->pdev->subsystem_device == 0x826d)) {
+		if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
+		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
+			return true;
+	}
+
+	/* Default: no EDID header probe required for DDC probing */
+	return false;
+}
+
 static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
 					  struct drm_connector *connector)
 {
@@ -655,7 +685,8 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
 		ret = connector_status_disconnected;
 
 	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector);
+		dret = radeon_ddc_probe(radeon_connector,
+					radeon_connector->requires_extended_probe);
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
@@ -827,7 +858,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 	bool dret = false;
 
 	if (radeon_connector->ddc_bus)
-		dret = radeon_ddc_probe(radeon_connector);
+		dret = radeon_ddc_probe(radeon_connector,
+					radeon_connector->requires_extended_probe);
 	if (dret) {
 		if (radeon_connector->edid) {
 			kfree(radeon_connector->edid);
@@ -1245,7 +1277,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
 				if (radeon_dp_getdpcd(radeon_connector))
 					ret = connector_status_connected;
 			} else {
-				if (radeon_ddc_probe(radeon_connector))
+				if (radeon_ddc_probe(radeon_connector,
+						     radeon_connector->requires_extended_probe))
 					ret = connector_status_connected;
 			}
 		}
@@ -1400,6 +1433,9 @@ radeon_add_atom_connector(struct drm_device *dev,
 	radeon_connector->shared_ddc = shared_ddc;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
+	radeon_connector->requires_extended_probe =
+		radeon_connector_needs_extended_probe(rdev, supported_device,
+							connector_type);
 	radeon_connector->router = *router;
 	if (router->ddc_valid || router->cd_valid) {
 		radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
@@ -1746,6 +1782,9 @@ radeon_add_legacy_connector(struct drm_device *dev,
 	radeon_connector->devices = supported_device;
 	radeon_connector->connector_object_id = connector_object_id;
 	radeon_connector->hpd = *hpd;
+	radeon_connector->requires_extended_probe =
+		radeon_connector_needs_extended_probe(rdev, supported_device,
+							connector_type);
 	switch (connector_type) {
 	case DRM_MODE_CONNECTOR_VGA:
 		drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 292f73f..ed085ce 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -777,8 +777,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
 	if (!radeon_connector->ddc_bus)
 		return -1;
 	edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
+	/* Log EDID retrieval status here. In particular with regard to
+	 * connectors with requires_extended_probe flag set, that will prevent
+	 * function radeon_dvi_detect() to fetch EDID on this connector,
+	 * as long as there is no valid EDID header found */
 	if (edid) {
+		DRM_INFO("Radeon display connector %s: Found valid EDID",
+				drm_get_connector_name(connector));
 		kfree(edid);
+	} else {
+		DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
+				drm_get_connector_name(connector));
 	}
 	return ret;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 781196d..6c111c1 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -32,17 +32,17 @@
  * radeon_ddc_probe
  *
  */
-bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
+bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
 {
-	u8 out_buf[] = { 0x0, 0x0};
-	u8 buf[2];
+	u8 out = 0x0;
+	u8 buf[8];
 	int ret;
 	struct i2c_msg msgs[] = {
 		{
 			.addr = 0x50,
 			.flags = 0,
 			.len = 1,
-			.buf = out_buf,
+			.buf = &out,
 		},
 		{
 			.addr = 0x50,
@@ -52,15 +52,31 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
 		}
 	};
 
+	/* Read 8 bytes from i2c for extended probe of EDID header */
+	if (requires_extended_probe)
+		msgs[1].len = 8;
+
 	/* on hw with routers, select right port */
 	if (radeon_connector->router.ddc_valid)
 		radeon_router_select_ddc_port(radeon_connector);
 
 	ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
-	if (ret == 2)
-		return true;
-
-	return false;
+	if (ret != 2)
+		/* Couldn't find an accessible DDC on this connector */
+		return false;
+	if (requires_extended_probe) {
+		/* Probe also for valid EDID header
+		 * EDID header starts with:
+		 * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
+		 * Only the first 6 bytes must be valid as
+		 * drm_edid_block_valid() can fix the last 2 bytes */
+		if (drm_edid_header_is_valid(buf) < 6) {
+			/* Couldn't find an accessible EDID on this
+			 * connector */
+			return false;
+		}
+	}
+	return true;
 }
 
 /* bit banging i2c */
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 6df4e3c..d09031c 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -438,6 +438,9 @@ struct radeon_connector {
 	struct radeon_i2c_chan *ddc_bus;
 	/* some systems have an hdmi and vga port with a shared ddc line */
 	bool shared_ddc;
+	/* for some Radeon chip families we apply an additional EDID header
+	   check as part of the DDC probe */
+	bool requires_extended_probe;
 	bool use_digital;
 	/* we need to mind the EDID between detect
 	   and get modes due to analog/digital/tvencoder */
@@ -514,7 +517,8 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
 				u8 val);
 extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
 extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
-extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
+extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector,
+			bool requires_extended_probe);
 extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
 
 extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 1/3] drm: Separate EDID Header Check from EDID Block Check
  2011-07-06 15:39       ` Alex Deucher
@ 2011-07-06 23:30           ` reimth
  2011-07-06 23:30           ` reimth
                             ` (3 subsequent siblings)
  4 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-07-06 23:30 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel
  Cc: dri-devel, linux-kernel, stable, Thomas Reim

From: Thomas Reim <rdratlos@yahoo.co.uk>

    Provides function drm_edid_header_is_valid() for EDID header check
    and replaces EDID header check part of function drm_edid_block_valid()
    by a call of drm_edid_header_is_valid().
    This is a prerequisite to extend DDC probing, e. g. in function
    radeon_ddc_probe() for Radeon devices, by a central EDID header check.

    Tested for kernel 2.35, 2.38 and 3.0

Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
---
 drivers/gpu/drm/drm_edid.c |   24 ++++++++++++++++++------
 include/drm/drm_crtc.h     |    1 +
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 0929219..1bbb85b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -127,6 +127,23 @@ static const u8 edid_header[] = {
 	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
 };
 
+ /*
+ * Sanity check the header of the base EDID block.  Return 8 if the header
+ * is perfect, down to 0 if it's totally wrong.
+ */
+int drm_edid_header_is_valid(const u8 *raw_edid)
+{
+	int i, score = 0;
+
+	for (i = 0; i < sizeof(edid_header); i++)
+		if (raw_edid[i] == edid_header[i])
+			score++;
+
+	return score;
+}
+EXPORT_SYMBOL(drm_edid_header_is_valid);
+
+
 /*
  * Sanity check the EDID block (base or extension).  Return 0 if the block
  * doesn't check out, or 1 if it's valid.
@@ -139,12 +156,7 @@ drm_edid_block_valid(u8 *raw_edid)
 	struct edid *edid = (struct edid *)raw_edid;
 
 	if (raw_edid[0] == 0x00) {
-		int score = 0;
-
-		for (i = 0; i < sizeof(edid_header); i++)
-			if (raw_edid[i] == edid_header[i])
-				score++;
-
+		int score = drm_edid_header_is_valid(raw_edid);
 		if (score == 8) ;
 		else if (score >= 6) {
 			DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 33d12f8..0ec3687 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -802,6 +802,7 @@ extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev,
 extern int drm_add_modes_noedid(struct drm_connector *connector,
 				int hdisplay, int vdisplay);
 
+extern int drm_edid_header_is_valid(const u8 *raw_edid);
 extern bool drm_edid_is_valid(struct edid *edid);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
 					   int hsize, int vsize, int fresh);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 1/3] drm: Separate EDID Header Check from EDID Block Check
@ 2011-07-06 23:30           ` reimth
  0 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-07-06 23:30 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare, Tyson Whitehead
  Cc: dri-devel, linux-kernel, stable, Thomas Reim

From: Thomas Reim <rdratlos@yahoo.co.uk>

    Provides function drm_edid_header_is_valid() for EDID header check
    and replaces EDID header check part of function drm_edid_block_valid()
    by a call of drm_edid_header_is_valid().
    This is a prerequisite to extend DDC probing, e. g. in function
    radeon_ddc_probe() for Radeon devices, by a central EDID header check.

    Tested for kernel 2.35, 2.38 and 3.0

Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
---
 drivers/gpu/drm/drm_edid.c |   24 ++++++++++++++++++------
 include/drm/drm_crtc.h     |    1 +
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 0929219..1bbb85b 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -127,6 +127,23 @@ static const u8 edid_header[] = {
 	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
 };
 
+ /*
+ * Sanity check the header of the base EDID block.  Return 8 if the header
+ * is perfect, down to 0 if it's totally wrong.
+ */
+int drm_edid_header_is_valid(const u8 *raw_edid)
+{
+	int i, score = 0;
+
+	for (i = 0; i < sizeof(edid_header); i++)
+		if (raw_edid[i] == edid_header[i])
+			score++;
+
+	return score;
+}
+EXPORT_SYMBOL(drm_edid_header_is_valid);
+
+
 /*
  * Sanity check the EDID block (base or extension).  Return 0 if the block
  * doesn't check out, or 1 if it's valid.
@@ -139,12 +156,7 @@ drm_edid_block_valid(u8 *raw_edid)
 	struct edid *edid = (struct edid *)raw_edid;
 
 	if (raw_edid[0] == 0x00) {
-		int score = 0;
-
-		for (i = 0; i < sizeof(edid_header); i++)
-			if (raw_edid[i] == edid_header[i])
-				score++;
-
+		int score = drm_edid_header_is_valid(raw_edid);
 		if (score == 8) ;
 		else if (score >= 6) {
 			DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 33d12f8..0ec3687 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -802,6 +802,7 @@ extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev,
 extern int drm_add_modes_noedid(struct drm_connector *connector,
 				int hdisplay, int vdisplay);
 
+extern int drm_edid_header_is_valid(const u8 *raw_edid);
 extern bool drm_edid_is_valid(struct edid *edid);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
 					   int hsize, int vsize, int fresh);
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [stable] [PATCH 1/3] drm: Separate EDID Header Check from EDID Block Check
  2011-07-06 23:30           ` reimth
  (?)
@ 2011-07-06 23:56           ` Greg KH
  -1 siblings, 0 replies; 50+ messages in thread
From: Greg KH @ 2011-07-06 23:56 UTC (permalink / raw)
  To: reimth
  Cc: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel, Thomas Reim, linux-kernel,
	dri-devel, stable

On Thu, Jul 07, 2011 at 01:30:12AM +0200, reimth@googlemail.com wrote:
> From: Thomas Reim <rdratlos@yahoo.co.uk>
> 
>     Provides function drm_edid_header_is_valid() for EDID header check
>     and replaces EDID header check part of function drm_edid_block_valid()
>     by a call of drm_edid_header_is_valid().
>     This is a prerequisite to extend DDC probing, e. g. in function
>     radeon_ddc_probe() for Radeon devices, by a central EDID header check.
> 
>     Tested for kernel 2.35, 2.38 and 3.0
> 
> Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>
> ---
>  drivers/gpu/drm/drm_edid.c |   24 ++++++++++++++++++------
>  include/drm/drm_crtc.h     |    1 +
>  2 files changed, 19 insertions(+), 6 deletions(-)

<formletter>

This is not the correct way to submit patches for inclusion in the
stable kernel tree.  Please read Documentation/stable_kernel_rules.txt
for how to do this properly.

</formletter>

Same goes for 2/3 and 3/3 as well.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 3/3] drm/radeon: Log Subsystem Vendor and Device Information
  2011-07-06 23:30           ` reimth
  (?)
@ 2011-07-07 13:56           ` Alex Deucher
  -1 siblings, 0 replies; 50+ messages in thread
From: Alex Deucher @ 2011-07-07 13:56 UTC (permalink / raw)
  To: reimth
  Cc: Dave Airlie, Mario Kleiner, Jean Delvare, Tyson Whitehead,
	Jason Wessel, dri-devel, linux-kernel, stable, Thomas Reim

On Wed, Jul 6, 2011 at 7:30 PM,  <reimth@googlemail.com> wrote:
> From: Thomas Reim <rdratlos@yahoo.co.uk>
>
>    Log PCI subsystem vendor and subsystem device ID in addition to
>    PCI vendor and device ID during kernel mode initialisation. This helps
>    to better identify radeon devices of third-party vendors, e. g. for
>    bug analysis.
>
>    Tested for kernel 2.35, 2.38 and 3.0 on Asus M2A-VM HDMI board
>
> Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>

Reviewed-by: Alex Deucher <alexdeucher@gmail.com>

> ---
>  drivers/gpu/drm/radeon/radeon_device.c |    5 +++--
>  1 files changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
> index 7cfaa7e..440e6ec 100644
> --- a/drivers/gpu/drm/radeon/radeon_device.c
> +++ b/drivers/gpu/drm/radeon/radeon_device.c
> @@ -704,8 +704,9 @@ int radeon_device_init(struct radeon_device *rdev,
>        rdev->gpu_lockup = false;
>        rdev->accel_working = false;
>
> -       DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
> -               radeon_family_name[rdev->family], pdev->vendor, pdev->device);
> +       DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n",
> +               radeon_family_name[rdev->family], pdev->vendor, pdev->device,
> +               pdev->subsystem_vendor, pdev->subsystem_device);
>
>        /* mutex initialization are all done here so we
>         * can recall function without having locking issues */
> --
> 1.7.1
>
>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 1/3] drm: Separate EDID Header Check from EDID Block Check
  2011-07-06 23:30           ` reimth
  (?)
  (?)
@ 2011-07-07 13:57           ` Alex Deucher
  -1 siblings, 0 replies; 50+ messages in thread
From: Alex Deucher @ 2011-07-07 13:57 UTC (permalink / raw)
  To: reimth
  Cc: Dave Airlie, Mario Kleiner, Jean Delvare, Tyson Whitehead,
	Jason Wessel, dri-devel, linux-kernel, Thomas Reim

On Wed, Jul 6, 2011 at 7:30 PM,  <reimth@googlemail.com> wrote:
> From: Thomas Reim <rdratlos@yahoo.co.uk>
>
>    Provides function drm_edid_header_is_valid() for EDID header check
>    and replaces EDID header check part of function drm_edid_block_valid()
>    by a call of drm_edid_header_is_valid().
>    This is a prerequisite to extend DDC probing, e. g. in function
>    radeon_ddc_probe() for Radeon devices, by a central EDID header check.
>
>    Tested for kernel 2.35, 2.38 and 3.0
>
> Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>

Reviewed-by: Alex Deucher <alexdeucher@gmail.com>

> ---
>  drivers/gpu/drm/drm_edid.c |   24 ++++++++++++++++++------
>  include/drm/drm_crtc.h     |    1 +
>  2 files changed, 19 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index 0929219..1bbb85b 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -127,6 +127,23 @@ static const u8 edid_header[] = {
>        0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
>  };
>
> + /*
> + * Sanity check the header of the base EDID block.  Return 8 if the header
> + * is perfect, down to 0 if it's totally wrong.
> + */
> +int drm_edid_header_is_valid(const u8 *raw_edid)
> +{
> +       int i, score = 0;
> +
> +       for (i = 0; i < sizeof(edid_header); i++)
> +               if (raw_edid[i] == edid_header[i])
> +                       score++;
> +
> +       return score;
> +}
> +EXPORT_SYMBOL(drm_edid_header_is_valid);
> +
> +
>  /*
>  * Sanity check the EDID block (base or extension).  Return 0 if the block
>  * doesn't check out, or 1 if it's valid.
> @@ -139,12 +156,7 @@ drm_edid_block_valid(u8 *raw_edid)
>        struct edid *edid = (struct edid *)raw_edid;
>
>        if (raw_edid[0] == 0x00) {
> -               int score = 0;
> -
> -               for (i = 0; i < sizeof(edid_header); i++)
> -                       if (raw_edid[i] == edid_header[i])
> -                               score++;
> -
> +               int score = drm_edid_header_is_valid(raw_edid);
>                if (score == 8) ;
>                else if (score >= 6) {
>                        DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 33d12f8..0ec3687 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -802,6 +802,7 @@ extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev,
>  extern int drm_add_modes_noedid(struct drm_connector *connector,
>                                int hdisplay, int vdisplay);
>
> +extern int drm_edid_header_is_valid(const u8 *raw_edid);
>  extern bool drm_edid_is_valid(struct edid *edid);
>  struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
>                                           int hsize, int vsize, int fresh);
> --
> 1.7.1
>
>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 2/3] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-07-06 23:30           ` reimth
  (?)
@ 2011-07-07 14:01           ` Alex Deucher
  2011-07-26 13:20             ` Dave Airlie
  -1 siblings, 1 reply; 50+ messages in thread
From: Alex Deucher @ 2011-07-07 14:01 UTC (permalink / raw)
  To: reimth
  Cc: Dave Airlie, Mario Kleiner, Jean Delvare, Tyson Whitehead,
	Jason Wessel, dri-devel, linux-kernel, stable, Thomas Reim

On Wed, Jul 6, 2011 at 7:30 PM,  <reimth@googlemail.com> wrote:
> From: Thomas Reim <rdratlos@yahoo.co.uk>
>
>    Fixes bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/722806:
>    Some integrated ATI Radeon chipset implementations with add-on HDMI card
>    (e. g. Asus M2A-VM HDMI) indicate the availability of a DDC even
>    when the add-on card is not plugged in or HDMI is disabled in BIOS setup.
>    In this case, drm_get_edid() and drm_edid_block_valid() periodically
>    dump data and kernel errors into system log files and onto terminals.
>    For these chipsets DDC probing is extended by a check for a correct
>    EDID header. Only in case a valid EDID header is also found, the
>    (HDMI) connector will be used by the Radeon driver. This prevents the
>    kernel driver from useless flooding of logs and terminal sessions with
>    EDID dumps and error messages.
>    This patch adds a flag 'requires_extended_probe' to the radeon_connector
>    structure. In function radeon_connector_needs_extended_probe() this flag
>    can be set on a chipset family/vendor/connector type specific basis.
>    In addition, function radeon_ddc_probe() has been adapted to perform
>    extended DDC probing if required by the connector's flag.
>    Requires function drm_edid_header_is_valid() in DRM module provided by
>    [PATCH] drm: Separate EDID Header Check from EDID Block Check.
>
>    Tested for kernel 2.35, 2.38 and 3.0 on Asus M2A-VM HDMI board
>
> Signed-off-by: Thomas Reim <rdratlos@yahoo.co.uk>

Reviewed-by: Alex Deucher <alexdeucher@gmail.com>

> ---
>  drivers/gpu/drm/radeon/radeon_connectors.c |   45 ++++++++++++++++++++++++++--
>  drivers/gpu/drm/radeon/radeon_display.c    |    9 +++++
>  drivers/gpu/drm/radeon/radeon_i2c.c        |   32 +++++++++++++++-----
>  drivers/gpu/drm/radeon/radeon_mode.h       |    6 +++-
>  4 files changed, 80 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> index cbfca3a..2e70be2 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -424,6 +424,36 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr
>        return 0;
>  }
>
> +/*
> + * Some integrated ATI Radeon chipset implementations (e. g.
> + * Asus M2A-VM HDMI) may indicate the availability of a DDC,
> + * even when there's no monitor connected. For these connectors
> + * following DDC probe extension will be applied: check also for the
> + * availability of EDID with at least a correct EDID header. Only then,
> + * DDC is assumed to be available. This prevents drm_get_edid() and
> + * drm_edid_block_valid() from periodically dumping data and kernel
> + * errors into the logs and onto the terminal.
> + */
> +static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
> +                                    uint32_t supported_device,
> +                                    int connector_type)
> +{
> +       /* Asus M2A-VM HDMI board sends data to i2c bus even,
> +        * if HDMI add-on card is not plugged in or HDMI is disabled in
> +        * BIOS. Valid DDC can only be assumed, if also a valid EDID header
> +        * can be retrieved via i2c bus during DDC probe */
> +       if ((dev->pdev->device == 0x791e) &&
> +           (dev->pdev->subsystem_vendor == 0x1043) &&
> +           (dev->pdev->subsystem_device == 0x826d)) {
> +               if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
> +                   (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
> +                       return true;
> +       }
> +
> +       /* Default: no EDID header probe required for DDC probing */
> +       return false;
> +}
> +
>  static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
>                                          struct drm_connector *connector)
>  {
> @@ -655,7 +685,8 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
>                ret = connector_status_disconnected;
>
>        if (radeon_connector->ddc_bus)
> -               dret = radeon_ddc_probe(radeon_connector);
> +               dret = radeon_ddc_probe(radeon_connector,
> +                                       radeon_connector->requires_extended_probe);
>        if (dret) {
>                if (radeon_connector->edid) {
>                        kfree(radeon_connector->edid);
> @@ -827,7 +858,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
>        bool dret = false;
>
>        if (radeon_connector->ddc_bus)
> -               dret = radeon_ddc_probe(radeon_connector);
> +               dret = radeon_ddc_probe(radeon_connector,
> +                                       radeon_connector->requires_extended_probe);
>        if (dret) {
>                if (radeon_connector->edid) {
>                        kfree(radeon_connector->edid);
> @@ -1245,7 +1277,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
>                                if (radeon_dp_getdpcd(radeon_connector))
>                                        ret = connector_status_connected;
>                        } else {
> -                               if (radeon_ddc_probe(radeon_connector))
> +                               if (radeon_ddc_probe(radeon_connector,
> +                                                    radeon_connector->requires_extended_probe))
>                                        ret = connector_status_connected;
>                        }
>                }
> @@ -1400,6 +1433,9 @@ radeon_add_atom_connector(struct drm_device *dev,
>        radeon_connector->shared_ddc = shared_ddc;
>        radeon_connector->connector_object_id = connector_object_id;
>        radeon_connector->hpd = *hpd;
> +       radeon_connector->requires_extended_probe =
> +               radeon_connector_needs_extended_probe(rdev, supported_device,
> +                                                       connector_type);
>        radeon_connector->router = *router;
>        if (router->ddc_valid || router->cd_valid) {
>                radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
> @@ -1746,6 +1782,9 @@ radeon_add_legacy_connector(struct drm_device *dev,
>        radeon_connector->devices = supported_device;
>        radeon_connector->connector_object_id = connector_object_id;
>        radeon_connector->hpd = *hpd;
> +       radeon_connector->requires_extended_probe =
> +               radeon_connector_needs_extended_probe(rdev, supported_device,
> +                                                       connector_type);
>        switch (connector_type) {
>        case DRM_MODE_CONNECTOR_VGA:
>                drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index 292f73f..ed085ce 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -777,8 +777,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
>        if (!radeon_connector->ddc_bus)
>                return -1;
>        edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
> +       /* Log EDID retrieval status here. In particular with regard to
> +        * connectors with requires_extended_probe flag set, that will prevent
> +        * function radeon_dvi_detect() to fetch EDID on this connector,
> +        * as long as there is no valid EDID header found */
>        if (edid) {
> +               DRM_INFO("Radeon display connector %s: Found valid EDID",
> +                               drm_get_connector_name(connector));
>                kfree(edid);
> +       } else {
> +               DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
> +                               drm_get_connector_name(connector));
>        }
>        return ret;
>  }
> diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
> index 781196d..6c111c1 100644
> --- a/drivers/gpu/drm/radeon/radeon_i2c.c
> +++ b/drivers/gpu/drm/radeon/radeon_i2c.c
> @@ -32,17 +32,17 @@
>  * radeon_ddc_probe
>  *
>  */
> -bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
> +bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
>  {
> -       u8 out_buf[] = { 0x0, 0x0};
> -       u8 buf[2];
> +       u8 out = 0x0;
> +       u8 buf[8];
>        int ret;
>        struct i2c_msg msgs[] = {
>                {
>                        .addr = 0x50,
>                        .flags = 0,
>                        .len = 1,
> -                       .buf = out_buf,
> +                       .buf = &out,
>                },
>                {
>                        .addr = 0x50,
> @@ -52,15 +52,31 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
>                }
>        };
>
> +       /* Read 8 bytes from i2c for extended probe of EDID header */
> +       if (requires_extended_probe)
> +               msgs[1].len = 8;
> +
>        /* on hw with routers, select right port */
>        if (radeon_connector->router.ddc_valid)
>                radeon_router_select_ddc_port(radeon_connector);
>
>        ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
> -       if (ret == 2)
> -               return true;
> -
> -       return false;
> +       if (ret != 2)
> +               /* Couldn't find an accessible DDC on this connector */
> +               return false;
> +       if (requires_extended_probe) {
> +               /* Probe also for valid EDID header
> +                * EDID header starts with:
> +                * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
> +                * Only the first 6 bytes must be valid as
> +                * drm_edid_block_valid() can fix the last 2 bytes */
> +               if (drm_edid_header_is_valid(buf) < 6) {
> +                       /* Couldn't find an accessible EDID on this
> +                        * connector */
> +                       return false;
> +               }
> +       }
> +       return true;
>  }
>
>  /* bit banging i2c */
> diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
> index 6df4e3c..d09031c 100644
> --- a/drivers/gpu/drm/radeon/radeon_mode.h
> +++ b/drivers/gpu/drm/radeon/radeon_mode.h
> @@ -438,6 +438,9 @@ struct radeon_connector {
>        struct radeon_i2c_chan *ddc_bus;
>        /* some systems have an hdmi and vga port with a shared ddc line */
>        bool shared_ddc;
> +       /* for some Radeon chip families we apply an additional EDID header
> +          check as part of the DDC probe */
> +       bool requires_extended_probe;
>        bool use_digital;
>        /* we need to mind the EDID between detect
>           and get modes due to analog/digital/tvencoder */
> @@ -514,7 +517,8 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
>                                u8 val);
>  extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
>  extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
> -extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
> +extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector,
> +                       bool requires_extended_probe);
>  extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
>
>  extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
> --
> 1.7.1
>
>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH] drm/radeon: Fix ECS A740GM-M DVI-D EDID error flooding problem
  2011-07-06 23:30           ` reimth
@ 2011-07-20  8:34             ` reimth
  -1 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-07-20  8:34 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel, Stephen Michaels
  Cc: dri-devel, linux-kernel, Thomas Reim

From: Thomas Reim <reimth@gmail.com>

   ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
   for a DVI connector that is not implemented/existent on the board.

   Fix by applying extented DDC probing for this connector.

   Requires [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem

   BugLink: http://bugs.launchpad.net/bugs/810926

Signed-off-by: Thomas Reim <reimth@gmail.com>
---
 drivers/gpu/drm/radeon/radeon_connectors.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 2e70be2..82dacc6 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -449,6 +449,15 @@ static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
 		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
 			return true;
 	}
+	/* ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
+	 * for a DVI connector that is not implemented */
+	if ((dev->pdev->device == 0x796e) &&
+	    (dev->pdev->subsystem_vendor == 0x1019) &&
+	    (dev->pdev->subsystem_device == 0x2615)) {
+		if ((connector_type == DRM_MODE_CONNECTOR_DVID) &&
+		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
+			return true;
+	}
 
 	/* Default: no EDID header probe required for DDC probing */
 	return false;
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH] drm/radeon: Fix ECS A740GM-M DVI-D EDID error flooding problem
@ 2011-07-20  8:34             ` reimth
  0 siblings, 0 replies; 50+ messages in thread
From: reimth @ 2011-07-20  8:34 UTC (permalink / raw)
  To: Dave Airlie, Alex Deucher, Mario Kleiner, Jean Delvare, Tyson Whitehead
  Cc: dri-devel, linux-kernel, Thomas Reim

From: Thomas Reim <reimth@gmail.com>

   ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
   for a DVI connector that is not implemented/existent on the board.

   Fix by applying extented DDC probing for this connector.

   Requires [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem

   BugLink: http://bugs.launchpad.net/bugs/810926

Signed-off-by: Thomas Reim <reimth@gmail.com>
---
 drivers/gpu/drm/radeon/radeon_connectors.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 2e70be2..82dacc6 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -449,6 +449,15 @@ static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
 		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
 			return true;
 	}
+	/* ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
+	 * for a DVI connector that is not implemented */
+	if ((dev->pdev->device == 0x796e) &&
+	    (dev->pdev->subsystem_vendor == 0x1019) &&
+	    (dev->pdev->subsystem_device == 0x2615)) {
+		if ((connector_type == DRM_MODE_CONNECTOR_DVID) &&
+		    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
+			return true;
+	}
 
 	/* Default: no EDID header probe required for DDC probing */
 	return false;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCH] drm/radeon: Fix ECS A740GM-M DVI-D EDID error flooding problem
  2011-07-20  8:34             ` reimth
@ 2011-07-20 22:18               ` Thomas Reim
  -1 siblings, 0 replies; 50+ messages in thread
From: Thomas Reim @ 2011-07-20 22:18 UTC (permalink / raw)
  To: Stephen Michaels, Dave Airlie, Alex Deucher, Jean Delvare,
	Mario Kleiner, Jason Wessel, Tyson Whitehead
  Cc: dri-devel, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1967 bytes --]

Von: Stephen Micheals <stephen.micheals@gmail.com>
An: thomas.reim@nepomuc.de
Betreff: Re: [PATCH] drm/radeon: Fix ECS A740GM-M DVI-D EDID error
flooding problem
Datum: Wed, 20 Jul 2011 13:12:26 -0700

Acked-by: Stephen Michaels <Stephen.Micheals@gmail.com>

On Wed, Jul 20, 2011 at 1:34 AM,  <reimth@googlemail.com> wrote:
> From: Thomas Reim <reimth@gmail.com>
>
>   ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
>   for a DVI connector that is not implemented/existent on the board.
>
>   Fix by applying extented DDC probing for this connector.
>
>   Requires [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
>
>   BugLink: http://bugs.launchpad.net/bugs/810926
>
> Signed-off-by: Thomas Reim <reimth@gmail.com>
> ---
>  drivers/gpu/drm/radeon/radeon_connectors.c |    9 +++++++++
>  1 files changed, 9 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> index 2e70be2..82dacc6 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -449,6 +449,15 @@ static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
>                    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
>                        return true;
>        }
> +       /* ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
> +        * for a DVI connector that is not implemented */
> +       if ((dev->pdev->device == 0x796e) &&
> +           (dev->pdev->subsystem_vendor == 0x1019) &&
> +           (dev->pdev->subsystem_device == 0x2615)) {
> +               if ((connector_type == DRM_MODE_CONNECTOR_DVID) &&
> +                   (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
> +                       return true;
> +       }
>
>        /* Default: no EDID header probe required for DDC probing */
>        return false;
> --
> 1.7.1
>
>


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH] drm/radeon: Fix ECS A740GM-M DVI-D EDID error flooding problem
@ 2011-07-20 22:18               ` Thomas Reim
  0 siblings, 0 replies; 50+ messages in thread
From: Thomas Reim @ 2011-07-20 22:18 UTC (permalink / raw)
  To: Stephen Michaels, Dave Airlie, Alex Deucher, Jean Delvare, Mario Kleiner
  Cc: dri-devel, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1967 bytes --]

Von: Stephen Micheals <stephen.micheals@gmail.com>
An: thomas.reim@nepomuc.de
Betreff: Re: [PATCH] drm/radeon: Fix ECS A740GM-M DVI-D EDID error
flooding problem
Datum: Wed, 20 Jul 2011 13:12:26 -0700

Acked-by: Stephen Michaels <Stephen.Micheals@gmail.com>

On Wed, Jul 20, 2011 at 1:34 AM,  <reimth@googlemail.com> wrote:
> From: Thomas Reim <reimth@gmail.com>
>
>   ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
>   for a DVI connector that is not implemented/existent on the board.
>
>   Fix by applying extented DDC probing for this connector.
>
>   Requires [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
>
>   BugLink: http://bugs.launchpad.net/bugs/810926
>
> Signed-off-by: Thomas Reim <reimth@gmail.com>
> ---
>  drivers/gpu/drm/radeon/radeon_connectors.c |    9 +++++++++
>  1 files changed, 9 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> index 2e70be2..82dacc6 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -449,6 +449,15 @@ static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
>                    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
>                        return true;
>        }
> +       /* ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
> +        * for a DVI connector that is not implemented */
> +       if ((dev->pdev->device == 0x796e) &&
> +           (dev->pdev->subsystem_vendor == 0x1019) &&
> +           (dev->pdev->subsystem_device == 0x2615)) {
> +               if ((connector_type == DRM_MODE_CONNECTOR_DVID) &&
> +                   (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
> +                       return true;
> +       }
>
>        /* Default: no EDID header probe required for DDC probing */
>        return false;
> --
> 1.7.1
>
>


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH] drm/radeon: Fix ECS A740GM-M DVI-D EDID error flooding problem
  2011-07-20  8:34             ` reimth
  (?)
  (?)
@ 2011-07-26 13:05             ` Alex Deucher
  -1 siblings, 0 replies; 50+ messages in thread
From: Alex Deucher @ 2011-07-26 13:05 UTC (permalink / raw)
  To: reimth
  Cc: Dave Airlie, Mario Kleiner, Jean Delvare, Tyson Whitehead,
	Jason Wessel, Stephen Michaels, dri-devel, linux-kernel,
	Thomas Reim

On Wed, Jul 20, 2011 at 4:34 AM,  <reimth@googlemail.com> wrote:
> From: Thomas Reim <reimth@gmail.com>
>
>   ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
>   for a DVI connector that is not implemented/existent on the board.
>
>   Fix by applying extented DDC probing for this connector.
>
>   Requires [PATCH] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
>
>   BugLink: http://bugs.launchpad.net/bugs/810926
>
> Signed-off-by: Thomas Reim <reimth@gmail.com>

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>

> ---
>  drivers/gpu/drm/radeon/radeon_connectors.c |    9 +++++++++
>  1 files changed, 9 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
> index 2e70be2..82dacc6 100644
> --- a/drivers/gpu/drm/radeon/radeon_connectors.c
> +++ b/drivers/gpu/drm/radeon/radeon_connectors.c
> @@ -449,6 +449,15 @@ static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
>                    (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
>                        return true;
>        }
> +       /* ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
> +        * for a DVI connector that is not implemented */
> +       if ((dev->pdev->device == 0x796e) &&
> +           (dev->pdev->subsystem_vendor == 0x1019) &&
> +           (dev->pdev->subsystem_device == 0x2615)) {
> +               if ((connector_type == DRM_MODE_CONNECTOR_DVID) &&
> +                   (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
> +                       return true;
> +       }
>
>        /* Default: no EDID header probe required for DDC probing */
>        return false;
> --
> 1.7.1
>
>

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 2/3] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-07-07 14:01           ` Alex Deucher
@ 2011-07-26 13:20             ` Dave Airlie
  2011-07-26 14:52                 ` Alex Deucher
  0 siblings, 1 reply; 50+ messages in thread
From: Dave Airlie @ 2011-07-26 13:20 UTC (permalink / raw)
  To: Alex Deucher
  Cc: reimth, Dave Airlie, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel, dri-devel, linux-kernel, stable,
	Thomas Reim

On Thu, Jul 7, 2011 at 3:01 PM, Alex Deucher <alexdeucher@gmail.com> wrote:
> On Wed, Jul 6, 2011 at 7:30 PM,  <reimth@googlemail.com> wrote:
>> From: Thomas Reim <rdratlos@yahoo.co.uk>

Guys I really still hate this :-)

Other OSes must deal with this sort of thing and I can't say they
don't do it like this but I can't say for certain this feels like the
right answer.

My thinking is that we could probably just trust the hot plug detect
if its reported on HDMI and DVI-D connectors, we still need to poll
DVI-D as the VGA->DVI convertors don't often assert hpd.

Am I missing something that this wouldn't fix?

otherwise I''ll push these after another few reads.

Dave.

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 2/3] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-07-26 13:20             ` Dave Airlie
@ 2011-07-26 14:52                 ` Alex Deucher
  0 siblings, 0 replies; 50+ messages in thread
From: Alex Deucher @ 2011-07-26 14:52 UTC (permalink / raw)
  To: Dave Airlie
  Cc: reimth, Dave Airlie, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel, dri-devel, linux-kernel, stable,
	Thomas Reim

On Tue, Jul 26, 2011 at 9:20 AM, Dave Airlie <airlied@gmail.com> wrote:
> On Thu, Jul 7, 2011 at 3:01 PM, Alex Deucher <alexdeucher@gmail.com> wrote:
>> On Wed, Jul 6, 2011 at 7:30 PM,  <reimth@googlemail.com> wrote:
>>> From: Thomas Reim <rdratlos@yahoo.co.uk>
>
> Guys I really still hate this :-)
>
> Other OSes must deal with this sort of thing and I can't say they
> don't do it like this but I can't say for certain this feels like the
> right answer.
>

I emailed the closed driver display team, but as the issue seems to
only afflict certain rs690/rs740 boards, I'm not sure anyone will
remember what quirks those boards had as they are about 5 generations
old at this point.

> My thinking is that we could probably just trust the hot plug detect
> if its reported on HDMI and DVI-D connectors, we still need to poll
> DVI-D as the VGA->DVI convertors don't often assert hpd.
>
> Am I missing something that this wouldn't fix?

The issue in this case is that the problematic connectors don't have
HPD pin wired up and the ddc lines seem to be wired improperly so a
ddc probe always reports something connected unless you actually look
at the EDID header.  For DVI-I we probably have to poll since only the
digital portion will assert hpd in most cases.

Alex

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 2/3] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
@ 2011-07-26 14:52                 ` Alex Deucher
  0 siblings, 0 replies; 50+ messages in thread
From: Alex Deucher @ 2011-07-26 14:52 UTC (permalink / raw)
  To: Dave Airlie
  Cc: Tyson Whitehead, linux-kernel, dri-devel, reimth, Thomas Reim,
	Mario Kleiner, Jason Wessel, Jean Delvare, Dave Airlie, stable

On Tue, Jul 26, 2011 at 9:20 AM, Dave Airlie <airlied@gmail.com> wrote:
> On Thu, Jul 7, 2011 at 3:01 PM, Alex Deucher <alexdeucher@gmail.com> wrote:
>> On Wed, Jul 6, 2011 at 7:30 PM,  <reimth@googlemail.com> wrote:
>>> From: Thomas Reim <rdratlos@yahoo.co.uk>
>
> Guys I really still hate this :-)
>
> Other OSes must deal with this sort of thing and I can't say they
> don't do it like this but I can't say for certain this feels like the
> right answer.
>

I emailed the closed driver display team, but as the issue seems to
only afflict certain rs690/rs740 boards, I'm not sure anyone will
remember what quirks those boards had as they are about 5 generations
old at this point.

> My thinking is that we could probably just trust the hot plug detect
> if its reported on HDMI and DVI-D connectors, we still need to poll
> DVI-D as the VGA->DVI convertors don't often assert hpd.
>
> Am I missing something that this wouldn't fix?

The issue in this case is that the problematic connectors don't have
HPD pin wired up and the ddc lines seem to be wired improperly so a
ddc probe always reports something connected unless you actually look
at the EDID header.  For DVI-I we probably have to poll since only the
digital portion will assert hpd in most cases.

Alex

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 2/3] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem
  2011-07-26 14:52                 ` Alex Deucher
  (?)
@ 2011-07-26 14:55                 ` Alex Deucher
  -1 siblings, 0 replies; 50+ messages in thread
From: Alex Deucher @ 2011-07-26 14:55 UTC (permalink / raw)
  To: Dave Airlie
  Cc: reimth, Dave Airlie, Mario Kleiner, Jean Delvare,
	Tyson Whitehead, Jason Wessel, dri-devel, linux-kernel, stable,
	Thomas Reim

On Tue, Jul 26, 2011 at 10:52 AM, Alex Deucher <alexdeucher@gmail.com> wrote:
> On Tue, Jul 26, 2011 at 9:20 AM, Dave Airlie <airlied@gmail.com> wrote:
>> On Thu, Jul 7, 2011 at 3:01 PM, Alex Deucher <alexdeucher@gmail.com> wrote:
>>> On Wed, Jul 6, 2011 at 7:30 PM,  <reimth@googlemail.com> wrote:
>>>> From: Thomas Reim <rdratlos@yahoo.co.uk>
>>
>> Guys I really still hate this :-)
>>
>> Other OSes must deal with this sort of thing and I can't say they
>> don't do it like this but I can't say for certain this feels like the
>> right answer.
>>
>
> I emailed the closed driver display team, but as the issue seems to
> only afflict certain rs690/rs740 boards, I'm not sure anyone will
> remember what quirks those boards had as they are about 5 generations
> old at this point.

Another possibility is that the closed driver uses the hw i2c engine
which may not be affected, or they just tell the hw i2c engine to
fetch several bytes and they inspect the result similar to what this
patch does.  I'll let you know what I hear back.

>
>> My thinking is that we could probably just trust the hot plug detect
>> if its reported on HDMI and DVI-D connectors, we still need to poll
>> DVI-D as the VGA->DVI convertors don't often assert hpd.
>>
>> Am I missing something that this wouldn't fix?
>
> The issue in this case is that the problematic connectors don't have
> HPD pin wired up and the ddc lines seem to be wired improperly so a
> ddc probe always reports something connected unless you actually look
> at the EDID header.  For DVI-I we probably have to poll since only the
> digital portion will assert hpd in most cases.
>
> Alex
>

^ permalink raw reply	[flat|nested] 50+ messages in thread

end of thread, other threads:[~2011-07-26 14:55 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-21 15:31 [PATCH 1/1] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem Thomas Reim
2011-06-21 15:31 ` Thomas Reim
2011-06-21 15:37 ` Alex Deucher
2011-06-21 18:03   ` Thomas Reim
2011-06-21 19:27 ` Jean Delvare
2011-06-21 19:27   ` Jean Delvare
2011-06-22  1:11   ` Thomas Reim
2011-06-22 13:53     ` Jean Delvare
2011-06-22 13:53       ` Jean Delvare
2011-06-22  1:20 ` reimth
2011-06-22  1:20   ` reimth
2011-06-22  1:28   ` Alex Deucher
2011-06-22 15:17     ` Thomas Reim
2011-06-22 15:41       ` Alex Deucher
2011-06-22 15:45       ` Alex Deucher
2011-06-23 21:57         ` Thomas Reim
2011-06-23 22:05   ` [PATCH] " reimth
2011-06-23 22:05     ` reimth
2011-06-23 22:55     ` Alex Deucher
2011-06-24  4:02       ` Thomas Reim
2011-06-24 13:36         ` Alex Deucher
2011-06-27 12:14           ` Jean Delvare
2011-06-27 12:14             ` Jean Delvare
2011-07-06  9:35           ` Thomas Reim
2011-07-06 10:09     ` reimth
2011-07-06 10:09       ` reimth
2011-07-06 12:26       ` Thomas Reim
2011-07-06 15:39       ` Alex Deucher
2011-07-06 15:42         ` Alex Deucher
2011-07-06 23:30         ` [PATCH 0/3] " reimth
2011-07-06 23:30           ` reimth
2011-07-20  8:34           ` [PATCH] drm/radeon: Fix ECS A740GM-M DVI-D " reimth
2011-07-20  8:34             ` reimth
2011-07-20 22:18             ` Thomas Reim
2011-07-20 22:18               ` Thomas Reim
2011-07-26 13:05             ` Alex Deucher
2011-07-06 23:30         ` [PATCH 3/3] drm/radeon: Log Subsystem Vendor and Device Information reimth
2011-07-06 23:30           ` reimth
2011-07-07 13:56           ` Alex Deucher
2011-07-06 23:30         ` [PATCH 2/3] drm/radeon: Fix Asus M2A-VM HDMI EDID error flooding problem reimth
2011-07-06 23:30           ` reimth
2011-07-07 14:01           ` Alex Deucher
2011-07-26 13:20             ` Dave Airlie
2011-07-26 14:52               ` Alex Deucher
2011-07-26 14:52                 ` Alex Deucher
2011-07-26 14:55                 ` Alex Deucher
2011-07-06 23:30         ` [PATCH 1/3] drm: Separate EDID Header Check from EDID Block Check reimth
2011-07-06 23:30           ` reimth
2011-07-06 23:56           ` [stable] " Greg KH
2011-07-07 13:57           ` Alex Deucher

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.